root/OpenSceneGraph/trunk/src/osgText/String.cpp @ 13041

Revision 13041, 9.1 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osgText/String>
2
3#include <osg/Notify>
4#include <osg/Math>
5
6#include <iterator>
7
8using namespace osgText;
9
10////////////////////////////////////////////////////////////////////////
11//
12// helper class to make it safer to query std::string's for encoding.
13//
14struct look_ahead_iterator
15{
16    look_ahead_iterator(const std::string& string):
17        _string(string),
18        _index(0),
19        _nullCharacter(0) {}
20
21    bool valid() const { return _index<_string.length(); }
22
23    look_ahead_iterator& operator ++ ()
24    {
25        if (_index<_string.length()) ++_index;
26        return *this;
27    }
28
29    look_ahead_iterator operator ++ (int)
30    {
31        look_ahead_iterator tmp(*this);
32        if (_index<_string.length()) ++_index;
33        return tmp;
34    }
35
36    look_ahead_iterator& operator += (int offset)
37    {
38        if (_index<_string.length()) _index = osg::minimum((unsigned int)(_index+offset),(unsigned int)_string.length());
39        return *this;
40    }
41
42    unsigned char operator * () const
43    {
44        if (_index<_string.length()) return _string[_index];
45        else return _nullCharacter;
46    }
47
48    unsigned char operator [] (unsigned int offset) const
49    {
50
51        if (_index+offset<_string.length()) return _string[_index+offset];
52        else return _nullCharacter;
53    }
54
55
56    const std::string&      _string;
57    unsigned int            _index;
58    unsigned char           _nullCharacter;
59
60protected:
61
62    look_ahead_iterator& operator = (const look_ahead_iterator&) { return *this; }
63};
64
65String::Encoding findEncoding(look_ahead_iterator& charString,String::Encoding overrideEncoding)
66{
67    switch (charString[0])
68    {
69        case 0xEF: // 8-bit encoding
70        {
71            // 8-bit signature = EF BB BF
72            if ((charString[1]==0xBB) && (charString[2]==0xBF))
73            {
74                charString+=3;
75                return String::ENCODING_UTF8;
76            }
77            break;
78        }
79        case 0xFE: // big-endian 16-bit
80        {
81            // 16-bit signature = FE FF
82            if (charString[1]==0xFF)
83            {
84                charString+=2;
85                return String::ENCODING_UTF16_BE;
86            }
87            break;
88        }
89        case 0xFF: // little-endian
90        {
91            // 16-bit signature = FF FE
92            // 32-bit signature = FF FE 00 00
93            if (charString[1]==0xFE)
94            {
95                // NOTE: There is an a potential problem as a 16-bit empty string
96                // is identical to a 32-bit start signature
97                if ((charString[2]==0) && (charString[3]==0) && (overrideEncoding != String::ENCODING_UTF16)) //32-bit
98                {
99                    charString+=4;
100                    return String::ENCODING_UTF32_LE;
101                }
102                else //16-bit
103                {
104                    charString+=2;
105                    return String::ENCODING_UTF16_LE;
106                }
107            }
108            break;
109        }
110        case 0x00: // 32-bit big-endian
111        {
112            // 32-bit signature = 00 00 FE FF
113            if ((charString[1]==0x00) && (charString[2]==0xFE) && (charString[3]==0xFF))
114            {
115                charString+=4;
116                return String::ENCODING_UTF32_BE;
117            }
118            break;
119        }
120    }
121    return String::ENCODING_ASCII;
122}
123
124
125unsigned int getNextCharacter(look_ahead_iterator& charString,String::Encoding encoding)
126{
127    // For more info on unicode encodings see:
128    // http://www-106.ibm.com/developerworks/unicode/library/u-encode.html
129    switch(encoding)
130    {
131        case String::ENCODING_ASCII:
132        {
133            return *charString++;
134        }
135        case String::ENCODING_UTF8:
136        {
137            int char0 = *charString++;
138            if (char0 < 0x80) // 1-byte character
139            {
140                return char0;
141            }
142            int char1 = *charString++;
143            if (char0<0xe0) // 2-byte character
144            {
145                return ((char0&0x1f)<<6) | (char1&0x3f);
146            }
147            int char2 = *charString++;
148            if (char0<0xf0) // 3-byte character
149            {
150                return ((char0&0xf)<<12) | ((char1&0x3f)<<6) | (char2&0x3f);
151            }
152            int char3 = *charString++;
153            if (char0<0xf8) // 4-byte character
154            {
155                return ((char0&0x7)<<18) | ((char1&0x3f)<<12) | ((char2&0x3f)<<6) | (char3&0x3f);
156            }
157            break;
158        }
159        case String::ENCODING_UTF16_BE:
160        {
161            int char0 = *charString++;
162            int char1 = *charString++;
163            if ((char0<=0xD7) || (char0>=0xE0)) // simple character
164            {
165                return (char0<<8) | char1;
166            }
167            else if ((char0>=0xD8)&&(char0<=0xDB)) //using planes (this should get called very rarely)
168            {
169                int char2 = *charString++;
170                int char3 = *charString++;
171                int highSurrogate = (char0<<8) | char1;
172                int lowSurrogate = (char2<<8) | char3;
173                if ((char2>=0xDC)&&(char2<=0xDF)) //only for the valid range of low surrogate
174                {
175                    // This covers the range of all 17 unicode planes
176                    return ((highSurrogate-0xD800)*0x400) + (lowSurrogate-0xD800) + 0x10000;
177                }
178            }
179            break;
180        }
181        case String::ENCODING_UTF16_LE:
182        {
183            int char1 = *charString++;
184            int char0 = *charString++;
185            if ((char0<=0xD7) || (char0>=0xE0)) // simple character
186            {
187                return (char0<<8) | char1;
188            }
189            else if ((char0>=0xD8)&&(char0<=0xDB)) //using planes (this should get called very rarely)
190            {
191                int char3 = *charString++;
192                int char2 = *charString++;
193                int highSurrogate = (char0<<8) | char1;
194                int lowSurrogate = (char2<<8) | char3;
195                if ((char2>=0xDC)&&(char2<=0xDF)) //only for the valid range of low surrogate
196                {
197                    // This covers the range of all 17 unicode planes
198                    return ((highSurrogate-0xD800)*0x400) + (lowSurrogate-0xD800) + 0x10000;
199                }
200            }
201            break;
202        }
203        case String::ENCODING_UTF32_BE:
204        {
205            int character = ((((int)charString[0])<<24) | (((int)charString[1])<<16) |
206                            (((int)charString[2])<<8) | charString[3]);
207            charString+=4;
208            if (character<0x110000)
209            {
210                // Character is constrained to the range set by the unicode standard
211                return character;
212            }
213            break;
214        }
215        case String::ENCODING_UTF32_LE:
216        {
217            int character = ((((int)charString[3])<<24) | (((int)charString[2])<<16) |
218                            (((int)charString[1])<<8) | charString[0]);
219            charString+=4;
220            if (character<0x110000)
221            {
222                // Character is constrained to the range set by the unicode standard
223                return character;
224            }
225            break;
226        }
227        default:
228        {
229            // Should not reach this point unless the encoding is unhandled
230            // ENCODING_UTF16, ENCODING_UTF32 and ENCODING_SIGNATURE should never enter this method
231            OSG_FATAL<<"Error: Invalid string encoding"<<std::endl;
232            break;
233        }
234    }
235    return 0;
236}
237
238
239////////////////////////////////////////////////////////////////////////////
240//
241// String implemention.
242//
243
244String::String(const String& str):
245    vector_type(str)
246{
247}
248
249String& String::operator = (const String& str)
250{
251    if (&str==this) return *this;
252
253    clear();
254    std::copy(str.begin(),str.end(),std::back_inserter(*this));
255
256    return *this;
257}
258
259void String::set(const std::string& text)
260{
261    clear();
262    for ( std::string::const_iterator it = text.begin(); it != text.end(); ++it )
263    {
264        unsigned int charcode = (unsigned char )*it;
265        push_back( charcode );
266    }
267}
268
269void String::set(const wchar_t* text)
270{
271    clear();
272    while(*text)
273    {
274        push_back(*text++);
275    }
276}
277
278void String::set(const std::string& text,Encoding encoding)
279{
280    clear();
281
282    look_ahead_iterator itr(text);
283
284    if ((encoding == ENCODING_SIGNATURE) ||
285        (encoding == ENCODING_UTF16) ||
286        (encoding == ENCODING_UTF32))
287    {
288        encoding = findEncoding(itr,encoding);
289    }
290
291    while(itr.valid())
292    {
293        unsigned int c = getNextCharacter(itr,encoding);
294        if (c) push_back(c);
295    }
296}
297
298std::string String::createUTF8EncodedString() const
299{
300    std::string utf8string;
301    for(const_iterator itr=begin();
302        itr!=end();
303        ++itr)
304    {
305        unsigned int currentChar = *itr;
306        if (currentChar < 0x80)
307        {
308            utf8string+=(char)currentChar;
309        }
310        else if (currentChar < 0x800)
311        {
312            utf8string+=(char)(0xc0 | (currentChar>>6));
313            utf8string+=(char)(0x80 | (currentChar & 0x3f));
314        }
315        else
316        {
317            utf8string+=(char)(0xe0 | (currentChar>>12));
318            utf8string+=(char)(0x80 | ((currentChar>>6) & 0x3f));
319            utf8string+=(char)(0x80 | (currentChar & 0x3f));
320        }
321    }
322    return utf8string;
323}
Note: See TracBrowser for help on using the browser.