~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/utf8/checked.h

  • Committer: Brian Aker
  • Date: 2009-12-06 01:55:53 UTC
  • mfrom: (1238.1.5 push)
  • Revision ID: brian@gaz-20091206015553-cva833q4gvwj11ob
Bundle for staging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
*/
26
26
 
27
27
 
28
 
 
29
28
#ifndef DRIZZLED_UTF8_CHECKED_H
30
29
#define DRIZZLED_UTF8_CHECKED_H
31
 
 
32
 
#include <drizzled/utf8/core.h>
 
30
 
 
31
#include "drizzled/utf8/core.h"
33
32
#include <stdexcept>
34
 
 
35
 
namespace drizzled
36
 
{
 
33
 
37
34
namespace utf8
38
35
{
39
 
    // Base for the exceptions that may be thrown from the library
40
 
    class exception : public std::exception {
41
 
    };
42
 
 
43
36
    // Exceptions that may be thrown from the library functions.
44
 
    class invalid_code_point : public exception {
 
37
    class invalid_code_point : public std::exception {
45
38
        uint32_t cp;
46
39
    public:
47
 
        invalid_code_point(uint32_t cp_in) : cp(cp_in) {}
 
40
        invalid_code_point(uint32_t cp) : cp(cp) {}
48
41
        virtual const char* what() const throw() { return "Invalid code point"; }
49
42
        uint32_t code_point() const {return cp;}
50
43
    };
51
44
 
52
 
    class invalid_utf8 : public exception {
 
45
    class invalid_utf8 : public std::exception {
53
46
        uint8_t u8;
54
47
    public:
55
48
        invalid_utf8 (uint8_t u) : u8(u) {}
57
50
        uint8_t utf8_octet() const {return u8;}
58
51
    };
59
52
 
60
 
    class invalid_utf16 : public exception {
 
53
    class invalid_utf16 : public std::exception {
61
54
        uint16_t u16;
62
55
    public:
63
56
        invalid_utf16 (uint16_t u) : u16(u) {}
65
58
        uint16_t utf16_word() const {return u16;}
66
59
    };
67
60
 
68
 
    class not_enough_room : public exception {
 
61
    class not_enough_room : public std::exception {
69
62
    public:
70
63
        virtual const char* what() const throw() { return "Not enough space"; }
71
64
    };
72
65
 
73
66
    /// The library API - functions intended to be called by the users
74
 
 
 
67
 
75
68
    template <typename octet_iterator, typename output_iterator>
76
69
    output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
77
70
    {
79
72
            octet_iterator sequence_start = start;
80
73
            internal::utf_error err_code = internal::validate_next(start, end);
81
74
            switch (err_code) {
82
 
                case internal::UTF8_OK :
 
75
                case internal::OK :
83
76
                    for (octet_iterator it = sequence_start; it != start; ++it)
84
77
                        *out++ = *it;
85
78
                    break;
99
92
                        ++start;
100
93
                    break;
101
94
            }
102
 
        }
 
95
        }   
103
96
        return out;
104
97
    }
105
98
 
113
106
    template <typename octet_iterator>
114
107
    octet_iterator append(uint32_t cp, octet_iterator result)
115
108
    {
116
 
        if (!internal::is_code_point_valid(cp))
 
109
        if (!internal::is_code_point_valid(cp)) 
117
110
            throw invalid_code_point(cp);
118
111
 
119
112
        if (cp < 0x80)                        // one octet
120
 
            *(result++) = static_cast<uint8_t>(cp);
 
113
            *(result++) = static_cast<uint8_t>(cp);  
121
114
        else if (cp < 0x800) {                // two octets
122
115
            *(result++) = static_cast<uint8_t>((cp >> 6)            | 0xc0);
123
116
            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80);
124
117
        }
125
118
        else if (cp < 0x10000) {              // three octets
126
119
            *(result++) = static_cast<uint8_t>((cp >> 12)           | 0xe0);
127
 
            *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f)   | 0x80);
 
120
            *(result++) = static_cast<uint8_t>((cp >> 6) & 0x3f     | 0x80);
128
121
            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80);
129
122
        }
130
 
        else {      // four octets
 
123
        else if (cp <= internal::CODE_POINT_MAX) {      // four octets
131
124
            *(result++) = static_cast<uint8_t>((cp >> 18)           | 0xf0);
132
 
            *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)  | 0x80);
133
 
            *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f)   | 0x80);
 
125
            *(result++) = static_cast<uint8_t>((cp >> 12)& 0x3f     | 0x80);
 
126
            *(result++) = static_cast<uint8_t>((cp >> 6) & 0x3f     | 0x80);
134
127
            *(result++) = static_cast<uint8_t>((cp & 0x3f)          | 0x80);
135
128
        }
 
129
        else
 
130
            throw invalid_code_point(cp);
 
131
 
136
132
        return result;
137
133
    }
138
134
 
142
138
        uint32_t cp = 0;
143
139
        internal::utf_error err_code = internal::validate_next(it, end, &cp);
144
140
        switch (err_code) {
145
 
            case internal::UTF8_OK :
 
141
            case internal::OK :
146
142
                break;
147
143
            case internal::NOT_ENOUGH_ROOM :
148
144
                throw not_enough_room();
153
149
            case internal::INVALID_CODE_POINT :
154
150
                throw invalid_code_point(cp);
155
151
        }
156
 
        return cp;
 
152
        return cp;        
157
153
    }
158
154
 
159
155
    template <typename octet_iterator>
166
162
    uint32_t prior(octet_iterator& it, octet_iterator start)
167
163
    {
168
164
        octet_iterator end = it;
169
 
        while (internal::is_trail(*(--it)))
 
165
        while (internal::is_trail(*(--it))) 
170
166
            if (it < start)
171
167
                throw invalid_utf8(*it); // error - no lead byte in the sequence
172
168
        octet_iterator temp = it;
178
174
    uint32_t previous(octet_iterator& it, octet_iterator pass_start)
179
175
    {
180
176
        octet_iterator end = it;
181
 
        while (internal::is_trail(*(--it)))
 
177
        while (internal::is_trail(*(--it))) 
182
178
            if (it == pass_start)
183
179
                throw invalid_utf8(*it); // error - no lead byte in the sequence
184
180
        octet_iterator temp = it;
197
193
    distance (octet_iterator first, octet_iterator last)
198
194
    {
199
195
        typename std::iterator_traits<octet_iterator>::difference_type dist;
200
 
        for (dist = 0; first < last; ++dist)
 
196
        for (dist = 0; first < last; ++dist) 
201
197
            next(first, last);
202
198
        return dist;
203
199
    }
204
200
 
205
201
    template <typename u16bit_iterator, typename octet_iterator>
206
202
    octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
207
 
    {
 
203
    {       
208
204
        while (start != end) {
209
205
            uint32_t cp = internal::mask16(*start++);
210
206
            // Take care of surrogate pairs first
211
 
            if (internal::is_lead_surrogate(cp)) {
 
207
            if (internal::is_surrogate(cp)) {
212
208
                if (start != end) {
213
209
                    uint32_t trail_surrogate = internal::mask16(*start++);
214
 
                    if (internal::is_trail_surrogate(trail_surrogate))
215
 
                        cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
216
 
                    else
 
210
                    if (trail_surrogate >= internal::TRAIL_SURROGATE_MIN && trail_surrogate <= internal::TRAIL_SURROGATE_MAX)
 
211
                        cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;                    
 
212
                    else 
217
213
                        throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
218
214
                }
219
 
                else
220
 
                    throw invalid_utf16(static_cast<uint16_t>(cp));
221
 
 
 
215
                else 
 
216
                    throw invalid_utf16(static_cast<uint16_t>(*start));
 
217
            
222
218
            }
223
 
            // Lone trail surrogate
224
 
            else if (internal::is_trail_surrogate(cp))
225
 
                throw invalid_utf16(static_cast<uint16_t>(cp));
226
 
 
227
219
            result = append(cp, result);
228
220
        }
229
 
        return result;
 
221
        return result;        
230
222
    }
231
223
 
232
224
    template <typename u16bit_iterator, typename octet_iterator>
256
248
    template <typename octet_iterator, typename u32bit_iterator>
257
249
    u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
258
250
    {
259
 
        while (start != end)
 
251
        while (start < end)
260
252
            (*result++) = next(start, end);
261
253
 
262
254
        return result;
264
256
 
265
257
    // The iterator class
266
258
    template <typename octet_iterator>
267
 
    class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
 
259
    class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> { 
268
260
      octet_iterator it;
269
261
      octet_iterator range_start;
270
262
      octet_iterator range_end;
271
263
      public:
272
264
      iterator () {};
273
 
      explicit iterator (const octet_iterator& octet_it,
274
 
                         const octet_iterator& range_start_in,
275
 
                         const octet_iterator& range_end_in) :
276
 
               it(octet_it), range_start(range_start_in), range_end(range_end_in)
 
265
      explicit iterator (const octet_iterator& octet_it, 
 
266
                         const octet_iterator& range_start,
 
267
                         const octet_iterator& range_end) :
 
268
               it(octet_it), range_start(range_start), range_end(range_end)
277
269
      {
278
270
          if (it < range_start || it > range_end)
279
271
              throw std::out_of_range("Invalid utf-8 iterator position");
285
277
          octet_iterator temp = it;
286
278
          return next(temp, range_end);
287
279
      }
288
 
      bool operator == (const iterator& rhs) const
289
 
      {
 
280
      bool operator == (const iterator& rhs) const 
 
281
      { 
290
282
          if (range_start != rhs.range_start || range_end != rhs.range_end)
291
283
              throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
292
284
          return (it == rhs.it);
295
287
      {
296
288
          return !(operator == (rhs));
297
289
      }
298
 
      iterator& operator ++ ()
 
290
      iterator& operator ++ () 
299
291
      {
300
292
          next(it, range_end);
301
293
          return *this;
305
297
          iterator temp = *this;
306
298
          next(it, range_end);
307
299
          return temp;
308
 
      }
 
300
      }  
309
301
      iterator& operator -- ()
310
302
      {
311
303
          prior(it, range_start);
320
312
    }; // class iterator
321
313
 
322
314
} // namespace utf8
323
 
} // namespace drizzled
324
315
 
325
316
#endif /* DRIZZLED_UTF8_CHECKED_H */
326
317