ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

ustr.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/ustr.h"
00024 #include "common/memorypool.h"
00025 #include "common/util.h"
00026 
00027 namespace Common {
00028 
00029 extern MemoryPool *g_refCountPool;
00030 
00031 static uint32 computeCapacity(uint32 len) {
00032     // By default, for the capacity we use the next multiple of 32
00033     return ((len + 32 - 1) & ~0x1F);
00034 }
00035 
00036 U32String::U32String(const value_type *str) : _size(0), _str(_storage) {
00037     if (str == nullptr) {
00038         _storage[0] = 0;
00039         _size = 0;
00040     } else {
00041         uint32 len = 0;
00042         const value_type *s = str;
00043         while (*s++) {
00044             ++len;
00045         }
00046         initWithCStr(str, len);
00047     }
00048 }
00049 
00050 U32String::U32String(const value_type *str, uint32 len) : _size(0), _str(_storage) {
00051     initWithCStr(str, len);
00052 }
00053 
00054 U32String::U32String(const value_type *beginP, const value_type *endP) : _size(0), _str(_storage) {
00055     assert(endP >= beginP);
00056     initWithCStr(beginP, endP - beginP);
00057 }
00058 
00059 U32String::U32String(const U32String &str)
00060     : _size(str._size) {
00061     if (str.isStorageIntern()) {
00062         // String in internal storage: just copy it
00063         memcpy(_storage, str._storage, _builtinCapacity * sizeof(value_type));
00064         _str = _storage;
00065     } else {
00066         // String in external storage: use refcount mechanism
00067         str.incRefCount();
00068         _extern._refCount = str._extern._refCount;
00069         _extern._capacity = str._extern._capacity;
00070         _str = str._str;
00071     }
00072     assert(_str != nullptr);
00073 }
00074 
00075 U32String::U32String(const char *str) : _size(0), _str(_storage) {
00076     if (str == nullptr) {
00077         _storage[0] = 0;
00078         _size = 0;
00079     } else {
00080         initWithCStr(str, strlen(str));
00081     }
00082 }
00083 
00084 U32String::U32String(const char *str, uint32 len) : _size(0), _str(_storage) {
00085     initWithCStr(str, len);
00086 }
00087 
00088 U32String::U32String(const char *beginP, const char *endP) : _size(0), _str(_storage) {
00089     assert(endP >= beginP);
00090     initWithCStr(beginP, endP - beginP);
00091 }
00092 
00093 U32String::U32String(const String &str) : _size(0) {
00094     initWithCStr(str.c_str(), str.size());
00095 }
00096 
00097 U32String::~U32String() {
00098     decRefCount(_extern._refCount);
00099 }
00100 
00101 U32String &U32String::operator=(const U32String &str) {
00102     if (&str == this)
00103         return *this;
00104 
00105     if (str.isStorageIntern()) {
00106         decRefCount(_extern._refCount);
00107         _size = str._size;
00108         _str = _storage;
00109         memcpy(_str, str._str, (_size + 1) * sizeof(value_type));
00110     } else {
00111         str.incRefCount();
00112         decRefCount(_extern._refCount);
00113 
00114         _extern._refCount = str._extern._refCount;
00115         _extern._capacity = str._extern._capacity;
00116         _size = str._size;
00117         _str = str._str;
00118     }
00119 
00120     return *this;
00121 }
00122 
00123 U32String &U32String::operator=(const String &str) {
00124     initWithCStr(str.c_str(), str.size());
00125     return *this;
00126 }
00127 
00128 U32String &U32String::operator=(const value_type *str) {
00129     return U32String::operator=(U32String(str));
00130 }
00131 
00132 U32String &U32String::operator=(const char *str) {
00133     initWithCStr(str, strlen(str));
00134     return *this;
00135 }
00136 
00137 U32String &U32String::operator+=(const U32String &str) {
00138     if (&str == this) {
00139         return operator+=(U32String(str));
00140     }
00141 
00142     int len = str._size;
00143     if (len > 0) {
00144         ensureCapacity(_size + len, true);
00145 
00146         memcpy(_str + _size, str._str, (len + 1) * sizeof(value_type));
00147         _size += len;
00148     }
00149     return *this;
00150 }
00151 
00152 U32String &U32String::operator+=(value_type c) {
00153     ensureCapacity(_size + 1, true);
00154 
00155     _str[_size++] = c;
00156     _str[_size] = 0;
00157 
00158     return *this;
00159 }
00160 
00161 bool U32String::operator==(const U32String &x) const {
00162     return equals(x);
00163 }
00164 
00165 bool U32String::operator==(const String &x) const {
00166     return equals(x);
00167 }
00168 
00169 bool U32String::operator==(const value_type *x) const {
00170     return equals(U32String(x));
00171 }
00172 
00173 bool U32String::operator==(const char *x) const {
00174     return equals(x);
00175 }
00176 
00177 bool U32String::operator!=(const U32String &x) const {
00178     return !equals(x);
00179 }
00180 
00181 bool U32String::operator!=(const String &x) const {
00182     return !equals(x);
00183 }
00184 
00185 bool U32String::operator!=(const value_type *x) const {
00186     return !equals(U32String(x));
00187 }
00188 
00189 bool U32String::operator!=(const char *x) const {
00190     return !equals(x);
00191 }
00192 
00193 bool U32String::equals(const U32String &x) const {
00194     if (this == &x || _str == x._str) {
00195         return true;
00196     }
00197 
00198     if (x.size() != _size) {
00199         return false;
00200     }
00201 
00202     return !memcmp(_str, x._str, _size * sizeof(value_type));
00203 }
00204 
00205 bool U32String::equals(const String &x) const {
00206     if (x.size() != _size)
00207         return false;
00208 
00209     for (size_t idx = 0; idx < _size; ++idx)
00210         if (_str[idx] != x[idx])
00211             return false;
00212 
00213     return true;
00214 }
00215 
00216 bool U32String::contains(value_type x) const {
00217     for (uint32 i = 0; i < _size; ++i) {
00218         if (_str[i] == x) {
00219             return true;
00220         }
00221     }
00222 
00223     return false;
00224 }
00225 
00226 void U32String::deleteChar(uint32 p) {
00227     assert(p < _size);
00228 
00229     makeUnique();
00230     while (p++ < _size)
00231         _str[p - 1] = _str[p];
00232     _size--;
00233 }
00234 
00235 void U32String::clear() {
00236     decRefCount(_extern._refCount);
00237 
00238     _size = 0;
00239     _str = _storage;
00240     _storage[0] = 0;
00241 }
00242 
00243 void U32String::toLowercase() {
00244     makeUnique();
00245     for (uint32 i = 0; i < _size; ++i) {
00246         if (_str[i] < 128) {
00247             _str[i] = tolower(_str[i]);
00248         }
00249     }
00250 }
00251 
00252 void U32String::toUppercase() {
00253     makeUnique();
00254     for (uint32 i = 0; i < _size; ++i) {
00255         if (_str[i] < 128) {
00256             _str[i] = toupper(_str[i]);
00257         }
00258     }
00259 }
00260 
00261 uint32 U32String::find(const U32String &str, uint32 pos) const {
00262     if (pos >= _size) {
00263         return npos;
00264     }
00265 
00266     const value_type *strP = str.c_str();
00267 
00268     for (const_iterator cur = begin() + pos; *cur; ++cur) {
00269         uint i = 0;
00270         while (true) {
00271             if (!strP[i]) {
00272                 return cur - begin();
00273             }
00274 
00275             if (cur[i] != strP[i]) {
00276                 break;
00277             }
00278 
00279             ++i;
00280         }
00281     }
00282 
00283     return npos;
00284 }
00285 
00286 void U32String::makeUnique() {
00287     ensureCapacity(_size, true);
00288 }
00289 
00290 void U32String::ensureCapacity(uint32 new_size, bool keep_old) {
00291     bool isShared;
00292     uint32 curCapacity, newCapacity;
00293     value_type *newStorage;
00294     int *oldRefCount = _extern._refCount;
00295 
00296     if (isStorageIntern()) {
00297         isShared = false;
00298         curCapacity = _builtinCapacity;
00299     } else {
00300         isShared = (oldRefCount && *oldRefCount > 1);
00301         curCapacity = _extern._capacity;
00302     }
00303 
00304     // Special case: If there is enough space, and we do not share
00305     // the storage, then there is nothing to do.
00306     if (!isShared && new_size < curCapacity)
00307         return;
00308 
00309     if (isShared && new_size < _builtinCapacity) {
00310         // We share the storage, but there is enough internal storage: Use that.
00311         newStorage = _storage;
00312         newCapacity = _builtinCapacity;
00313     } else {
00314         // We need to allocate storage on the heap!
00315 
00316         // Compute a suitable new capacity limit
00317         // If the current capacity is sufficient we use the same capacity
00318         if (new_size < curCapacity)
00319             newCapacity = curCapacity;
00320         else
00321             newCapacity = MAX(curCapacity * 2, computeCapacity(new_size + 1));
00322 
00323         // Allocate new storage
00324         newStorage = new value_type[newCapacity];
00325         assert(newStorage);
00326     }
00327 
00328     // Copy old data if needed, elsewise reset the new storage.
00329     if (keep_old) {
00330         assert(_size < newCapacity);
00331         memcpy(newStorage, _str, (_size + 1) * sizeof(value_type));
00332     } else {
00333         _size = 0;
00334         newStorage[0] = 0;
00335     }
00336 
00337     // Release hold on the old storage ...
00338     decRefCount(oldRefCount);
00339 
00340     // ... in favor of the new storage
00341     _str = newStorage;
00342 
00343     if (!isStorageIntern()) {
00344         // Set the ref count & capacity if we use an external storage.
00345         // It is important to do this *after* copying any old content,
00346         // else we would override data that has not yet been copied!
00347         _extern._refCount = nullptr;
00348         _extern._capacity = newCapacity;
00349     }
00350 }
00351 
00352 void U32String::incRefCount() const {
00353     assert(!isStorageIntern());
00354     if (_extern._refCount == nullptr) {
00355         if (g_refCountPool == nullptr) {
00356             g_refCountPool = new MemoryPool(sizeof(int));
00357             assert(g_refCountPool);
00358         }
00359 
00360         _extern._refCount = (int *)g_refCountPool->allocChunk();
00361         *_extern._refCount = 2;
00362     } else {
00363         ++(*_extern._refCount);
00364     }
00365 }
00366 
00367 void U32String::decRefCount(int *oldRefCount) {
00368     if (isStorageIntern())
00369         return;
00370 
00371     if (oldRefCount) {
00372         --(*oldRefCount);
00373     }
00374     if (!oldRefCount || *oldRefCount <= 0) {
00375         // The ref count reached zero, so we free the string storage
00376         // and the ref count storage.
00377         if (oldRefCount) {
00378             assert(g_refCountPool);
00379             g_refCountPool->freeChunk(oldRefCount);
00380         }
00381         delete[] _str;
00382 
00383         // Even though _str points to a freed memory block now,
00384         // we do not change its value, because any code that calls
00385         // decRefCount will have to do this afterwards anyway.
00386     }
00387 }
00388 
00389 void U32String::initWithCStr(const value_type *str, uint32 len) {
00390     assert(str);
00391 
00392     _storage[0] = 0;
00393 
00394     _size = len;
00395 
00396     if (len >= _builtinCapacity) {
00397         // Not enough internal storage, so allocate more
00398         _extern._capacity = computeCapacity(len + 1);
00399         _extern._refCount = nullptr;
00400         _str = new value_type[_extern._capacity];
00401         assert(_str != nullptr);
00402     }
00403 
00404     // Copy the string into the storage area
00405     memmove(_str, str, len * sizeof(value_type));
00406     _str[len] = 0;
00407 }
00408 
00409 void U32String::initWithCStr(const char *str, uint32 len) {
00410     assert(str);
00411 
00412     _storage[0] = 0;
00413 
00414     _size = len;
00415 
00416     if (len >= _builtinCapacity) {
00417         // Not enough internal storage, so allocate more
00418         _extern._capacity = computeCapacity(len + 1);
00419         _extern._refCount = nullptr;
00420         _str = new value_type[_extern._capacity];
00421         assert(_str != nullptr);
00422     }
00423 
00424     // Copy the string into the storage area
00425     for (size_t idx = 0; idx < len; ++idx, ++str)
00426         _str[idx] = *str;
00427 
00428     _str[len] = 0;
00429 }
00430 
00431 // This is a quick and dirty converter.
00432 //
00433 // More comprehensive one lives in wintermute/utils/convert_utf.cpp
00434 U32String convertUtf8ToUtf32(const String &str) {
00435     // The String class, and therefore the Font class as well, assume one
00436     // character is one byte, but in this case it's actually an UTF-8
00437     // string with up to 4 bytes per character. To work around this,
00438     // convert it to an U32String before drawing it, because our Font class
00439     // can handle that.
00440     Common::U32String u32str;
00441     uint i = 0;
00442     while (i < str.size()) {
00443         uint32 chr = 0;
00444         if ((str[i] & 0xF8) == 0xF0) {
00445             chr |= (str[i++] & 0x07) << 18;
00446             chr |= (str[i++] & 0x3F) << 12;
00447             chr |= (str[i++] & 0x3F) << 6;
00448             chr |= (str[i++] & 0x3F);
00449         } else if ((str[i] & 0xF0) == 0xE0) {
00450             chr |= (str[i++] & 0x0F) << 12;
00451             chr |= (str[i++] & 0x3F) << 6;
00452             chr |= (str[i++] & 0x3F);
00453         } else if ((str[i] & 0xE0) == 0xC0) {
00454             chr |= (str[i++] & 0x1F) << 6;
00455             chr |= (str[i++] & 0x3F);
00456         } else {
00457             chr = (str[i++] & 0x7F);
00458         }
00459         u32str += chr;
00460     }
00461     return u32str;
00462 }
00463 
00464 static const uint32 g_windows1250ConversionTable[] = {0x20AC, 0x0081, 0x201A, 0x0083, 0x201E, 0x2026, 0x2020, 0x2021,
00465                                          0x0088, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
00466                                          0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
00467                                          0x0098, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
00468                                          0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
00469                                          0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
00470                                          0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
00471                                          0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
00472                                          0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
00473                                          0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
00474                                          0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
00475                                          0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
00476                                          0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
00477                                          0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
00478                                          0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
00479                                          0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9};
00480 
00481 static const uint32 g_windows1251ConversionTable[] = {0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
00482                                          0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
00483                                          0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
00484                                          0x0098, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
00485                                          0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
00486                                          0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
00487                                          0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
00488                                          0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
00489                                          0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
00490                                          0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
00491                                          0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
00492                                          0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
00493                                          0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
00494                                          0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
00495                                          0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
00496                                          0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F};
00497 
00498 static const uint32 g_windows1252ConversionTable[] = {0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
00499                                          0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008D, 0x017D, 0x008F,
00500                                          0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
00501                                          0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x009D, 0x017E, 0x0178,
00502                                          0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7,
00503                                          0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
00504                                          0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
00505                                          0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
00506                                          0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
00507                                          0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
00508                                          0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
00509                                          0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
00510                                          0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
00511                                          0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
00512                                          0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
00513                                          0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF};
00514 
00515 static const uint32 g_windows1255ConversionTable[] = {0x20AC, 0x0081, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
00516                                          0x02C6, 0x2030, 0x008A, 0x2039, 0x008C, 0x008D, 0x008E, 0x008F,
00517                                          0x0090, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
00518                                          0x02DC, 0x2122, 0x009A, 0x203A, 0x009C, 0x009D, 0x009E, 0x009F,
00519                                          0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7,
00520                                          0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF,
00521                                          0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
00522                                          0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF,
00523                                          0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,
00524                                          0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF,
00525                                          0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3,
00526                                          0x05F4, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
00527                                          0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
00528                                          0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
00529                                          0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
00530                                          0x05E8, 0x05E9, 0x05EA, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x00FF};
00531 
00532 U32String convertToU32String(const char *str, CodePage page) {
00533     const String string(str);
00534     if (page == kUtf8) {
00535         return convertUtf8ToUtf32(string);
00536     }
00537 
00538     U32String unicodeString;
00539     for (uint i = 0; i < string.size(); ++i) {
00540         if ((byte)string[i] <= 0x7F) {
00541             unicodeString += string[i];
00542             continue;
00543         }
00544 
00545         byte index = string[i] - 0x80;
00546 
00547         switch (page) {
00548         case kWindows1250:
00549             unicodeString += g_windows1250ConversionTable[index];
00550             break;
00551         case kWindows1251:
00552             unicodeString += g_windows1251ConversionTable[index];
00553             break;
00554         case kWindows1252:
00555             unicodeString += g_windows1252ConversionTable[index];
00556             break;
00557         case kWindows1255:
00558             unicodeString += g_windows1255ConversionTable[index];
00559             break;
00560         default:
00561             break;
00562         }
00563     }
00564     return unicodeString;
00565 }
00566 
00567 } // End of namespace Common


Generated on Sat May 18 2019 05:01:28 for ResidualVM by doxygen 1.7.1
curved edge   curved edge