1 /** \file lvstring.h
2 \brief string classes interface
3
4 CoolReader Engine
5
6 (c) Vadim Lopatin, 2000-2006
7 This source code is distributed under the terms of
8 GNU General Public License.
9
10 See LICENSE file for details.
11 */
12
13 #ifndef __LV_STRING_H_INCLUDED__
14 #define __LV_STRING_H_INCLUDED__
15
16 #include <stdlib.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include "lvtypes.h"
20 #include "lvmemman.h"
21
22 // (Note: some of these 0x have lowercase hex digit, to avoid
23 // 'redefined' warnings as they are already defined in lowercase
24 // in antiword/wordconst.h.)
25
26 /// Unicode spaces
27 #define UNICODE_NO_BREAK_SPACE 0x00A0
28 #define UNICODE_ZERO_WIDTH_NO_BREAK_SPACE 0xfeff
29 #define UNICODE_WORD_JOINER 0x2060
30 // All chars from U+2000 to U+200B allow wrap after, except U+2007
31 #define UNICODE_EN_QUAD 0x2000
32 #define UNICODE_FIGURE_SPACE 0x2007
33 #define UNICODE_ZERO_WIDTH_SPACE 0x200b
34
35 #ifdef USE_ATOMIC_REFCOUNT
36 #include <atomic>
37 #endif
38 /// Unicode hyphens
39 #define UNICODE_SOFT_HYPHEN_CODE 0x00AD
40 #define UNICODE_ARMENIAN_HYPHEN 0x058A
41 // All chars from U+2010 to U+2014 allow deprecated wrap after, except U+2011
42 #define UNICODE_HYPHEN 0x2010
43 #define UNICODE_NO_BREAK_HYPHEN 0x2011
44 #define UNICODE_EM_DASH 0x2014
45
46 // Punctuation and CJK ranges
47 #define UNICODE_GENERAL_PUNCTUATION_BEGIN 0x2000
48 #define UNICODE_GENERAL_PUNCTUATION_END 0x206F
49 #define UNICODE_CJK_IDEOGRAPHS_BEGIN 0x3041
50 #define UNICODE_CJK_IDEOGRAPHS_END 0x02CEAF
51 #define UNICODE_CJK_IDEOGRAPHIC_SPACE 0x3000
52 #define UNICODE_CJK_PUNCTUATION_BEGIN 0x3000
53 #define UNICODE_CJK_PUNCTUATION_END 0x303F
54 // These may be wrong as this block contain katakana and hangul
55 // letters, as well as ascii full-width chars:
56 #define UNICODE_CJK_PUNCTUATION_HALF_AND_FULL_WIDTH_BEGIN 0xFF01
57 #define UNICODE_CJK_PUNCTUATION_HALF_AND_FULL_WIDTH_END 0xFFEE
58
59 #define UNICODE_ASCII_FULL_WIDTH_BEGIN 0xFF01
60 #define UNICODE_ASCII_FULL_WIDTH_END 0xFF5E
61 #define UNICODE_ASCII_FULL_WIDTH_OFFSET 0xFEE0 // substract or add to convert to/from ASCII
62
63
64 /// strlen for lChar16
65 int lStr_len(const lChar16 * str);
66 /// strlen for lChar32
67 int lStr_len(const lChar32 * str);
68 /// strlen for lChar8
69 int lStr_len(const lChar8 * str);
70 /// strnlen for lChar16
71 int lStr_nlen(const lChar16 * str, int maxcount);
72 /// strnlen for lChar32
73 int lStr_nlen(const lChar32 * str, int maxcount);
74 /// strnlen for lChar8
75 int lStr_nlen(const lChar8 * str, int maxcount);
76 /// strcpy for lChar16
77 int lStr_cpy(lChar16 * dst, const lChar16 * src);
78 /// strcpy for lChar32
79 int lStr_cpy(lChar32 * dst, const lChar32 * src);
80 /// strcpy for lChar16 -> lChar8
81 int lStr_cpy(lChar16 * dst, const lChar8 * src);
82 /// strcpy for lChar32 -> lChar8
83 int lStr_cpy(lChar32 * dst, const lChar8 * src);
84 /// strcpy for lChar8
85 int lStr_cpy(lChar8 * dst, const lChar8 * src);
86 /// strncpy for lChar16
87 int lStr_ncpy(lChar16 * dst, const lChar16 * src, int maxcount);
88 /// strncpy for lChar32
89 int lStr_ncpy(lChar32 * dst, const lChar32 * src, int maxcount);
90 /// strncpy for lChar8
91 int lStr_ncpy(lChar8 * dst, const lChar8 * src, int maxcount);
92 /// memcpy for lChar16
93 void lStr_memcpy(lChar16 * dst, const lChar16 * src, int count);
94 /// memcpy for lChar32
95 void lStr_memcpy(lChar32 * dst, const lChar32 * src, int count);
96 /// memcpy for lChar8
97 void lStr_memcpy(lChar8 * dst, const lChar8 * src, int count);
98 /// memset for lChar16
99 void lStr_memset(lChar16 * dst, lChar16 value, int count);
100 /// memset for lChar32
101 void lStr_memset(lChar32 * dst, lChar32 value, int count);
102 /// memset for lChar8
103 void lStr_memset(lChar8 * dst, lChar8 value, int count);
104 /// strcmp for lChar16
105 int lStr_cmp(const lChar16 * str1, const lChar16 * str2);
106 /// strcmp for lChar32
107 int lStr_cmp(const lChar32 * str1, const lChar32 * str2);
108 /// strcmp for lChar32 <> lChar8
109 int lStr_cmp(const lChar32 * str1, const lChar8 * str2);
110 /// strcmp for lChar16 <> lChar8
111 int lStr_cmp(const lChar16 * str1, const lChar8 * str2);
112 /// strcmp for lChar8 <> lChar16
113 int lStr_cmp(const lChar8 * str1, const lChar16 * str2);
114 /// strcmp for lChar16 <> lChar32
115 int lStr_cmp(const lChar16 * str1, const lChar32 * str2);
116 /// strcmp for lChar8 <> lChar32
117 int lStr_cmp(const lChar8 * str1, const lChar32 * str2);
118 /// strcmp for lChar32 <> lChar16
119 int lStr_cmp(const lChar32 * str1, const lChar16 * str2);
120 /// strcmp for lChar8
121 int lStr_cmp(const lChar8 * str1, const lChar8 * str2);
122 /// convert string to uppercase
123 void lStr_uppercase( lChar8 * str, int len );
124 /// convert string to lowercase
125 void lStr_lowercase( lChar8 * str, int len );
126 /// convert string to uppercase
127 void lStr_uppercase( lChar32 * str, int len );
128 /// convert string to lowercase
129 void lStr_lowercase( lChar32 * str, int len );
130 /// convert string to be capitalized
131 void lStr_capitalize( lChar32 * str, int len );
132 /// convert string to use full width chars
133 void lStr_fullWidthChars( lChar32 * str, int len );
134 /// calculates CRC32 for buffer contents
135 lUInt32 lStr_crc32( lUInt32 prevValue, const void * buf, int size );
136
137 // converts 0..15 to 0..f
138 char toHexDigit( int c );
139 // returns 0..15 if c is hex digit, -1 otherwise
140 int hexDigit( int c );
141 // decode LEN hex digits, return decoded number, -1 if invalid
142 int decodeHex( const lChar32 * str, int len );
143 // decode LEN decimal digits, return decoded number, -1 if invalid
144 int decodeDecimal( const lChar32 * str, int len );
145
146
147 #define CH_PROP_UPPER 0x0001 ///< uppercase alpha character flag
148 #define CH_PROP_LOWER 0x0002 ///< lowercase alpha character flag
149 #define CH_PROP_ALPHA 0x0003 ///< alpha flag is combination of uppercase and lowercase flags
150 #define CH_PROP_DIGIT 0x0004 ///< digit character flag
151 #define CH_PROP_PUNCT 0x0008 ///< pubctuation character flag
152 #define CH_PROP_SPACE 0x0010 ///< space character flag
153 #define CH_PROP_HYPHEN 0x0020 ///< hyphenation character flag
154 #define CH_PROP_VOWEL 0x0040 ///< vowel character flag
155 #define CH_PROP_CONSONANT 0x0080 ///< consonant character flag
156 #define CH_PROP_SIGN 0x0100 ///< sign character flag
157 #define CH_PROP_ALPHA_SIGN 0x0200 ///< alpha sign character flag
158 #define CH_PROP_DASH 0x0400 ///< minus, emdash, endash, ... (- signs)
159 #define CH_PROP_CJK 0x0800 ///< CJK ideographs
160 #define CH_PROP_AVOID_WRAP_AFTER 0x1000 ///< avoid wrap on following space
161 #define CH_PROP_AVOID_WRAP_BEFORE 0x2000 ///< avoid wrap on preceding space
162
163 /// retrieve character properties mask array for wide c-string
164 void lStr_getCharProps( const lChar32 * str, int sz, lUInt16 * props );
165 /// retrieve character properties mask for single wide character
166 lUInt16 lGetCharProps( lChar32 ch );
167 /// find alpha sequence bounds
168 void lStr_findWordBounds( const lChar32 * str, int sz, int pos, int & start, int & end );
169 // is char a word separator
170 bool lStr_isWordSeparator( lChar32 ch );
171
172
173 // must be power of 2
174 #define CONST_STRING_BUFFER_SIZE 4096
175 #define CONST_STRING_BUFFER_MASK (CONST_STRING_BUFFER_SIZE - 1)
176 #define CONST_STRING_BUFFER_HASH_MULT 31
177
178
179 struct lstring8_chunk_t {
180 friend class lString8;
181 friend class lString32;
182 friend struct lstring_chunk_slice_t;
183 public:
lstring8_chunk_tlstring8_chunk_t184 lstring8_chunk_t(lChar8 * _buf8) : buf8(_buf8), size(1), len(0)
185 {
186 refCount = 1;
187 }
data8lstring8_chunk_t188 const lChar8 * data8() const { return buf8; }
189 private:
190 lChar8 * buf8; // z-string
191 lInt32 size; // 0 for free chunk
192 lInt32 len; // count of chars in string
193 #ifdef USE_ATOMIC_REFCOUNT
194 std::atomic_int refCount; // atomic reference counter
195 #else
196 int refCount; // reference counter
197 #endif
198
lstring8_chunk_tlstring8_chunk_t199 lstring8_chunk_t() {}
200
201 // chunk allocation functions
202 static lstring8_chunk_t * alloc();
203 static void free( lstring8_chunk_t * pChunk );
204
205 };
206
207 struct lstring32_chunk_t {
208 friend class lString8;
209 friend class lString32;
210 friend class lString32Collection;
211 friend struct lstring_chunk_slice_t;
212 public:
lstring32_chunk_tlstring32_chunk_t213 lstring32_chunk_t(lChar32 * _buf32) : buf32(_buf32), size(1), len(0)
214 {
215 refCount = 1;
216 }
data32lstring32_chunk_t217 const lChar32 * data32() const { return buf32; }
218 private:
219 lChar32 * buf32; // z-string
220 lInt32 size; // 0 for free chunk
221 lInt32 len; // count of chars in string
222 #ifdef USE_ATOMIC_REFCOUNT
223 std::atomic_int refCount; // atomic reference counter
224 #else
225 int refCount; // reference counter
226 #endif
227
lstring32_chunk_tlstring32_chunk_t228 lstring32_chunk_t() {}
229
230 // chunk allocation functions
231 static lstring32_chunk_t * alloc();
232 static void free( lstring32_chunk_t * pChunk );
233 };
234
235 struct lstring16_chunk_t {
236 friend class lString8;
237 friend class lString16;
238 friend struct lstring_chunk_slice_t;
239 public:
lstring16_chunk_tlstring16_chunk_t240 lstring16_chunk_t(lChar16 * _buf16) : buf16(_buf16), size(1), len(0)
241 {
242 refCount = 1;
243 }
data16lstring16_chunk_t244 const lChar16 * data16() const { return buf16; }
245 private:
246 lChar16 * buf16; // z-string
247 lInt32 size; // 0 for free chunk
248 lInt32 len; // count of chars in string
249 #ifdef USE_ATOMIC_REFCOUNT
250 std::atomic_int refCount; // atomic reference counter
251 #else
252 int refCount; // reference counter
253 #endif
254
lstring16_chunk_tlstring16_chunk_t255 lstring16_chunk_t() {}
256
257 // chunk allocation functions
258 static lstring16_chunk_t * alloc();
259 static void free( lstring16_chunk_t * pChunk );
260 };
261
262
263 namespace fmt {
264 class decimal {
265 lInt64 value;
266 public:
decimal(lInt64 v)267 explicit decimal(lInt64 v) : value(v) { }
get()268 lInt64 get() const { return value; }
269 };
270
271 class hex {
272 lUInt64 value;
273 public:
hex(lInt64 v)274 explicit hex(lInt64 v) : value(v) { }
get()275 lUInt64 get() const { return value; }
276 };
277 }
278
279
280 /**
281 \brief lChar8 string
282
283 Reference counting, copy-on-write implementation of 8-bit string.
284 Interface is similar to STL strings
285
286 */
287 class lString8
288 {
289 friend class lString8Collection;
290 friend const lString8 & cs8(const char * str);
291 public:
292 // typedefs for STL compatibility
293 typedef lChar8 value_type; ///< character type
294 typedef int size_type; ///< size type
295 typedef int difference_type; ///< difference type
296 typedef value_type * pointer; ///< pointer to char type
297 typedef value_type & reference; ///< reference to char type
298 typedef const value_type * const_pointer; ///< pointer to const char type
299 typedef const value_type & const_reference; ///< reference to const char type
300
301 typedef lstring8_chunk_t lstring_chunk_t; ///< data container
302
303 class decimal {
304 lInt64 value;
305 public:
decimal(lInt64 v)306 explicit decimal(lInt64 v) : value(v) { }
get()307 lInt64 get() { return value; }
308 };
309
310 class hex {
311 lUInt64 value;
312 public:
hex(lInt64 v)313 explicit hex(lInt64 v) : value(v) { }
get()314 lUInt64 get() { return value; }
315 };
316
317 private:
318 lstring_chunk_t * pchunk;
319 static lstring_chunk_t * EMPTY_STR_8;
320 void alloc(size_type sz);
321 void free();
addref()322 inline void addref() const {
323 #ifdef USE_ATOMIC_REFCOUNT
324 pchunk->refCount.fetch_add(1);
325 #else
326 ++pchunk->refCount;
327 #endif
328 }
release()329 inline void release() {
330 #ifdef USE_ATOMIC_REFCOUNT
331 if (pchunk->refCount.fetch_sub(1) <= 1)
332 free();
333 #else
334 if (--pchunk->refCount==0) free();
335 #endif
336 }
refCount()337 inline int refCount() {
338 return pchunk->refCount;
339 }
lString8(lstring_chunk_t * chunk)340 explicit lString8(lstring_chunk_t * chunk) : pchunk(chunk) { addref(); }
341 public:
342 /// default constrictor
lString8()343 explicit lString8() : pchunk(EMPTY_STR_8) { addref(); }
344 /// constructor of empty string with buffer of specified size
lString8(int size)345 explicit lString8( int size ) : pchunk(EMPTY_STR_8) { addref(); reserve(size); }
346 /// copy constructor
lString8(const lString8 & str)347 lString8(const lString8 & str) : pchunk(str.pchunk) { addref(); }
348 /// constructor from C string
349 explicit lString8(const value_type * str);
350 /// constructor from 16-bit C string
351 explicit lString8(const lChar32 * str);
352 /// constructor from string of specified length
353 explicit lString8(const value_type * str, size_type count);
354 /// fragment copy constructor
355 explicit lString8(const lString8 & str, size_type offset, size_type count);
356 /// destructor
~lString8()357 ~lString8() { release(); }
358
359 /// copy assignment
assign(const lString8 & str)360 lString8 & assign(const lString8 & str)
361 {
362 if (pchunk!=str.pchunk)
363 {
364 release();
365 pchunk = str.pchunk;
366 addref();
367 }
368 return *this;
369 }
370 /// C-string assignment
371 lString8 & assign(const value_type * str);
372 /// C-string fragment assignment
373 lString8 & assign(const value_type * str, size_type count);
374 /// string fragment assignment
375 lString8 & assign(const lString8 & str, size_type offset, size_type count);
376 /// C-string assignment
377 lString8 & operator = (const value_type * str) { return assign(str); }
378 /// string copy assignment
379 lString8 & operator = (const lString8 & str) { return assign(str); }
380 /// erase part of string
381 lString8 & erase(size_type offset, size_type count);
382 /// append C-string
383 lString8 & append(const value_type * str);
384 /// append C-string fragment
385 lString8 & append(const value_type * str, size_type count);
386 /// append string
387 lString8 & append(const lString8 & str);
388 /// append string fragment
389 lString8 & append(const lString8 & str, size_type offset, size_type count);
390 /// append repeated character
391 lString8 & append(size_type count, value_type ch);
392 /// append decimal number
393 lString8 & appendDecimal(lInt64 v);
394 /// append hex number
395 lString8 & appendHex(lUInt64 v);
396 /// insert C-string
397 lString8 & insert(size_type p0, const value_type * str);
398 /// insert C-string fragment
399 lString8 & insert(size_type p0, const value_type * str, size_type count);
400 /// insert string
401 lString8 & insert(size_type p0, const lString8 & str);
402 /// insert string fragment
403 lString8 & insert(size_type p0, const lString8 & str, size_type offset, size_type count);
404 /// insert repeated character
405 lString8 & insert(size_type p0, size_type count, value_type ch);
406 /// replace fragment with C-string
407 lString8 & replace(size_type p0, size_type n0, const value_type * str);
408 /// replace fragment with C-string fragment
409 lString8 & replace(size_type p0, size_type n0, const value_type * str, size_type count);
410 /// replace fragment with string
411 lString8 & replace(size_type p0, size_type n0, const lString8 & str);
412 /// replace fragment with string fragment
413 lString8 & replace(size_type p0, size_type n0, const lString8 & str, size_type offset, size_type count);
414 /// replace fragment with repeated character
415 lString8 & replace(size_type p0, size_type n0, size_type count, value_type ch);
416 /// make string uppercase
417 lString8 & uppercase();
418 /// make string lowercase
419 lString8 & lowercase();
420 /// compare with another string
compare(const lString8 & str)421 int compare(const lString8& str) const { return lStr_cmp(pchunk->buf8, str.pchunk->buf8); }
422 /// compare part of string with another string
423 int compare(size_type p0, size_type n0, const lString8& str) const;
424 /// compare part of string with fragment of another string
425 int compare(size_type p0, size_type n0, const lString8& str, size_type pos, size_type n) const;
426 /// compare with C-string
compare(const value_type * s)427 int compare(const value_type *s) const { return lStr_cmp(pchunk->buf8, s); }
428 /// compare part of string with C-string
429 int compare(size_type p0, size_type n0, const value_type *s) const;
430 /// compare part of string with C-string fragment
431 int compare(size_type p0, size_type n0, const value_type *s, size_type pos) const;
432 /// find position of char inside string, -1 if not found
433 int pos(lChar8 ch) const;
434 /// find position of char inside string starting from specified position, -1 if not found
435 int pos(lChar8 ch, int start) const;
436 /// find position of substring inside string, -1 if not found
437 int pos(const lString8 & subStr) const;
438 /// find position of substring inside string, -1 if not found
439 int pos(const char * subStr) const;
440 /// find position of substring inside string starting from right, -1 if not found
441 int rpos(const char * subStr) const;
442 /// find position of substring inside string starting from specified position, -1 if not found
443 int pos(const lString8 & subStr, int startPos) const;
444 /// find position of substring inside string starting from specified position, -1 if not found
445 int pos(const char * subStr, int startPos) const;
446
447 /// substring
448 lString8 substr(size_type pos, size_type n) const;
449 /// substring from position to end of string
substr(size_type pos)450 lString8 substr(size_type pos) const { return substr(pos, length() - pos); }
451
452 /// append single character
453 lString8 & operator << (value_type ch) { return append(1, ch); }
454 /// append C-string
455 lString8 & operator << (const value_type * str) { return append(str); }
456 /// append string
457 lString8 & operator << (const lString8 & str) { return append(str); }
458 /// append decimal number
459 lString8 & operator << (const fmt::decimal v) { return appendDecimal(v.get()); }
460 /// append hex number
461 lString8 & operator << (const fmt::hex v) { return appendHex(v.get()); }
462
463 /// returns true if string starts with specified substring
464 bool startsWith ( const lString8 & substring ) const;
465 /// returns true if string starts with specified substring
466 bool startsWith ( const char * substring ) const;
467
468 /// returns last character
lastChar()469 value_type lastChar() { return empty() ? 0 : at(length()-1); }
470 /// returns first character
firstChar()471 value_type firstChar() { return empty() ? 0 : at(0); }
472
473 /// calculate hash
474 lUInt32 getHash() const;
475
476 /// get character at specified position with range check
at(size_type pos)477 value_type & at(size_type pos) {
478 if (pos > pchunk->len)
479 crFatalError();
480 return modify()[pos];
481 }
482 /// get character at specified position without range check
483 value_type operator [] ( size_type pos ) const { return pchunk->buf8[pos]; }
484 /// get reference to character at specified position
485 value_type & operator [] ( size_type pos ) { return modify()[pos]; }
486
487 /// ensures that reference count is 1
488 void lock( size_type newsize );
489 /// returns pointer to modifable string buffer
modify()490 value_type * modify() { if (refCount()>1) lock(pchunk->len); return pchunk->buf8; }
491 /// clear string
clear()492 void clear() { release(); pchunk = EMPTY_STR_8; addref(); }
493 /// clear string, set buffer size
494 void reset( size_type size );
495 /// returns character count
length()496 size_type length() const { return pchunk->len; }
497 /// returns buffer size
size()498 size_type size() const { return pchunk->len; }
499 /// changes buffer size
500 void resize(size_type count = 0, value_type e = 0);
501 /// returns maximum number of chars that can fit into buffer
capacity()502 size_type capacity() const { return pchunk->size-1; }
503 /// reserve space for specified amount of chars
504 void reserve(size_type count = 0);
505 /// returns true if string is empty
empty()506 bool empty() const { return pchunk->len==0; }
507 /// returns true if string is empty
508 bool operator !() const { return pchunk->len==0; }
509 /// swaps content of two strings
swap(lString8 & str)510 void swap( lString8 & str ) { lstring_chunk_t * tmp = pchunk;
511 pchunk=str.pchunk; str.pchunk=tmp; }
512 /// pack string (free unused buffer space)
513 lString8 & pack();
514
515 /// remove spaces from begin and end of string
516 lString8 & trim();
517 /// convert to integer
518 int atoi() const;
519 /// convert to 64 bit integer
520 lInt64 atoi64() const;
521
522 /// returns C-string
c_str()523 const value_type * c_str() const { return pchunk->buf8; }
524 /// returns C-string
data()525 const value_type * data() const { return pchunk->buf8; }
526
527 /// append string
528 lString8 & operator += ( lString8 s ) { return append(s); }
529 /// append C-string
530 lString8 & operator += ( const value_type * s ) { return append(s); }
531 /// append single character
532 lString8 & operator += ( value_type ch ) { return append(1, ch); }
533 /// append decimal
534 lString8 & operator += ( fmt::decimal v ) { return appendDecimal(v.get()); }
535 /// append hex
536 lString8 & operator += ( fmt::hex v ) { return appendHex(v.get()); }
537
538 /// returns true if string ends with specified substring
539 bool endsWith( const lChar8 * substring ) const;
540
541 /// constructs string representation of integer
542 static lString8 itoa( int i );
543 /// constructs string representation of unsigned integer
544 static lString8 itoa( unsigned int i );
545 // constructs string representation of 64 bit integer
546 static lString8 itoa( lInt64 n );
547
548 static const lString8 empty_str;
549
550 friend class lString32Collection;
551 };
552
553 /**
554 \brief Wide character (lChar16) string.
555 Intended primarily for WINAPI.
556
557 Reference counting, copy-on-write implementation.
558 Interface is similar to STL strings.
559
560 */
561 class lString16
562 {
563 public:
564 // typedefs for STL compatibility
565 typedef lChar16 value_type;
566 typedef int size_type;
567 typedef int difference_type;
568 typedef value_type * pointer;
569 typedef value_type & reference;
570 typedef const value_type * const_pointer;
571 typedef const value_type & const_reference;
572
573 typedef lstring16_chunk_t lstring_chunk_t; ///< data container
574
575 private:
576 lstring_chunk_t * pchunk;
577 static lstring_chunk_t * EMPTY_STR_16;
578 void alloc(size_type sz);
579 void free();
addref()580 inline void addref() const {
581 #ifdef USE_ATOMIC_REFCOUNT
582 pchunk->refCount.fetch_add(1);
583 #else
584 ++pchunk->refCount;
585 #endif
586 }
release()587 inline void release() {
588 #ifdef USE_ATOMIC_REFCOUNT
589 if (pchunk->refCount.fetch_sub(1) <= 1)
590 free();
591 #else
592 if (--pchunk->refCount==0) free();
593 #endif
594 }
refCount()595 inline int refCount() {
596 return pchunk->refCount;
597 }
598 public:
lString16(lstring_chunk_t * chunk)599 explicit lString16(lstring_chunk_t * chunk) : pchunk(chunk) { addref(); }
600 /// empty string constructor
lString16()601 explicit lString16() : pchunk(EMPTY_STR_16) { addref(); }
602 /// copy constructor
lString16(const lString16 & str)603 lString16(const lString16 & str) : pchunk(str.pchunk) { addref(); }
604 /// constructor from wide c-string
605 lString16(const value_type * str);
606 /// constructor from 8bit c-string (ASCII only)
607 explicit lString16(const lChar8 * str);
608 /// constructor from 8bit (ASCII only) character array fragment
609 explicit lString16(const lChar8 * str, size_type count);
610 /// constructor from wide character array fragment
611 explicit lString16(const value_type * str, size_type count);
612 /// constructor from another string substring
613 explicit lString16(const lString16 & str, size_type offset, size_type count);
614 /// desctructor
~lString16()615 ~lString16() { release(); }
616
617 /// assignment from string
assign(const lString16 & str)618 lString16 & assign(const lString16 & str)
619 {
620 if (pchunk!=str.pchunk)
621 {
622 release();
623 pchunk = str.pchunk;
624 addref();
625 }
626 return *this;
627 }
628 /// assignment from c-string
629 lString16 & assign(const value_type * str);
630 /// assignment from 8bit c-string (ASCII only)
631 lString16 & assign(const lChar8 * str);
632 /// assignment from character array fragment
633 lString16 & assign(const value_type * str, size_type count);
634 /// assignment from 8-bit character array fragment (ASCII only)
635 lString16 & assign(const lChar8 * str, size_type count);
636 /// assignment from string fragment
637 lString16 & assign(const lString16 & str, size_type offset, size_type count);
638 /// assignment from c-string
639 lString16 & operator = (const value_type * str) { return assign(str); }
640 /// assignment from string 8bit ASCII only
641 lString16 & operator = (const lChar8 * str) { return assign(str); }
642 /// assignment from string
643 lString16 & operator = (const lString16 & str) { return assign(str); }
644 lString16 & erase(size_type offset, size_type count);
645
646 lString16 & append(const value_type * str);
647 lString16 & append(const value_type * str, size_type count);
648 lString16 & append(const lChar8 * str);
649 lString16 & append(const lChar8 * str, size_type count);
650 lString16 & append(const lString16 & str);
651 lString16 & append(const lString16 & str, size_type offset, size_type count);
652 lString16 & append(size_type count, value_type ch);
653 /// append decimal number
654 lString16 & appendDecimal(lInt64 v);
655 /// append hex number
656 lString16 & appendHex(lUInt64 v);
657 lString16 & insert(size_type p0, const value_type * str);
658 lString16 & insert(size_type p0, const value_type * str, size_type count);
659 lString16 & insert(size_type p0, const lString16 & str);
660 lString16 & insert(size_type p0, size_type count, value_type ch);
661 /// compare with another string
compare(const lString16 & str)662 int compare(const lString16& str) const { return lStr_cmp(pchunk->buf16, str.pchunk->buf16); }
compare(const value_type * s)663 int compare(const value_type *s) const { return lStr_cmp(pchunk->buf16, s); }
compare(const lChar8 * s)664 int compare(const lChar8 *s) const { return lStr_cmp(pchunk->buf16, s); }
665
666 /// returns n characters beginning with pos
667 lString16 substr(size_type pos, size_type n) const;
668 /// returns part of string from specified position to end of string
substr(size_type pos)669 lString16 substr(size_type pos) const { return substr(pos, length()-pos); }
670 /// replaces first found occurence of pattern
671 bool replace(const lString16 & findStr, const lString16 & replaceStr);
672 /// replaces first found occurence of "$N" pattern with string, where N=index
673 bool replaceParam(int index, const lString16 & replaceStr);
674 /// replaces first found occurence of "$N" pattern with itoa of integer, where N=index
675 bool replaceIntParam(int index, int replaceNumber);
676
677 /// append single character
678 lString16 & operator << (value_type ch) { return append(1, ch); }
679 /// append c-string
680 lString16 & operator << (const value_type * str) { return append(str); }
681 /// append 8-bit c-string (ASCII only)
682 lString16 & operator << (const lChar8 * str) { return append(str); }
683 /// append string
684 lString16 & operator << (const lString16 & str) { return append(str); }
685 /// append decimal number
686 lString16 & operator << (const fmt::decimal v) { return appendDecimal(v.get()); }
687 /// append hex number
688 lString16 & operator << (const fmt::hex v) { return appendHex(v.get()); }
689
690 /// returns true if string starts with specified substring
691 bool startsWith (const lString16 & substring) const;
692 /// returns true if string starts with specified substring
693 bool startsWith (const lChar16 * substring) const;
694 /// returns true if string starts with specified substring (8bit ASCII only)
695 bool startsWith (const lChar8 * substring) const;
696 /// returns true if string ends with specified substring
697 bool endsWith(const lChar16 * substring) const;
698 /// returns true if string ends with specified substring (8-bit ASCII only)
699 bool endsWith(const lChar8 * substring) const;
700 /// returns true if string ends with specified substring
701 bool endsWith (const lString16 & substring) const;
702 /// returns true if string starts with specified substring, case insensitive
703 bool startsWithNoCase (const lString16 & substring) const;
704
705 /// returns last character
lastChar()706 value_type lastChar() { return empty() ? 0 : at(length()-1); }
707 /// returns first character
firstChar()708 value_type firstChar() { return empty() ? 0 : at(0); }
709
710 /// calculates hash for string
711 lUInt32 getHash() const;
712 /// returns character at specified position, with index bounds checking, fatal error if fails
at(size_type pos)713 value_type & at( size_type pos ) { if ((unsigned)pos > (unsigned)pchunk->len) crFatalError(); return modify()[pos]; }
714 /// returns character at specified position, without index bounds checking
715 value_type operator [] ( size_type pos ) const { return pchunk->buf16[pos]; }
716 /// returns reference to specified character position (lvalue)
717 value_type & operator [] ( size_type pos ) { return modify()[pos]; }
718 /// resizes string, copies if several references exist
719 void lock( size_type newsize );
720 /// returns writable pointer to string buffer
modify()721 value_type * modify() { if (refCount()>1) lock(pchunk->len); return pchunk->buf16; }
722 /// clears string contents
clear()723 void clear() { release(); pchunk = EMPTY_STR_16; addref(); }
724 /// resets string, allocates space for specified amount of characters
725 void reset( size_type size );
726 /// returns string length, in characters
length()727 size_type length() const { return pchunk->len; }
728 /// returns string length, in characters
size()729 size_type size() const { return pchunk->len; }
730 /// resizes string buffer, appends with specified character if buffer is being extended
731 void resize(size_type count = 0, value_type e = 0);
732 /// returns string buffer size
capacity()733 size_type capacity() const { return pchunk->size-1; }
734 /// ensures string buffer can hold at least count characters
735 void reserve(size_type count = 0);
736 /// erase all extra characters from end of string after size
737 void limit( size_type size );
738 /// returns true if string is empty
empty()739 bool empty() const { return pchunk->len==0; }
740 /// swaps two string variables contents
swap(lString16 & str)741 void swap( lString16 & str ) { lstring_chunk_t * tmp = pchunk;
742 pchunk=str.pchunk; str.pchunk=tmp; }
743 /// trims all unused space at end of string (sets size to length)
744 lString16 & pack();
745
746 /// trims non alpha at beginning and end of string
747 lString16 & trimNonAlpha();
748 /// trims spaces at beginning and end of string
749 lString16 & trim();
750 /// converts to integer
751 int atoi() const;
752 /// converts to integer, returns true if success
753 bool atoi( int &n ) const;
754 /// converts to 64 bit integer, returns true if success
755 bool atoi( lInt64 &n ) const;
756 /// returns constant c-string pointer
c_str()757 const value_type * c_str() const { return pchunk->buf16; }
758 /// returns constant c-string pointer, same as c_str()
data()759 const value_type * data() const { return pchunk->buf16; }
760 /// appends string
761 lString16 & operator += ( lString16 s ) { return append(s); }
762 /// appends c-string
763 lString16 & operator += ( const value_type * s ) { return append(s); }
764 /// append C-string
765 lString16 & operator += ( const lChar8 * s ) { return append(s); }
766 /// appends single character
767 lString16 & operator += ( value_type ch ) { return append(1, ch); }
768 /// append decimal
769 lString16 & operator += ( fmt::decimal v ) { return appendDecimal(v.get()); }
770 /// append hex
771 lString16 & operator += ( fmt::hex v ) { return appendHex(v.get()); }
772
773 /// constructs string representation of integer
774 static lString16 itoa( int i );
775 /// constructs string representation of unsigned integer
776 static lString16 itoa( unsigned int i );
777 /// constructs string representation of 64 bit integer
778 static lString16 itoa( lInt64 i );
779 /// constructs string representation of unsigned 64 bit integer
780 static lString16 itoa( lUInt64 i );
781
782 /// empty string global instance
783 static const lString16 empty_str;
784 };
785
786
787 /**
788 \brief Wide character (lChar32) string.
789
790 Reference counting, copy-on-write implementation.
791 Interface is similar to STL strings.
792
793 */
794 class lString32
795 {
796 friend const lString32 & cs32(const char * str);
797 friend const lString32 & cs32(const lChar32 * str);
798 public:
799 // typedefs for STL compatibility
800 typedef lChar32 value_type;
801 typedef int size_type;
802 typedef int difference_type;
803 typedef value_type * pointer;
804 typedef value_type & reference;
805 typedef const value_type * const_pointer;
806 typedef const value_type & const_reference;
807
808 typedef lstring32_chunk_t lstring_chunk_t; ///< data container
809
810 private:
811 lstring_chunk_t * pchunk;
812 static lstring_chunk_t * EMPTY_STR_32;
813 void alloc(size_type sz);
814 void free();
addref()815 inline void addref() const {
816 #ifdef USE_ATOMIC_REFCOUNT
817 pchunk->refCount.fetch_add(1);
818 #else
819 ++pchunk->refCount;
820 #endif
821 }
release()822 inline void release() {
823 #ifdef USE_ATOMIC_REFCOUNT
824 if (pchunk->refCount.fetch_sub(1) <= 1)
825 free();
826 #else
827 if (--pchunk->refCount==0) free();
828 #endif
829 }
refCount()830 inline int refCount() {
831 return pchunk->refCount;
832 }
833 public:
lString32(lstring_chunk_t * chunk)834 explicit lString32(lstring_chunk_t * chunk) : pchunk(chunk) { addref(); }
835 /// empty string constructor
lString32()836 explicit lString32() : pchunk(EMPTY_STR_32) { addref(); }
837 /// copy constructor
lString32(const lString32 & str)838 lString32(const lString32 & str) : pchunk(str.pchunk) { addref(); }
839 /// constructor from wide c-string
840 lString32(const value_type * str);
841 /// constructor from 8bit c-string (ASCII only)
842 explicit lString32(const lChar8 * str);
843 /// constructor from 8bit (ASCII only) character array fragment
844 explicit lString32(const lChar8 * str, size_type count);
845 /// constructor from wide character array fragment
846 explicit lString32(const value_type * str, size_type count);
847 /// constructor from another string substring
848 explicit lString32(const lString32 & str, size_type offset, size_type count);
849 /// desctructor
~lString32()850 ~lString32() { release(); }
851
852 /// assignment from string
assign(const lString32 & str)853 lString32 & assign(const lString32 & str)
854 {
855 if (pchunk!=str.pchunk)
856 {
857 release();
858 pchunk = str.pchunk;
859 addref();
860 }
861 return *this;
862 }
863 /// assignment from c-string
864 lString32 & assign(const value_type * str);
865 /// assignment from 8bit c-string (ASCII only)
866 lString32 & assign(const lChar8 * str);
867 /// assignment from character array fragment
868 lString32 & assign(const value_type * str, size_type count);
869 /// assignment from 8-bit character array fragment (ASCII only)
870 lString32 & assign(const lChar8 * str, size_type count);
871 /// assignment from string fragment
872 lString32 & assign(const lString32 & str, size_type offset, size_type count);
873 /// assignment from c-string
874 lString32 & operator = (const value_type * str) { return assign(str); }
875 /// assignment from string 8bit ASCII only
876 lString32 & operator = (const lChar8 * str) { return assign(str); }
877 /// assignment from string
878 lString32 & operator = (const lString32 & str) { return assign(str); }
879 lString32 & erase(size_type offset, size_type count);
880
881 lString32 & append(const value_type * str);
882 lString32 & append(const value_type * str, size_type count);
883 lString32 & append(const lChar8 * str);
884 lString32 & append(const lChar8 * str, size_type count);
885 lString32 & append(const lString32 & str);
886 lString32 & append(const lString32 & str, size_type offset, size_type count);
887 lString32 & append(size_type count, value_type ch);
888 /// append decimal number
889 lString32 & appendDecimal(lInt64 v);
890 /// append hex number
891 lString32 & appendHex(lUInt64 v);
892 lString32 & insert(size_type p0, const value_type * str);
893 lString32 & insert(size_type p0, const value_type * str, size_type count);
894 lString32 & insert(size_type p0, const lString32 & str);
895 lString32 & insert(size_type p0, const lString32 & str, size_type offset, size_type count);
896 lString32 & insert(size_type p0, size_type count, value_type ch);
897 lString32 & replace(size_type p0, size_type n0, const value_type * str);
898 lString32 & replace(size_type p0, size_type n0, const value_type * str, size_type count);
899 lString32 & replace(size_type p0, size_type n0, const lString32 & str);
900 lString32 & replace(size_type p0, size_type n0, const lString32 & str, size_type offset, size_type count);
901 /// replace range of string with character ch repeated count times
902 lString32 & replace(size_type p0, size_type n0, size_type count, value_type ch);
903 /// make string uppercase
904 lString32 & uppercase();
905 /// make string lowercase
906 lString32 & lowercase();
907 /// make string capitalized
908 lString32 & capitalize();
909 /// make string use full width chars
910 lString32 & fullWidthChars();
911 /// compare with another string
compare(const lString32 & str)912 int compare(const lString32& str) const { return lStr_cmp(pchunk->buf32, str.pchunk->buf32); }
913 /// compare subrange with another string
914 int compare(size_type p0, size_type n0, const lString32& str) const;
915 /// compare subrange with substring of another string
916 int compare(size_type p0, size_type n0, const lString32& str, size_type pos, size_type n) const;
compare(const value_type * s)917 int compare(const value_type *s) const { return lStr_cmp(pchunk->buf32, s); }
compare(const lChar8 * s)918 int compare(const lChar8 *s) const { return lStr_cmp(pchunk->buf32, s); }
919 int compare(size_type p0, size_type n0, const value_type *s) const;
920 int compare(size_type p0, size_type n0, const value_type *s, size_type pos) const;
921
922 /// split string into two strings using delimiter
923 bool split2( const lString32 & delim, lString32 & value1, lString32 & value2 );
924 /// split string into two strings using delimiter
925 bool split2( const lChar32 * delim, lString32 & value1, lString32 & value2 );
926 /// split string into two strings using delimiter
927 bool split2( const lChar8 * delim, lString32 & value1, lString32 & value2 );
928
929 /// returns n characters beginning with pos
930 lString32 substr(size_type pos, size_type n) const;
931 /// returns part of string from specified position to end of string
substr(size_type pos)932 lString32 substr(size_type pos) const { return substr(pos, length()-pos); }
933 /// replaces first found occurence of pattern
934 bool replace(const lString32 & findStr, const lString32 & replaceStr);
935 /// replaces first found occurence of "$N" pattern with string, where N=index
936 bool replaceParam(int index, const lString32 & replaceStr);
937 /// replaces first found occurence of "$N" pattern with itoa of integer, where N=index
938 bool replaceIntParam(int index, int replaceNumber);
939
940 /// find position of char inside string, -1 if not found
941 int pos(lChar32 ch) const;
942 /// find position of char inside string starting from specified position, -1 if not found
943 int pos(lChar32 ch, int start) const;
944 /// find position of substring inside string, -1 if not found
945 int pos(lString32 subStr) const;
946 /// find position of substring inside string starting from specified position, -1 if not found
947 int pos(const lString32 & subStr, int start) const;
948 /// find position of substring inside string, -1 if not found
949 int pos(const lChar32 * subStr) const;
950 /// find position of substring inside string (8bit ASCII only), -1 if not found
951 int pos(const lChar8 * subStr) const;
952 /// find position of substring inside string starting from specified position, -1 if not found
953 int pos(const lChar32 * subStr, int start) const;
954 /// find position of substring inside string (8bit ASCII only) starting from specified position, -1 if not found
955 int pos(const lChar8 * subStr, int start) const;
956
957 /// find position of substring inside string, right to left, return -1 if not found
958 int rpos(lString32 subStr) const;
959
960 /// append single character
961 lString32 & operator << (value_type ch) { return append(1, ch); }
962 /// append c-string
963 lString32 & operator << (const value_type * str) { return append(str); }
964 /// append 8-bit c-string (ASCII only)
965 lString32 & operator << (const lChar8 * str) { return append(str); }
966 /// append string
967 lString32 & operator << (const lString32 & str) { return append(str); }
968 /// append decimal number
969 lString32 & operator << (const fmt::decimal v) { return appendDecimal(v.get()); }
970 /// append hex number
971 lString32 & operator << (const fmt::hex v) { return appendHex(v.get()); }
972
973 /// returns true if string starts with specified substring
974 bool startsWith (const lString32 & substring) const;
975 /// returns true if string starts with specified substring
976 bool startsWith (const lChar32 * substring) const;
977 /// returns true if string starts with specified substring (8bit ASCII only)
978 bool startsWith (const lChar8 * substring) const;
979 /// returns true if string ends with specified substring
980 bool endsWith(const lChar32 * substring) const;
981 /// returns true if string ends with specified substring (8-bit ASCII only)
982 bool endsWith(const lChar8 * substring) const;
983 /// returns true if string ends with specified substring
984 bool endsWith (const lString32 & substring) const;
985 /// returns true if string starts with specified substring, case insensitive
986 bool startsWithNoCase (const lString32 & substring) const;
987
988 /// returns last character
lastChar()989 value_type lastChar() { return empty() ? 0 : at(length()-1); }
990 /// returns first character
firstChar()991 value_type firstChar() { return empty() ? 0 : at(0); }
992
993 /// calculates hash for string
994 lUInt32 getHash() const;
995 /// returns character at specified position, with index bounds checking, fatal error if fails
at(size_type pos)996 value_type & at( size_type pos ) { if ((unsigned)pos > (unsigned)pchunk->len) crFatalError(); return modify()[pos]; }
997 /// returns character at specified position, without index bounds checking
998 value_type operator [] ( size_type pos ) const { return pchunk->buf32[pos]; }
999 /// returns reference to specified character position (lvalue)
1000 value_type & operator [] ( size_type pos ) { return modify()[pos]; }
1001 /// resizes string, copies if several references exist
1002 void lock( size_type newsize );
1003 /// returns writable pointer to string buffer
modify()1004 value_type * modify() { if (refCount()>1) lock(pchunk->len); return pchunk->buf32; }
1005 /// clears string contents
clear()1006 void clear() { release(); pchunk = EMPTY_STR_32; addref(); }
1007 /// resets string, allocates space for specified amount of characters
1008 void reset( size_type size );
1009 /// returns string length, in characters
length()1010 size_type length() const { return pchunk->len; }
1011 /// returns string length, in characters
size()1012 size_type size() const { return pchunk->len; }
1013 /// resizes string buffer, appends with specified character if buffer is being extended
1014 void resize(size_type count = 0, value_type e = 0);
1015 /// returns string buffer size
capacity()1016 size_type capacity() const { return pchunk->size-1; }
1017 /// ensures string buffer can hold at least count characters
1018 void reserve(size_type count = 0);
1019 /// erase all extra characters from end of string after size
1020 void limit( size_type size );
1021 /// returns true if string is empty
empty()1022 bool empty() const { return pchunk->len==0; }
1023 /// swaps two string variables contents
swap(lString32 & str)1024 void swap( lString32 & str ) { lstring_chunk_t * tmp = pchunk;
1025 pchunk=str.pchunk; str.pchunk=tmp; }
1026 /// trims all unused space at end of string (sets size to length)
1027 lString32 & pack();
1028
1029 /// trims non alpha at beginning and end of string
1030 lString32 & trimNonAlpha();
1031 /// trims spaces at beginning and end of string
1032 lString32 & trim();
1033 /// trims duplicate space characters inside string and (optionally) at end and beginning of string
1034 lString32 & trimDoubleSpaces( bool allowStartSpace, bool allowEndSpace, bool removeEolHyphens=false );
1035 /// converts to integer
1036 int atoi() const;
1037 /// converts to integer, returns true if success
1038 bool atoi( int &n ) const;
1039 /// converts to 64 bit integer, returns true if success
1040 bool atoi( lInt64 &n ) const;
1041 /// returns constant c-string pointer
c_str()1042 const value_type * c_str() const { return pchunk->buf32; }
1043 /// returns constant c-string pointer, same as c_str()
data()1044 const value_type * data() const { return pchunk->buf32; }
1045 /// appends string
1046 lString32 & operator += ( lString32 s ) { return append(s); }
1047 /// appends c-string
1048 lString32 & operator += ( const value_type * s ) { return append(s); }
1049 /// append C-string
1050 lString32 & operator += ( const lChar8 * s ) { return append(s); }
1051 /// appends single character
1052 lString32 & operator += ( value_type ch ) { return append(1, ch); }
1053 /// append decimal
1054 lString32 & operator += ( fmt::decimal v ) { return appendDecimal(v.get()); }
1055 /// append hex
1056 lString32 & operator += ( fmt::hex v ) { return appendHex(v.get()); }
1057
1058 /// constructs string representation of integer
1059 static lString32 itoa( int i );
1060 /// constructs string representation of unsigned integer
1061 static lString32 itoa( unsigned int i );
1062 /// constructs string representation of 64 bit integer
1063 static lString32 itoa( lInt64 i );
1064 /// constructs string representation of unsigned 64 bit integer
1065 static lString32 itoa( lUInt64 i );
1066
1067 /// empty string global instance
1068 static const lString32 empty_str;
1069
1070 friend class lString32Collection;
1071 };
1072
1073 /// calculates hash for wide string
getHash(const lString32 & s)1074 inline lUInt32 getHash( const lString32 & s )
1075 {
1076 return s.getHash();
1077 }
1078
getHash(const lString16 & s)1079 inline lUInt32 getHash( const lString16 & s )
1080 {
1081 return s.getHash();
1082 }
1083
1084 /// calculates hash for string
getHash(const lString8 & s)1085 inline lUInt32 getHash( const lString8 & s )
1086 {
1087 return s.getHash();
1088 }
1089
1090 /// get reference to atomic constant string for string literal e.g. cs8("abc") -- fast and memory effective replacement of lString8("abc")
1091 const lString8 & cs8(const char * str);
1092 /// get reference to atomic constant wide string for string literal e.g. cs32("abc") -- fast and memory effective replacement of lString32("abc")
1093 const lString32 & cs32(const char * str);
1094 /// get reference to atomic constant wide string for string literal e.g. cs32(L"abc") -- fast and memory effective replacement of lString32(L"abc")
1095 const lString32 & cs32(const lChar32 * str);
1096
1097 /// calculates hash for wide c-string
1098 lUInt32 calcStringHash( const lChar16 * s );
1099 lUInt32 calcStringHash( const lChar32 * s );
1100
1101 /// returns true if two wide strings are equal
1102 inline bool operator == (const lString16& s1, const lString16& s2 )
1103 { return s1.compare(s2)==0; }
1104 /// returns true if two wide strings are equal
1105 inline bool operator == (const lString32& s1, const lString32& s2 )
1106 { return s1.compare(s2)==0; }
1107 /// returns true if wide strings is equal to wide c-string
1108 inline bool operator == (const lString16& s1, const lChar16 * s2 )
1109 { return s1.compare(s2)==0; }
1110 /// returns true if wide strings is equal to wide c-string
1111 inline bool operator == (const lString32& s1, const lChar32 * s2 )
1112 { return s1.compare(s2)==0; }
1113 /// returns true if wide strings is equal to wide c-string
1114 inline bool operator == (const lString16& s1, const lChar8 * s2 )
1115 { return s1.compare(s2)==0; }
1116 /// returns true if wide strings is equal to wide c-string
1117 inline bool operator == (const lString32& s1, const lChar8 * s2 )
1118 { return s1.compare(s2)==0; }
1119 /// returns true if wide strings is equal to wide c-string
1120 inline bool operator == (const lChar32 * s1, const lString32& s2 )
1121 { return s2.compare(s1)==0; }
1122 /// returns true if wide strings is equal to wide c-string
1123 inline bool operator == (const lChar16 * s1, const lString16& s2 )
1124 { return s2.compare(s1)==0; }
1125
1126 /// returns true if wide strings is equal to wide c-string
1127 inline bool operator == (const lString16& s1, const lString8& s2 )
1128 { return lStr_cmp(s2.c_str(), s1.c_str())==0; }
1129 /// returns true if wide strings is equal to wide c-string
1130 inline bool operator == (const lString32& s1, const lString16& s2 )
1131 { return lStr_cmp(s2.c_str(), s1.c_str())==0; }
1132 /// returns true if wide strings is equal to wide c-string
1133 inline bool operator == (const lString32& s1, const lString8& s2 )
1134 { return lStr_cmp(s2.c_str(), s1.c_str())==0; }
1135 /// returns true if wide strings is equal to wide c-string
1136 inline bool operator == (const lString8& s1, const lString32& s2 )
1137 { return lStr_cmp(s2.c_str(), s1.c_str())==0; }
1138 /// returns true if wide strings is equal to wide c-string
1139 inline bool operator == (const lString16& s1, const lString32& s2 )
1140 { return lStr_cmp(s2.c_str(), s1.c_str())==0; }
1141
1142 inline bool operator != (const lString16& s1, const lString16& s2 )
1143 { return s1.compare(s2)!=0; }
1144 inline bool operator != (const lString32& s1, const lString32& s2 )
1145 { return s1.compare(s2)!=0; }
1146 inline bool operator != (const lString16& s1, const lChar16 * s2 )
1147 { return s1.compare(s2)!=0; }
1148 inline bool operator != (const lString32& s1, const lChar32 * s2 )
1149 { return s1.compare(s2)!=0; }
1150 inline bool operator != (const lString16& s1, const lChar8 * s2 )
1151 { return s1.compare(s2)!=0; }
1152 inline bool operator != (const lString32& s1, const lChar8 * s2 )
1153 { return s1.compare(s2)!=0; }
1154 inline bool operator != (const lChar16 * s1, const lString16& s2 )
1155 { return s2.compare(s1)!=0; }
1156 inline bool operator != (const lChar32 * s1, const lString32& s2 )
1157 { return s2.compare(s1)!=0; }
1158 inline bool operator != (const lChar8 * s1, const lString16& s2 )
1159 { return s2.compare(s1)!=0; }
1160 inline bool operator != (const lChar8 * s1, const lString32& s2 )
1161 { return s2.compare(s1)!=0; }
1162 inline lString32 operator + (const lString32 &s1, const lString32 &s2) { lString32 s(s1); s.append(s2); return s; }
1163 inline lString32 operator + (const lString32 &s1, const lChar32 * s2) { lString32 s(s1); s.append(s2); return s; }
1164 inline lString32 operator + (const lString32 &s1, const lChar8 * s2) { lString32 s(s1); s.append(s2); return s; }
1165 inline lString32 operator + (const lChar32 * s1, const lString32 &s2) { lString32 s(s1); s.append(s2); return s; }
1166 inline lString32 operator + (const lChar8 * s1, const lString32 &s2) { lString32 s(s1); s.append(s2); return s; }
1167 inline lString32 operator + (const lString32 &s1, fmt::decimal v) { lString32 s(s1); s.appendDecimal(v.get()); return s; }
1168 inline lString32 operator + (const lString32 &s1, fmt::hex v) { lString32 s(s1); s.appendHex(v.get()); return s; }
1169
1170 inline bool operator == (const lString8& s1, const lString8& s2 )
1171 { return s1.compare(s2)==0; }
1172 inline bool operator == (const lString8& s1, const lChar8 * s2 )
1173 { return s1.compare(s2)==0; }
1174 inline bool operator == (const lChar8 * s1, const lString8& s2 )
1175 { return s2.compare(s1)==0; }
1176 inline bool operator != (const lString8& s1, const lString8& s2 )
1177 { return s1.compare(s2)!=0; }
1178 inline bool operator != (const lString8& s1, const lChar8 * s2 )
1179 { return s1.compare(s2)!=0; }
1180 inline bool operator != (const lChar8 * s1, const lString8& s2 )
1181 { return s2.compare(s1)!=0; }
1182 inline lString8 operator + (const lString8 &s1, const lString8 &s2)
1183 { lString8 s(s1); s.append(s2); return s; }
1184 inline lString8 operator + (const lString8 &s1, const lChar8 * s2)
1185 { lString8 s(s1); s.append(s2); return s; }
1186 inline lString8 operator + (const lString8 &s1, fmt::decimal v)
1187 { lString8 s(s1); s.appendDecimal(v.get()); return s; }
1188 inline lString8 operator + (const lString8 &s1, fmt::hex v)
1189 { lString8 s(s1); s.appendHex(v.get()); return s; }
1190
1191
1192 lString8 UnicodeToTranslit( const lString32 & str );
1193 /// converts wide unicode string to local 8-bit encoding
1194 lString8 UnicodeToLocal( const lString32 & str );
1195 /// converts wide unicode string to utf-8 string
1196 lString8 UnicodeToUtf8( const lString32 & str );
1197 /// converts wide unicode string to utf-16 string
1198 lString16 UnicodeToUtf16( const lString32 & str );
1199 /// converts wide unicode string to utf-8 string
1200 lString8 UnicodeToUtf8(const lChar32 * s, int count);
1201 /// converts wide unicode string to utf-16 string
1202 lString16 UnicodeToUtf16(const lChar32 * s, int count);
1203 /// converts wide unicode string to wtf-8 string
1204 lString8 UnicodeToWtf8( const lString32 & str );
1205 /// converts wide unicode string to wtf-8 string
1206 lString8 UnicodeToWtf8(const lChar32 * s, int count);
1207 /// converts unicode string to 8-bit string using specified conversion table
1208 lString8 UnicodeTo8Bit( const lString32 & str, const lChar8 * * table );
1209 /// converts 8-bit string to unicode string using specified conversion table for upper 128 characters
1210 lString32 ByteToUnicode( const lString8 & str, const lChar32 * table );
1211 /// converts 8-bit string in local encoding to wide unicode string
1212 lString32 LocalToUnicode( const lString8 & str );
1213 /// converts utf-8 string to wide unicode string
1214 lString32 Utf8ToUnicode( const lString8 & str );
1215 /// converts utf-8 c-string to wide unicode string
1216 lString32 Utf8ToUnicode( const char * s );
1217 /// converts utf-8 string fragment to wide unicode string
1218 lString32 Utf8ToUnicode( const char * s, int sz );
1219 /// converts utf-8 string fragment to wide unicode string
1220 void Utf8ToUnicode(const lUInt8 * src, int &srclen, lChar32 * dst, int &dstlen);
1221 /// converts utf-16 string to wide unicode string
1222 lString32 Utf16ToUnicode( const lString16 & str );
1223 /// converts utf-16 c-string to wide unicode string
1224 lString32 Utf16ToUnicode( const lChar16 * s );
1225 /// converts utf-16 string fragment to wide unicode string
1226 lString32 Utf16ToUnicode( const lChar16 * s, int sz );
1227 /// converts utf-16 string fragment to wide unicode string
1228 void Utf16ToUnicode(const lChar16 * src, int &srclen, lChar32 * dst, int &dstlen);
1229 /// converts wtf-8 string to wide unicode string
1230 lString32 Wtf8ToUnicode( const lString8 & str );
1231 /// converts utf-8 c-string to wide unicode string
1232 lString32 Wtf8ToUnicode( const char * s );
1233 /// converts utf-8 string fragment to wide unicode string
1234 lString32 Wtf8ToUnicode( const char * s, int sz );
1235 /// decodes path like "file%20name" to "file name"
1236 lString32 DecodeHTMLUrlString( lString32 s );
1237 /// truncates string by specified size, appends ... if truncated, prefers to wrap whole words
1238 void limitStringSize(lString32 & str, int maxSize);
1239
1240 int TrimDoubleSpaces(lChar32 * buf, int len, bool allowStartSpace, bool allowEndSpace, bool removeEolHyphens);
1241
1242 /// remove soft-hyphens from string
1243 lString32 removeSoftHyphens( lString32 s );
1244
1245
1246 #define LCSTR(x) (UnicodeToUtf8(x).c_str())
1247 bool splitIntegerList( lString32 s, lString32 delim, int & value1, int & value2 );
1248
1249 #if LDOM_USE_OWN_MEM_MAN==1
1250 void free_ls_storage();
1251 #endif
1252
1253 #endif // __LV_STRING_H_INCLUDED__
1254