Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
String.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlCore/String.hpp>
33 #include <vlCore/String_Tables.hpp>
34 #include <vlCore/Log.hpp>
35 #include <vlCore/Say.hpp>
36 #include <vlCore/FileSystem.hpp>
37 #include <vlCore/VirtualFile.hpp>
39 #include <stdio.h>
40 #include <stdarg.h>
41 
42 using namespace vl;
43 
44 //-----------------------------------------------------------------------------
45 // String
46 //-----------------------------------------------------------------------------
48 {
49 #if VL_STRING_COPY_ON_WRITE == 0
50  acquireData();
51 #endif
52 }
53 //-----------------------------------------------------------------------------
54 String::String(const String& other)
55 {
56  operator=(other);
57 }
58 //-----------------------------------------------------------------------------
59 String::String(const wchar_t* wstr)
60 {
61 #if VL_STRING_COPY_ON_WRITE == 0
62  acquireData();
63 #endif
64  if (wstr)
65  *this = wstr;
66 }
67 //-----------------------------------------------------------------------------
68 String::String(const char* str)
69 {
70 #if VL_STRING_COPY_ON_WRITE == 0
71  acquireData();
72 #endif
73  if (str)
74  *this = str;
75 }
76 //-----------------------------------------------------------------------------
77 String::String(wchar_t ch, int count)
78 {
79 #if VL_STRING_COPY_ON_WRITE == 0
80  acquireData();
81 #endif
82  for(int i=0; i<count; ++i)
83  *this += ch;
84 }
85 //-----------------------------------------------------------------------------
86 String String::loadText(const String& path, EStringEncoding default_encoding)
87 {
89  if (file)
90  return loadText( file.get(), default_encoding );
91  else
92  {
93  Log::error( Say("Could not locate '%s'.\n") << path );
94  return String();
95  }
96 }
97 //-----------------------------------------------------------------------------
99 {
100  std::vector<char> buffer;
101  file->load( buffer );
102  file->close();
103 
104  if ( buffer.size() )
105  {
106  return loadText( &buffer[0], (int)buffer.size(), default_encoding );
107  }
108  else
109  {
110  return String();
111  }
112 }
113 //-----------------------------------------------------------------------------
114 String String::loadText(void* data, int bytes, EStringEncoding default_encoding )
115 {
116  EStringEncoding enc = detectEncoding( data, bytes, default_encoding );
117  String text;
118  switch(enc)
119  {
120  case SE_ASCII:
121  return fromAscii((char*)data, bytes);
122  break;
123  case SE_LATIN1:
124  return fromLatin1((char*)data, bytes);
125  break;
126  case SE_UTF8:
127  return fromUTF8((char*)data, bytes);
128  break;
129  case SE_UTF16_BE:
130  return fromUTF16BE((unsigned short*)data, bytes );
131  break;
132  case SE_UTF16_LE:
133  return fromUTF16LE((unsigned short*)data, bytes );
134  break;
135  case SE_Unknown:
136  Log::error("String::loadText() unknown encoding.\n");
137  break;
138  case SE_UTF32_BE:
139  case SE_UTF32_LE:
140  Log::error("String::loadText() SE_UTF32_BE/SE_UTF32_LE encoding not supported.\n");
141  break;
142  }
143  return String();
144 }
145 //-----------------------------------------------------------------------------
146 String& String::resize(int character_count)
147 {
148  acquireData();
149  mString->resize(character_count);
150  return *this;
151 }
152 //-----------------------------------------------------------------------------
153 String String::substring(int start, int count) const
154 {
155  // createData();
156  if ( empty() )
157  return String();
158 
159  if (start<0)
160  start = 0;
161  if (count<0)
162  count = length();
163  int end_idx = start+count-1;
164  if (end_idx > length()-1 )
165  end_idx = length()-1;
166 
167  String str;
168  str.acquireData();
169  int sz = end_idx - start + 1;
170  sz = sz < 0 ? 0 : sz;
171  str.mString->resize( sz );
172  for(int i=0; i<(int)str.mString->length(); ++i)
173  (*str.mString)[i] = (*mString)[start+i];
174  return str;
175 }
176 //-----------------------------------------------------------------------------
177 int String::findBackwards(wchar_t ch) const
178 {
179  // createData();
180  if (empty())
181  return -1;
182 
183  for(int i=length(); i--; )
184  if ((*mString)[i] == ch)
185  return i;
186  return -1;
187 }
188 //-----------------------------------------------------------------------------
189 int String::findBackwards(const String& str) const
190 {
191  // createData();
192  if (empty())
193  return -1;
194 
195  if (str.length() < length())
196  {
197  for(int i = length() - str.length()+1; i--; )
198  {
199  int j=0;
200  for(; j<str.length(); ++j)
201  {
202  if ( str[j] != (*mString)[i+j] )
203  break;
204  }
205  if ( j == str.length() )
206  return i;
207  }
208  }
209  return -1;
210 }
211 //-----------------------------------------------------------------------------
212 bool String::contains(wchar_t ch) const
213 {
214  return find(ch) != -1;
215 }
216 //-----------------------------------------------------------------------------
217 int String::find(wchar_t ch, int start) const
218 {
219  // createData();
220  if (empty())
221  return -1;
222 
223  for(int i=start; i<length(); ++i)
224  if ((*mString)[i] == ch)
225  return i;
226  return -1;
227 }
228 //-----------------------------------------------------------------------------
229 bool String::contains(const String& substr) const
230 {
231  return find(substr) != -1;
232 }
233 //-----------------------------------------------------------------------------
234 namespace
235 {
236  // warning: this function takes 256K on the stack!
237  int String_Quick_Search(const wchar_t*x, int m, const wchar_t*y, int n)
238  {
239  int qsBc[0x10000];
240  for (int i = 0; i < 0x10000; ++i)
241  qsBc[i] = m + 1;
242  for (int i = 0; i < m; ++i)
243  qsBc[x[i]] = m - i;
244  for(int j=0; j <= n - m; j += qsBc[y[j + m]] )
245  if (memcmp(x, y + j, m*sizeof(wchar_t)) == 0)
246  return j;
247  return -1;
248  }
249 }
250 //-----------------------------------------------------------------------------
251 int String::findInLargeText(const String& substr, int start) const
252 {
253  // createData();
254  if (empty())
255  return -1;
256 
257  if ( substr.length() > length() || start >= length() || substr.empty() || empty() )
258  return -1;
259  {
260  int pos = String_Quick_Search( &(*substr.mString)[0], substr.length(), &(*mString)[0]+start, length()-start );
261  return pos >= 0 ? pos + start : pos;
262  }
263 }
264 //-----------------------------------------------------------------------------
265 int String::find(const String& substr, int start) const
266 {
267  // createData();
268  if (empty())
269  return -1;
270 
271  if ( substr.length() > length() || start >= length() || substr.empty() || empty() )
272  return -1;
273  {
274  int max = length() - substr.length();
275  for(int i=start; i<=max; ++i)
276  {
277  int j=0;
278  for(; j<substr.length(); ++j)
279  {
280  if (substr[j] != (*mString)[i+j])
281  break;
282  }
283  if (j == substr.length())
284  return i;
285  }
286  return -1;
287  }
288 }
289 //-----------------------------------------------------------------------------
291 {
292  if(empty())
293  return;
294 
295  mString->squeeze();
296 }
297 //-----------------------------------------------------------------------------
298 String& String::fill(wchar_t ch)
299 {
300  acquireData();
301 
302  for(int i=0; i<length(); ++i)
303  (*mString)[i] = ch;
304  return *this;
305 }
306 //-----------------------------------------------------------------------------
307 String& String::trim(const String& chars)
308 {
309  acquireData();
310 
311  while( chars.length() )
312  {
313  int len = length();
314  for( int i=0; i<chars.length(); ++i)
315  trim(chars[i]);
316  if ( len == length())
317  break;
318  }
319  return *this;
320 }
321 //-----------------------------------------------------------------------------
322 String& String::trim(wchar_t ch)
323 {
324  acquireData();
325 
326  if (length())
327  {
328  int pos = 0;
329  while( (*mString)[pos] == ch )
330  pos++;
331  if (pos)
332  *this = substring(pos);
333  pos = length()-1;
334  while( pos >=0 && (*mString)[pos] == ch )
335  pos--;
336  pos++;
337  if (pos != length())
338  *this = substring(0,pos);
339  }
340  return *this;
341 }
342 //-----------------------------------------------------------------------------
344 {
345  acquireData();
346 
347  trim("\n\r\t\v ");
348 
349  return *this;
350 }
351 //-----------------------------------------------------------------------------
352 void String::split(const String& separator_list, std::vector<String>& fields, bool remove_empty) const
353 {
354  fields.clear();
355 
356  // createData();
357  if (empty())
358  return;
359 
360  if ( length() )
361  {
362  fields.push_back( String() );
363  fields.back().acquireData();
364  fields.back().mString->clear();
365  for(int i=0; i<length(); ++i)
366  {
367  if ( separator_list.contains((*mString)[i]) )
368  {
369  fields.push_back( String() );
370  fields.back().acquireData();
371  fields.back().mString->clear();
372  continue;
373  }
374  fields.back().mString->push_back( (*mString)[i] );
375  }
376  }
377 
378  if (remove_empty)
379  {
380  for ( size_t i=fields.size(); i--; )
381  if (fields[i].empty())
382  fields.erase(fields.begin() + i);
383  }
384 }
385 //-----------------------------------------------------------------------------
386 void String::split(wchar_t separator, std::vector<String>& fields, bool remove_empty) const
387 {
388  fields.clear();
389 
390  // createData();
391  if (empty())
392  return;
393 
394  if ( length() )
395  {
396  fields.push_back( String() );
397  fields.back().acquireData();
398  fields.back().mString->clear();
399  for(int i=0; i<length(); ++i)
400  {
401  if ((*mString)[i] == separator)
402  {
403  fields.push_back( String() );
404  fields.back().acquireData();
405  fields.back().mString->clear();
406  continue;
407  }
408  fields.back().mString->push_back( (*mString)[i] );
409  }
410  }
411 
412  if (remove_empty)
413  {
414  for ( size_t i=fields.size(); i--; )
415  if (fields[i].empty())
416  fields.erase(fields.begin() + i);
417  }
418 }
419 //-----------------------------------------------------------------------------
420 void String::splitLines(std::vector<String>& lines) const
421 {
422  lines.clear();
423 
424  // createData();
425  if (empty())
426  return;
427 
428  if ( length() )
429  {
430  lines.push_back( String() );
431  lines.back().acquireData();
432  lines.back().mString->clear();
433  for(int i=0; i<length(); ++i)
434  {
435  if ((*mString)[i] == '\n' || (*mString)[i] == '\r')
436  {
437  lines.push_back( String() );
438  lines.back().acquireData();
439  lines.back().mString->clear();
440  // no need to check i+1<lenght()-1 since the buffer is 0 terminated
441  if ((*mString)[i] == '\n' && (*mString)[i+1] == '\r')
442  ++i;
443  else
444  if ((*mString)[i] == '\r' && (*mString)[i+1] == '\n')
445  ++i;
446  continue;
447  }
448  lines.back().mString->push_back( (*mString)[i] );
449  }
450  }
451 }
452 //-----------------------------------------------------------------------------
453 String String::field(wchar_t separator, int field_index) const
454 {
455  String field;
456  int field_count = 0;
457  int i=0;
458  for(; i<length() && field_count<field_index; ++i)
459  {
460  if ( (*this)[i] == separator )
461  ++field_count;
462  }
463  // fill field data
464  for(; i<length() && (*this)[i] != separator; ++i)
465  field+=(*this)[i];
466  return field;
467 }
468 //-----------------------------------------------------------------------------
469 String& String::remove(const String& str, int start, int count)
470 {
471  acquireData();
472 
473  if (count == 0)
474  return *this;
475  if (count<0)
476  count = length();
477  int removed = 0;
478  for( int pos = find(str, start); pos != -1 && removed<count; start=pos, pos=find(str, start), ++removed)
479  remove( pos, str.length() );
480  return *this;
481 }
482 //-----------------------------------------------------------------------------
483 String& String::remove( int start, int count )
484 {
485  if (count == 0)
486  return *this;
487 
488  acquireData();
489 
490  String tmp;
491  tmp.acquireData();
492  tmp.mString->clear();
493  int end = start + count-1;
494  for( int i=0; i<length(); i++ )
495  if (i<start || i>end)
496  tmp.mString->push_back((*mString)[i]);
497  /*tmp.mString->push_back(0);*/
498  mString = tmp.mString;
499  return *this;
500 }
501 //-----------------------------------------------------------------------------
502 String& String::remove(wchar_t ch, int start, int count)
503 {
504  acquireData();
505 
506  if (count<0)
507  count = length();
508  String tmp = *this;
509  tmp.acquireData();
510  mString->clear();
511  int removed = 0;
512  for(int i=0; i<tmp.length(); ++i)
513  if ( tmp[i]!=ch || removed==count || i<start)
514  mString->push_back( tmp[i] );
515  else
516  ++removed;
517  /*mString->push_back(0);*/
518  return *this;
519 }
520 //-----------------------------------------------------------------------------
522 {
523  acquireData();
524  int count = length() / 2;
525  for(int i=0; i<count; ++i)
526  {
527  wchar_t tmp = (*this)[i];
528  (*this)[i] = (*this)[length() - 1 - i];
529  (*this)[length() - 1 - i] = tmp;
530  }
531  return *this;
532 }
533 //-----------------------------------------------------------------------------
535 {
536  // convert all '\' to '/'
537  replace('\\', '/');
538  // remove double slashes
539  int len=0;
540  do
541  {
542  len=length();
543  replace("//", "/");
544  }
545  while(len!=length());
546 
547  bool beg_slash = startsWith('/');
548 
549  bool end_slash = endsWith('/');
550 
551  // resolve . and ..
552  std::vector<String> parts;
553  split('/', parts, true);
554  std::vector<String> new_parts;
555  for(size_t i=0; i<parts.size(); ++i)
556  {
557  if (parts[i] == ".")
558  continue;
559  else
560  if (parts[i] == ".." && !new_parts.empty())
561  {
562  new_parts.pop_back();
563  continue;
564  }
565  else
566  new_parts.push_back(parts[i]);
567  }
568 
569  // recreate the string
570 
571  clear();
572  if (beg_slash)
573  *this += '/';
574 
575  for(size_t i=0; i<new_parts.size(); ++i)
576  {
577  *this += new_parts[i];
578  if(i != new_parts.size()-1)
579  *this += '/';
580  }
581 
582  if (end_slash)
583  *this += '/';
584 
585  return *this;
586 }
587 //-----------------------------------------------------------------------------
588 String& String::append(wchar_t ch, int count)
589 {
590  acquireData();
591 
592  for(int i=0; i<count; ++i)
593  mString->push_back(ch);
594  return *this;
595 }
596 //-----------------------------------------------------------------------------
598 {
599  acquireData();
600 
601  for(int i=0; i<other.length(); ++i)
602  mString->push_back(other[i]);
603  return *this;
604 }
605 //-----------------------------------------------------------------------------
607 {
608  return insert(0, str);
609 }
610 //-----------------------------------------------------------------------------
611 String& String::prepend(wchar_t ch, int count)
612 {
613  return insert(0, ch, count);
614 }
615 //-----------------------------------------------------------------------------
616 String& String::replace( int start, int count, const String& str )
617 {
618  remove(start, count);
619  insert(start, str);
620  return *this;
621 }
622 //-----------------------------------------------------------------------------
623 String& String::replace( const String& oldstr, const String& newstr, bool case_sensitive )
624 {
625  acquireData();
626  String supstr = case_sensitive ? *this : toLowerCase();
627  String substr = case_sensitive ? oldstr : oldstr.toLowerCase();
628 
629  std::vector<int> positions;
630  for( int pos = 0; (pos=supstr.find(substr,pos)) != -1; pos += substr.length() )
631  positions.push_back(pos);
632 
633  // replace backwards to support new/old string of different sizes
634  for(unsigned i=(unsigned)positions.size(); i--; )
635  replace(positions[i], oldstr.length(), newstr);
636 
637  return *this;
638 }
639 //-----------------------------------------------------------------------------
640 String& String::replace( int start, int count, wchar_t ch )
641 {
642  acquireData();
643 
644  if (start < 0 )
645  start = 0;
646  if (count < 0)
647  count = length();
648  int end = start + count;
649  if (end > length())
650  end = length();
651  for(int i=start; i<end; ++i)
652  (*mString)[i] = ch;
653  return *this;
654 }
655 //-----------------------------------------------------------------------------
656 String& String::replace( wchar_t old_ch, wchar_t new_ch )
657 {
658  acquireData();
659 
660  for(int i=0; i<length(); ++i)
661  if ((*mString)[i] == old_ch)
662  (*mString)[i] = new_ch;
663  return *this;
664 }
665 //-----------------------------------------------------------------------------
666 int String::count(wchar_t ch, int start) const
667 {
668  // createData();
669  if (empty())
670  return 0;
671 
672  int num = 0;
673  for(int i=start; i<length(); ++i)
674  if ((*mString)[i] == ch)
675  ++num;
676  return num;
677 }
678 //-----------------------------------------------------------------------------
679 int String::count(const String& str, int start) const
680 {
681  // createData();
682  if (empty())
683  return 0;
684 
685  int found = 0;
686  for( int pos = find(str, start); pos != -1; start=pos+str.length(), pos=find(str, start))
687  ++found;
688  return found;
689 }
690 //-----------------------------------------------------------------------------
691 int String::compare(const String& other) const
692 {
693  createData();
694 
695  int min = length() < other.length() ? length() : other.length();
696  for(int i=0; i<min; ++i)
697  {
698  if ( (*mString)[i] != (*other.mString)[i] )
699  return (int)(*mString)[i] - (int)(*other.mString)[i];
700  }
701  // their common subsection is equal, shortest goes first
702  return length() - other.length();
703 }
704 //-----------------------------------------------------------------------------
705 bool String::endsWith(const String& str) const
706 {
707  //createData();
708  if (empty())
709  return false;
710 
711  if (length() < str.length() || empty() || str.empty() )
712  return false;
713  else
714  {
715  int offset = length() - str.length();
716  return memcmp( &(*mString)[0] + offset, &(*str.mString)[0], sizeof((*mString)[0])*str.length() ) == 0;
717  }
718 }
719 //-----------------------------------------------------------------------------
720 bool String::startsWith(const String& str) const
721 {
722  //createData();
723  if (str.empty())
724  return true;
725 
726  if (empty())
727  return false;
728 
729  if (length() < str.length() || empty() || str.empty() )
730  return false;
731  else
732  {
733  return memcmp( &(*mString)[0], &(*str.mString)[0], sizeof((*mString)[0])*str.length() ) == 0;
734  }
735 }
736 //-----------------------------------------------------------------------------
737 bool String::endsWith(wchar_t ch) const
738 {
739  //createData();
740  if (empty())
741  return false;
742 
743  return length() > 0 && (*mString)[length()-1] == ch;
744 }
745 //-----------------------------------------------------------------------------
746 bool String::startsWith(wchar_t ch) const
747 {
748  //createData();
749  if (empty())
750  return false;
751 
752  return length() > 0 && (*mString)[0] == ch;
753 }
754 //-----------------------------------------------------------------------------
756 {
757  //createData();
758  if (empty())
759  return String();
760 
761  String lower = *this;
762  lower.acquireData();
763  for(int i=0; i<length(); ++i)
764  (*lower.mString)[i] = getLowerCase( (*lower.mString)[i] );
765  return lower;
766 }
767 //-----------------------------------------------------------------------------
769 {
770  //createData();
771  if (empty())
772  return String();
773 
774  String lower = *this;
775  lower.acquireData();
776  for(int i=0; i<length(); ++i)
777  (*lower.mString)[i] = getUpperCase( (*lower.mString)[i] );
778  return lower;
779 }
780 //-----------------------------------------------------------------------------
781 String& String::insert(int pos, const String& str)
782 {
783  if (str.empty())
784  return *this;
785 
786  acquireData();
787 
788  if (pos > length())
789  return append(str);
790  int remaining = length() - pos;
791  mString->resize( mString->length() + str.length() );
792  memmove( &(*mString)[0]+pos+str.length(), &(*mString)[0]+pos, sizeof(str[0])*remaining );
793  memcpy( &(*mString)[0]+pos, &(*str.mString)[0], sizeof(str[0])*str.length() );
794  return *this;
795 }
796 //-----------------------------------------------------------------------------
797 String& String::insert(int pos, wchar_t ch, int count)
798 {
799  if (count == 0)
800  return *this;
801 
802  acquireData();
803 
804  if (pos >= length())
805  return append(ch, count);
806  int remaining = length() - pos;
807  mString->resize( mString->length() + count );
808  memmove( &(*mString)[0]+pos+count, &(*mString)[0]+pos, sizeof((*mString)[0])*remaining );
809  for(int i=0; i<count && i+pos<length(); ++i)
810  (*mString)[i+pos] = ch;
811  return *this;
812 }
813 //-----------------------------------------------------------------------------
815 {
816  if (count<0)
817  return substring(0, length()+count);
818  else
819  return substring(0, count);
820 }
821 //-----------------------------------------------------------------------------
823 {
824  if (count<0)
825  return substring(-count, length()+count);
826  else
827  return substring(length()-count, count);
828 }
829 //-----------------------------------------------------------------------------
831 {
832  //createData();
833  if (empty())
834  return String();
835 
836  String path = *this;
837  path.normalizeSlashes();
838  int slash_pos = path.findBackwards('/');
839  if (slash_pos<0)
840  return String();
841  else
842  return path.substring(0,slash_pos+1);
843 }
844 //-----------------------------------------------------------------------------
846 {
847  //createData();
848  if (empty())
849  return String();
850 
851  int a = findBackwards('/');
852  int b = findBackwards('\\');
853  int slash_pos = a > b ? a : b;
854  return substring(slash_pos+1);
855 }
856 //-----------------------------------------------------------------------------
857 String String::extractFileExtension(bool require_dot) const
858 {
859  //createData();
860  if (empty())
861  return String();
862 
863  int dot_pos = findBackwards('.');
864  if (require_dot && dot_pos == -1)
865  return String();
866  else
867  return substring(dot_pos+1);
868 }
869 //-----------------------------------------------------------------------------
870 String String::fromStdWString(const std::wstring& str)
871 {
872  String s;
873  s.acquireData();
874 
875  s.mString->clear();
876  for(int i=0; i<(int)str.length(); ++i)
877  s.mString->push_back( str[i] );
878  return s;
879 }
880 //-----------------------------------------------------------------------------
881 String String::fromStdString(const std::string& str, bool utf8)
882 {
883  if (utf8)
884  return fromUTF8( str.c_str(), (int)str.length());
885  else
886  return fromAscii( str.c_str() );
887 }
888 //-----------------------------------------------------------------------------
889 String String::fromAscii(const char* str, int size)
890 {
891  String s;
892  s.acquireData();
893 
894  if (size<0)
895  size = (int)strlen(str);
896  const unsigned char* ascii = (const unsigned char*)str;
897  s.mString->clear();
898  for(int i=0; i<size; ++i)
899  {
900  if( ascii[i] < 128 )
901  s.mString->push_back( ascii[i] );
902  else
903 
904  s.mString->push_back( L'?' );
905  }
906  /*s.mString->push_back(0);*/
907  return s;
908 }
909 //-----------------------------------------------------------------------------
910 String String::fromUTF16BE(const unsigned short* str, int byte_count)
911 {
912  String s;
913  s.acquireData();
914 
915  VL_COMPILE_TIME_CHECK( sizeof(unsigned short) == 2 )
916  int character_count = byte_count < 0 ? -1 : byte_count / 2;
917 
918  // detect character_count
919  if (character_count<0)
920  for(character_count=0; str[character_count]; ) ++character_count;
921 
922  // skip header
923  if (str[0] == 65534)
924  {
925  str++;
926  --character_count;
927  }
928 
929  s.mString->clear();
930  for(int i=0; i<character_count; ++i)
931  {
932  const unsigned char* bytes = (const unsigned char*)(str+i);
933  unsigned int code = bytes[1] + (bytes[0]<<8);
934  // skip surrogate pair
935  if (code>=0xD800 && code <=0xDC00)
936  {
937  s.mString->push_back( '?' );
938  ++i;
939  }
940  else
941  s.mString->push_back( (wchar_t)code );
942  }
943  return s;
944 }
945 //-----------------------------------------------------------------------------
946 String String::fromUTF16LE(const unsigned short* str, int byte_count)
947 {
948  String s;
949  s.acquireData();
950 
951  VL_COMPILE_TIME_CHECK( sizeof(unsigned short) == 2 )
952  int character_count = byte_count < 0 ? -1 : byte_count / 2;
953 
954  // detect character_count
955  if (character_count<0)
956  for(character_count=0; str[character_count]; ) ++character_count;
957 
958  // skip header
959  if (str[0] == 65279)
960  {
961  str++;
962  --character_count;
963  }
964 
965  s.mString->clear();
966  for(int i=0; i<character_count; ++i)
967  {
968  unsigned char* bytes = (unsigned char*)(str+i);
969  unsigned int code = bytes[0] + (bytes[1]<<8);
970  // skip surrogate pair
971  if (code>=0xD800 && code <=0xDC00)
972  {
973  s.mString->push_back( '?' );
974  ++i;
975  }
976  else
977  s.mString->push_back( (wchar_t)code );
978  }
979  return s;
980 }
981 //-----------------------------------------------------------------------------
982 String String::fromUTF16(const unsigned short* str, int byte_count)
983 {
984  String s;
985  s.acquireData();
986 
987  if (str[0] == 65279)
988  s = fromUTF16LE(str, byte_count);
989  else
990  if (str[0] == 65534)
991  s = fromUTF16BE(str, byte_count);
992  else
993  {
994  Log::error("String::fromUTF16(): not UTF16 BE nor LE found.\n");
995  s.clear();
996  }
997  return s;
998 }
999 //-----------------------------------------------------------------------------
1000 String String::fromUTF8(const char* str, int byte_count)
1001 {
1002  String s;
1003  s.acquireData();
1004 
1005  unsigned char* utf8 = (unsigned char*)str;
1006  int start=0;
1007  // skip header EF BB BF if present
1008  if ( utf8[0] == 0xEF && utf8[1] == 0xBB && utf8[2] == 0xBF )
1009  start=3;
1010  // detect size
1011  if (byte_count<0)
1012  for(byte_count=0; utf8[byte_count]; ) ++byte_count;
1013 
1014  s.mString->clear();
1015  const int UTF8_1BYTE = 128;
1016  const int UTF8_2BYTE = 128+64;
1017  const int UTF8_3BYTE = 128+64+32;
1018  const int UTF8_4BYTE = 128+64+32+16;
1019 
1020  for( int i=start; i<byte_count; ++i )
1021  {
1022  // Unicode Byte1 Byte2 Byte3 Byte4
1023  // U+000000-U+00007F 0xxxxxxx
1024  // U+000080-U+0007FF 110xxxxx 10xxxxxx
1025  // U+000800-U+00FFFF 1110xxxx 10xxxxxx 10xxxxxx
1026  // U+010000-U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1027 
1028  unsigned int unicode_code_point = 0;
1029  if (utf8[i] < UTF8_1BYTE)
1030  unicode_code_point = utf8[i];
1031  else
1032  if ( (utf8[i] & UTF8_3BYTE) == UTF8_2BYTE )
1033  {
1034  unicode_code_point = ((utf8[i]-UTF8_2BYTE)<<6) + (utf8[i+1]&0x3f);
1035  i+=1;
1036  }
1037  else
1038  if ( (utf8[i] & UTF8_4BYTE) == UTF8_3BYTE )
1039  {
1040  unicode_code_point = ((utf8[i]-UTF8_3BYTE)<<12) + ((utf8[i+1]&0x3f)<<6) + (utf8[i+2]&0x3f);
1041  i+=2;
1042  }
1043  else
1044  {
1045  unicode_code_point = ((utf8[i]-UTF8_4BYTE)<<18) + ((utf8[i+1]&0x3f)<<12) + ((utf8[i+2]&0x3f)<<6) + (utf8[i+3]&0x3f);
1046  i+=3;
1047  }
1048 
1049  if (unicode_code_point <= 0xFFFF)
1050  s.mString->push_back((wchar_t)unicode_code_point);
1051  else // characters outside the BMP
1052  s.mString->push_back(L'?');
1053  }
1054  return s;
1055 }
1056 //-----------------------------------------------------------------------------
1057 String String::fromLatin1(const char* str, int character_count)
1058 {
1059  String s;
1060  s.acquireData();
1061 
1062  unsigned char* latin1 = (unsigned char*)str;
1063  if (character_count<0)
1064  for(character_count=0; latin1[character_count]; ) ++character_count;
1065 
1066  s.mString->clear();
1067  for(int i=0; i<character_count; ++i)
1068  s.mString->push_back( latin1_to_unicode[ latin1[i] ] );
1069  return s;
1070 }
1071 //-----------------------------------------------------------------------------
1072 String String::fromPointer(const void* value)
1073 {
1074  char buffer[32];
1075  memset(buffer, 0, sizeof(buffer));
1076  sprintf(buffer, "%p", value);
1077  return fromAscii(buffer);
1078 }
1079 //-----------------------------------------------------------------------------
1081 {
1082  char buffer[256];
1083  memset(buffer, 0, sizeof(buffer));
1084  sprintf(buffer, "%d", value);
1085  return fromAscii(buffer);
1086 }
1087 //-----------------------------------------------------------------------------
1088 String String::fromUInt(unsigned int value)
1089 {
1090  char buffer[256];
1091  memset(buffer, 0, sizeof(buffer));
1092  sprintf(buffer, "%u", value);
1093  return fromAscii(buffer);
1094 }
1095 //-----------------------------------------------------------------------------
1097 {
1098  char buffer[256];
1099  memset(buffer, 0, sizeof(buffer));
1100  sprintf(buffer, "%lld", value);
1101  return fromAscii(buffer);
1102 }
1103 //-----------------------------------------------------------------------------
1104 String String::fromULongLong(unsigned long long value)
1105 {
1106  char buffer[256];
1107  memset(buffer, 0, sizeof(buffer));
1108  sprintf(buffer, "%llu", value);
1109  return fromAscii(buffer);
1110 }
1111 //-----------------------------------------------------------------------------
1112 String String::fromDouble(double value, int decimals)
1113 {
1114  char buffer[256];
1115  memset(buffer, 0, sizeof(buffer));
1116  switch(decimals)
1117  {
1118  case 0: sprintf(buffer, "%.0lf", value); break;
1119  case 1: sprintf(buffer, "%.1lf", value); break;
1120  case 2: sprintf(buffer, "%.2lf", value); break;
1121  case 3: sprintf(buffer, "%.3lf", value); break;
1122  case 4: sprintf(buffer, "%.4lf", value); break;
1123  case 5: sprintf(buffer, "%.5lf", value); break;
1124  case 6: sprintf(buffer, "%.6lf", value); break;
1125  case 7: sprintf(buffer, "%.7lf", value); break;
1126  case 8: sprintf(buffer, "%.8lf", value); break;
1127  case 9: sprintf(buffer, "%.9lf", value); break;
1128  case 10: sprintf(buffer, "%.10lf", value); break;
1129  case 11: sprintf(buffer, "%.11lf", value); break;
1130  case 12: sprintf(buffer, "%.12lf", value); break;
1131  case 13: sprintf(buffer, "%.13lf", value); break;
1132  case 14: sprintf(buffer, "%.14lf", value); break;
1133  case 15: sprintf(buffer, "%.15lf", value); break;
1134  case 16: sprintf(buffer, "%.16lf", value); break;
1135  case 17: sprintf(buffer, "%.17lf", value); break;
1136  case 18: sprintf(buffer, "%.18lf", value); break;
1137  case 19: sprintf(buffer, "%.19lf", value); break;
1138  case 20: sprintf(buffer, "%.20lf", value); break;
1139  default: sprintf(buffer, "%.6lf", value); break;
1140  }
1141  return fromAscii(buffer);
1142 }
1143 //-----------------------------------------------------------------------------
1144 std::wstring String::toStdWString() const
1145 {
1146  //createData();
1147  if (empty())
1148  return std::wstring();
1149 
1150  std::wstring ws;
1151  for(int i=0; i<length(); ++i)
1152  ws += (*mString)[i];
1153  return ws;
1154 }
1155 //-----------------------------------------------------------------------------
1156 std::string String::toStdString() const
1157 {
1158  //createData();
1159  if (empty())
1160  return std::string();
1161  std::string std_string;
1162 
1163  std::vector<unsigned char> utf8;
1164  toUTF8(utf8, false);
1165  if (utf8.size()>1)
1166  {
1167  std_string.resize(utf8.size()-1);
1168  memcpy(&std_string[0], &utf8[0], utf8.size()-1);
1169  }
1170 
1171  return std_string;
1172 }
1173 //-----------------------------------------------------------------------------
1174 void String::toAscii(std::string& ascii, bool translate_non_ascii_chars) const
1175 {
1176  //createData();
1177  if (empty())
1178  {
1179  ascii.clear();
1180  return;
1181  }
1182 
1183  ascii.clear();
1184  if (mString->length())
1185  {
1186  for(int i=0; i<(int)mString->length() && (*mString)[i]; ++i)
1187  {
1188  if ( (*mString)[i] < 128 || !translate_non_ascii_chars )
1189  ascii += (char)((*mString)[i] & 0xFF);
1190  else
1191  {
1192  const char* translation = unicode_to_ascii( (*mString)[i] );
1193  if (translation)
1194  {
1195  for(int j=0; translation[j]; ++j)
1196  ascii += translation[j];
1197  }
1198  else
1199  ascii += '?';
1200  }
1201  }
1202  }
1203  // no need to add the 0 terminator
1204 }
1205 //-----------------------------------------------------------------------------
1206 void String::toUTF8(std::string& str, bool include_utf8_signature) const
1207 {
1208  std::vector<unsigned char> utf8;
1209  toUTF8(utf8, include_utf8_signature);
1210  str.clear();
1211  if (utf8.size())
1212  {
1213  for(int i=0; utf8[i]; ++i)
1214  str.push_back(utf8[i]);
1215  }
1216 }
1217 //-----------------------------------------------------------------------------
1218 void String::toUTF8(std::vector<unsigned char>& utf8, bool include_utf8_signature) const
1219 {
1220  utf8.clear();
1221  if(include_utf8_signature)
1222  {
1223  utf8.push_back(0xEF);
1224  utf8.push_back(0xBB);
1225  utf8.push_back(0xBF);
1226  }
1227 
1228  //createData();
1229  if (empty())
1230  {
1231  utf8.push_back(0);
1232  return;
1233  }
1234 
1235  // Unicode Byte1 Byte2 Byte3 Byte4
1236  // U+000000-U+00007F 0xxxxxxx
1237  // U+000080-U+0007FF 110xxxxx 10xxxxxx
1238  // U+000800-U+00FFFF 1110xxxx 10xxxxxx 10xxxxxx
1239  // U+010000-U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1240  for(int i=0; i<length(); ++i)
1241  {
1242  if ( (*mString)[i] < 0x80)
1243  utf8.push_back( (unsigned char)(*mString)[i] );
1244  else
1245  if ( (*mString)[i] < 0x800)
1246  {
1247  int a = 0xC0 | ((*mString)[i]>>6);
1248  int b = 0x80 | ((*mString)[i]&0x3F);
1249  utf8.push_back( (unsigned char)a );
1250  utf8.push_back( (unsigned char)b );
1251  }
1252  else
1253  {
1254  int a = 0xE0 | ((*mString)[i]>>12);
1255  int b = 0x80 | (((*mString)[i]>>6)&0x3F);
1256  int c = 0x80 | ((*mString)[i]&0x3F);
1257  utf8.push_back( (unsigned char)a );
1258  utf8.push_back( (unsigned char)b );
1259  utf8.push_back( (unsigned char)c );
1260  }
1261  }
1262 
1263  utf8.push_back(0);
1264 }
1265 //-----------------------------------------------------------------------------
1266 void String::toUTF16BE(std::vector<unsigned char>& utf16, bool include_utf16be_signature) const
1267 {
1268  utf16.clear();
1269  if (include_utf16be_signature)
1270  {
1271  utf16.push_back(0xFE);
1272  utf16.push_back(0xFF);
1273  }
1274 
1275  //createData();
1276  if (empty())
1277  {
1278  utf16.push_back(0);
1279  return;
1280  }
1281 
1282  for(int i=0; i<length(); ++i)
1283  {
1284  int x = ((*mString)[i]>>8) & 0xFF;
1285  int y = (*mString)[i] & 0xFF;
1286  utf16.push_back( (unsigned char)x );
1287  utf16.push_back( (unsigned char)y );
1288  }
1289  utf16.push_back(0);
1290 }
1291 //-----------------------------------------------------------------------------
1292 void String::toUTF16LE(std::vector<unsigned char>& utf16, bool include_utf16le_signature) const
1293 {
1294  utf16.clear();
1295  if (include_utf16le_signature)
1296  {
1297  utf16.push_back(0xFF);
1298  utf16.push_back(0xFE);
1299  }
1300 
1301  //createData();
1302  if (empty())
1303  {
1304  utf16.push_back(0);
1305  return;
1306  }
1307 
1308  for(int i=0; i<length(); ++i)
1309  {
1310  int x = (*mString)[i] & 0xFF;
1311  int y = ((*mString)[i]>>8) & 0xFF;
1312  utf16.push_back( (unsigned char)x );
1313  utf16.push_back( (unsigned char)y );
1314  }
1315  utf16.push_back(0);
1316 }
1317 //-----------------------------------------------------------------------------
1318 void String::toLatin1(std::vector<unsigned char>& latin1) const
1319 {
1320  latin1.clear();
1321 
1322  //createData();
1323  if (empty())
1324  {
1325  latin1.push_back(0);
1326  return;
1327  }
1328 
1329  for(int i=0; i<length(); ++i)
1330  {
1331  if ((*mString)[i] < 128)
1332  latin1.push_back((unsigned char)(*mString)[i]);
1333  else
1334  {
1335  // search candidate
1336  int j=128;
1337  for(; latin1_to_unicode[j]; ++j)
1338  {
1339  if ( latin1_to_unicode[j] == (*mString)[i] )
1340  {
1341  latin1.push_back((unsigned char)j);
1342  break;
1343  }
1344  }
1345  if (j==256)
1346  latin1.push_back('?');
1347  }
1348  }
1349  latin1.push_back(0);
1350 }
1351 //-----------------------------------------------------------------------------
1352 int String::toInt(bool hex) const
1353 {
1354  //createData();
1355  if (empty())
1356  return 0;
1357 
1358  if (hex)
1359  {
1360  int i=0;
1361  sscanf(toStdString().c_str(), "%x", &i);
1362  return i;
1363  }
1364  else
1365  return atoi( toStdString().c_str() );
1366 }
1367 //-----------------------------------------------------------------------------
1368 double String::toDouble() const
1369 {
1370  //createData();
1371  if (empty())
1372  return 0.0;
1373 
1374  return atof( toStdString().c_str() );
1375 }
1376 //-----------------------------------------------------------------------------
1377 void String::filterStrings(std::vector<String>& strings, const String& filter)
1378 {
1379  String match = filter;
1380  int filter_type = 0;
1381  bool filter_ok = filter.empty();
1382 
1383  if ( filter.startsWith('*') )
1384  {
1385  filter_type--; // -1
1386  match.remove(0, 1);
1387  filter_ok = true;
1388  }
1389 
1390  if ( filter.endsWith('*') )
1391  {
1392  filter_type++; // +1 or 0
1393  match.remove(match.length()-1, 1);
1394  filter_ok = true;
1395  }
1396 
1397  if ( !filter_ok )
1398  {
1399  Log::error( Say("unacceptable filter '%s'.\n") << filter );
1400  return;
1401  }
1402 
1403  if ( filter_type && filter.length() > 1 )
1404  {
1405  for( int i=(int)strings.size(); i--; )
1406  switch(filter_type)
1407  {
1408  case 0: if( strings[i].find(match) == -1 ) strings.erase( strings.begin() + i ); break;
1409  case -1: if( !strings[i].endsWith(match) ) strings.erase( strings.begin() + i ); break;
1410  case +1: if( !strings[i].startsWith(match) ) strings.erase( strings.begin() + i ); break;
1411  }
1412  }
1413 }
1414 //-----------------------------------------------------------------------------
1415 EStringEncoding String::detectEncoding(const void* str, int byte_count, EStringEncoding default_encoding)
1416 {
1417  const unsigned char* h = (unsigned char*)str;
1418  // UTF32 LE -> FF FE 00 00
1419  // UTF32 BE -> 00 00 FE FF
1420  // UTF8 -> EF BB BF
1421  // UTF16 BE -> FE FF
1422  // UTF16 LE -> FF FE
1423 
1424  if (byte_count>4 && h[0] == 0xFF && h[1] == 0xFE && h[2] == 0 && h[3] == 0 ) return SE_UTF32_LE;
1425  if (byte_count>4 && h[0] == 0 && h[1] == 0 && h[2] == 0xFE && h[3] == 0xFF) return SE_UTF32_BE;
1426  if (byte_count>3 && h[0] == 0xEF && h[1] == 0xBB && h[2] == 0xBF ) return SE_UTF8;
1427  if (byte_count>2 && h[0] == 0xFE && h[1] == 0xFF ) return SE_UTF16_BE;
1428  if (byte_count>2 && h[0] == 0xFF && h[1] == 0xFE ) return SE_UTF16_LE;
1429  return default_encoding;
1430 }
1431 //-----------------------------------------------------------------------------
1432 unsigned short String::getUpperCase(unsigned short ch)
1433 {
1434  for(int i=0; i<107; ++i)
1435  {
1436  if (ch >= case_table_start_min_max[i][1] && ch <= case_table_start_min_max[i][2])
1437  {
1438  int index = ch - case_table_start_min_max[i][1] + case_table_start_min_max[i][0];
1439  return case_table_upper_lower_title[index][0];
1440  }
1441  }
1442  return ch;
1443 }
1444 //-----------------------------------------------------------------------------
1445 unsigned short String::getLowerCase(unsigned short ch)
1446 {
1447  for(int i=0; i<107; ++i)
1448  {
1449  if (ch >= case_table_start_min_max[i][1] && ch <= case_table_start_min_max[i][2])
1450  {
1451  int index = ch - case_table_start_min_max[i][1] + case_table_start_min_max[i][0];
1452  return case_table_upper_lower_title[index][1];
1453  }
1454  }
1455  return ch;
1456 }
1457 //-----------------------------------------------------------------------------
1458 unsigned short String::getTitleCase(unsigned short ch)
1459 {
1460  for(int i=0; i<107; ++i)
1461  {
1462  if (ch >= case_table_start_min_max[i][1] && ch <= case_table_start_min_max[i][2])
1463  {
1464  int index = ch - case_table_start_min_max[i][1] + case_table_start_min_max[i][0];
1465  return case_table_upper_lower_title[index][2];
1466  }
1467  }
1468  return ch;
1469 }
1470 //-----------------------------------------------------------------------------
1471 std::string String::trimStdString(const std::string& text)
1472 {
1473  std::string trimmed;
1474  for(unsigned i=0; i<text.length(); ++i)
1475  {
1476  if(text[i] == ' ' ||
1477  text[i] == '\n' ||
1478  text[i] == '\t' ||
1479  text[i] == '\v' ||
1480  text[i] == '\b' ||
1481  text[i] == '\a' ||
1482  text[i] == '\f' ||
1483  text[i] == '\r' )
1484  continue;
1485  else
1486  {
1487  trimmed = text.c_str() + i;
1488  break;
1489  }
1490  }
1491  int i = (int)trimmed.length();
1492  while( i-- )
1493  {
1494  if(trimmed[i] == ' ' ||
1495  trimmed[i] == '\n' ||
1496  trimmed[i] == '\t' ||
1497  trimmed[i] == '\v' ||
1498  trimmed[i] == '\b' ||
1499  trimmed[i] == '\a' ||
1500  trimmed[i] == '\f' ||
1501  trimmed[i] == '\r' )
1502  continue;
1503  else
1504  break;
1505  }
1506  trimmed.resize( i+1 );
1507  return trimmed;
1508 }
1509 //-----------------------------------------------------------------------------
1510 String String::printf(const char* fmt, ...)
1511 {
1512  std::vector<char> buffer;
1513  buffer.resize(1024 + strlen(fmt));
1514  buffer[0] = 0;
1515 
1516  va_list ap;
1517  va_start(ap, fmt);
1518  vsnprintf(&buffer[0], buffer.size(), fmt, ap);
1519  va_end(ap);
1520  return &buffer[0];
1521 }
1522 //-----------------------------------------------------------------------------
String toLowerCase() const
Returns the lower-case version of a String.
Definition: String.cpp:755
String & prepend(const String &str)
Prepends the specified String to another String.
Definition: String.cpp:606
void toLatin1(std::vector< unsigned char > &latin1) const
Encodes the String into a Latin1 encoded string.
Definition: String.cpp:1318
void createData() const
Definition: String.hpp:565
String extractFileExtension(bool require_dot=true) const
If the String contains a file name or file path the function returns the extension of the file...
Definition: String.cpp:857
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
Definition: pimpl.cpp:97
int findBackwards(wchar_t ch) const
Searches for the specified character chstarting from the end of the string and returns the index of t...
Definition: String.cpp:177
String & trim()
Equivalent to trim("\n\r\t\v "), that is, removes all the tabs, spaces and new-lines from the beginni...
Definition: String.cpp:343
static String fromUTF16(const unsigned short *str, int byte_count=-1)
str must have UTF16 LE or UTF16 BE signature The size of the buffer pointed by &#39;str&#39; must be at least...
Definition: String.cpp:982
void squeeze()
Minimizes the memory buffer used to store the String.
Definition: String.cpp:290
static String fromUInt(unsigned int value)
Creates a string representing the given unsigned integer value.
Definition: String.cpp:1088
int compare(const String &other) const
Performs a lexicographic comparison.
Definition: String.cpp:691
const T * get() const
Definition: Object.hpp:128
An abstract class representing a file.
Definition: VirtualFile.hpp:60
std::wstring toStdWString() const
Returns the std::wstring representation of a String.
Definition: String.cpp:1144
A simple String formatting class.
Definition: Say.hpp:124
String & resize(int character_count)
Resizes the string to the specified character count.
Definition: String.cpp:146
String & reverse()
Reverses the order of the characters in the string.
Definition: String.cpp:521
static String fromLongLong(long long value)
Creates a string representing the given long long value.
Definition: String.cpp:1096
static String fromUTF8(const char *str, int byte_count=-1)
Accepts strings with and without UTF8 signature.
Definition: String.cpp:1000
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
String substring(int start, int count=-1) const
Returns the count characters long substring starting a character index start. If count == -1 the retu...
Definition: String.cpp:153
String & replace(wchar_t old_ch, wchar_t new_ch)
Replaces the character &#39;old_ch&#39; with &#39;new_ch&#39;.
Definition: String.cpp:656
static unsigned short getTitleCase(unsigned short ch)
Returns the title-case version of the specified character.
Definition: String.cpp:1458
static String fromUTF16BE(const unsigned short *str, int byte_count=-1)
Accepts strings with and without UTF16 BE signature Supports natively the characters from the BMP...
Definition: String.cpp:910
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
static String fromInt(int value)
Creates a string representing the given integer value.
Definition: String.cpp:1080
String extractPath() const
If the String contains a file path the function returns the path with trailing slash, without the file name.
Definition: String.cpp:830
void splitLines(std::vector< String > &lines) const
Splits a String into a set of Strings each of which contains a line.
Definition: String.cpp:420
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
Definition: FileSystem.cpp:61
int count(wchar_t ch, int start=0) const
Returns the number of occurrences of the given character after position &#39;start&#39;.
Definition: String.cpp:666
String & operator=(const char *str)
Equivalent to &#39;*this = fromUTF8(str);&#39;.
Definition: String.hpp:390
int findInLargeText(const String &substr, int start=0) const
Searches for the specified string substr starting at position start and returns the index of the firs...
Definition: String.cpp:251
static String fromStdWString(const std::wstring &str)
Initializes the string from a std::string using the fromAscii() function.
Definition: String.cpp:870
String left(int count) const
Returns the count leftmost caracters of a String. If count is negative the function returns all but t...
Definition: String.cpp:814
EStringEncoding
int toInt(bool hex=false) const
Returns the int number represented by the string. The conversion is done using the standard atoi() fu...
Definition: String.cpp:1352
String & normalizeSlashes()
Transform \ slashes in / slashes and removes duplicates.
Definition: String.cpp:534
virtual void close()=0
Closes the file.
static unsigned short getLowerCase(unsigned short ch)
Returns the lower-case version of the specified character.
Definition: String.cpp:1445
void toUTF8(std::vector< unsigned char > &utf8, bool include_utf8_signature=true) const
Encodes the String into a UTF8 encoded string.
Definition: String.cpp:1218
Visualization Library main namespace.
static String fromStdString(const std::string &str, bool utf8=true)
Initializes the string from a std::string using fromUTF() if utf8 == true (default) otherwise uses fr...
Definition: String.cpp:881
String & remove(wchar_t ch, int start=0, int count=-1)
Removes &#39;count&#39; occurrences of the character &#39;ch&#39; after position &#39;start&#39;.
Definition: String.cpp:502
int length() const
Returns the length of the string.
Definition: String.hpp:133
double toDouble() const
Returns the double number represented by the string. The conversion is done using the standard atof()...
Definition: String.cpp:1368
static EStringEncoding detectEncoding(const void *str, int byte_count, EStringEncoding encoding=VL_PLATFORM_DEFAULT_ENCODING)
Detects the encoding.
Definition: String.cpp:1415
void toUTF16LE(std::vector< unsigned char > &utf16, bool include_utf16le_signature=true) const
Encodes the String into a UTF16 little endian encoded string.
Definition: String.cpp:1292
float max(float a, float b)
Definition: Vector2.hpp:311
float min(float a, float b)
Definition: Vector2.hpp:307
static String fromPointer(const void *value)
Creates a string representing the given pointer.
Definition: String.cpp:1072
static String fromAscii(const char *str, int size=-1)
Initializes the string from a 7 bit ascii string.
Definition: String.cpp:889
static String fromUTF16LE(const unsigned short *str, int byte_count=-1)
Accepts strings with and without UTF16 LE signature Supports natively the characters from the BMP...
Definition: String.cpp:946
void acquireData() const
Acquires a private copy of the data if the string has been copied from another one.
Definition: String.hpp:556
VL_COMPILE_TIME_CHECK(sizeof(i8) *8==8)
String & append(const String &other)
Appends the specified String to another String.
Definition: String.cpp:597
bool empty() const
Returns true if length() == 0.
Definition: String.hpp:136
static String loadText(const String &path, EStringEncoding encoding=VL_PLATFORM_DEFAULT_ENCODING)
Loads a String from the specified path.
Definition: String.cpp:86
void split(wchar_t separator, std::vector< String > &fields, bool remove_empty_fields=false) const
Splits a String into a set of fields. The fields are separated by the specified separator and are ret...
Definition: String.cpp:386
bool startsWith(const String &str) const
Returns true if a String starts with the specified String str.
Definition: String.cpp:720
static String fromLatin1(const char *str, int character_count=-1)
The size of the buffer pointed by &#39;str&#39; must be at least &#39;character_count&#39; bytes large or null termin...
Definition: String.cpp:1057
bool contains(wchar_t ch) const
Returns true if a String contains the specified character.
Definition: String.cpp:212
int find(wchar_t ch, int start=0) const
Searches for the specified character ch starting at position start and returns the index of the first...
Definition: String.cpp:217
String extractFileName() const
If the String contains a file path the function returns the file name without the path...
Definition: String.cpp:845
void toAscii(std::string &ascii, bool translate_non_ascii_chars=true) const
Provides some basic character translation of code points outside of the ASCII range.
Definition: String.cpp:1174
static void filterStrings(std::vector< String > &strings, const String &filter)
Filters the specified Strings using the given filter. The filter must be of the type "*abc"...
Definition: String.cpp:1377
static unsigned short getUpperCase(unsigned short ch)
Returns the upper-case version of the specified character.
Definition: String.cpp:1432
static String fromULongLong(unsigned long long value)
Creates a string representing the given unsigned long long value.
Definition: String.cpp:1104
static std::string trimStdString(const std::string &text)
Remove the spaces before and after an std::string.
Definition: String.cpp:1471
String()
Constructor.
Definition: String.cpp:47
static String fromDouble(double value, int decimals=6)
Creates a string representing the given double value The value of &#39;decimals&#39; can be between 0 and 20...
Definition: String.cpp:1112
String toUpperCase() const
Returns the upper-case version of a String.
Definition: String.cpp:768
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
String right(int count) const
Returns the count rightmost caracters of a String. If count is negative the function returns all but ...
Definition: String.cpp:822
void toUTF16BE(std::vector< unsigned char > &utf16, bool include_utf16be_signature=true) const
Encodes the String into a UTF16 big endian encoded string.
Definition: String.cpp:1266
static String printf(const char *fmt,...)
Returns a formatted string using the legacy printf syntax. The resulting string can be maximum 1024 +...
Definition: String.cpp:1510
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
bool endsWith(const String &str) const
Returns true if a String ends with the specified String str.
Definition: String.cpp:705
long long load(std::vector< char > &data)
Loads the entire file in the specified vector.
String & insert(int pos, const String &str)
Inserts str at position pos.
Definition: String.cpp:781
String & clear()
Clears the string.
Definition: String.hpp:142
String field(wchar_t separator, int field_index) const
Splits a String into a set of fields based on the specified separator and returns the filed at positi...
Definition: String.cpp:453
String & fill(wchar_t ch)
Fills the string with the specified character ch.
Definition: String.cpp:298