~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/utf8/checked.h

  • Committer: Brian Aker
  • Date: 2011-01-06 05:17:09 UTC
  • Revision ID: brian@tangent.org-20110106051709-oa0se8ur02uc6i9o
Added native functions into the function table.

Show diffs side-by-side

added added

removed removed

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