~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/utf8/checked.h

  • Committer: Brian Aker
  • Date: 2009-10-15 00:22:33 UTC
  • mto: (1183.1.11 merge)
  • mto: This revision was merged to the branch mainline in revision 1198.
  • Revision ID: brian@gaz-20091015002233-fa4ao2mbc67wls91
First pass of information engine. OMG, ponies... is it so much easier to
deal with creating and engine.

The list table iterator though... its ass, needs to go. We should also
abstract out share. Very few engines need a custom one. Just say'in

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
*/
26
26
 
27
27
 
28
 
 
29
 
#ifndef DRIZZLED_UTF8_CHECKED_H
30
 
#define DRIZZLED_UTF8_CHECKED_H
31
 
 
 
28
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
 
29
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
 
30
 
32
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
 
#endif /* DRIZZLED_UTF8_CHECKED_H */
 
316
#endif //header guard
326
317
 
327
318