Free Electron
String.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __platform_string_h__
8 #define __platform_string_h__
9 
10 namespace fe
11 {
12 
13 #define FESTRING_DEBUG FALSE
14 #define FESTRING_LOCALSIZE 16 //* unshared for small strings
15 
16 #ifdef HAS_MEMRCHR
17 #define FEMEMRCHR(s,c,n) memrchr(s,c,n)
18 #else
19 inline void *fe_memrchr(const void *s, int c, size_t n)
20 {
21  char* r=(char*)s+n;
22  while(r>=s && *r!=c) { r--; }
23  return r<s? NULL: r;
24 }
25 #define FEMEMRCHR(s,c,n) fe_memrchr(s,c,n)
26 #endif
27 
28 #if FE_OS==FE_WIN32 || FE_OS==FE_WIN64
29 //#define FESTRLEN_MB(x,y) _mbstrlen((char *)x)
30 #define FESTRCMP_MB(x,y) _mbscmp(x,y)
31 #define FESTRNCMP_MB(x,y,z) _mbsncmp(x,y,z)
32 #define FESTR_MB2UPPER(x) _mbsupr((unsigned char*)x)
33 #define FESTR_MB2LOWER(x) _mbslwr((unsigned char*)x)
34 #define FEVSNPRINTF(x,y,z,a) _vsnprintf(x,y,z,a)
35 #define FESTRCPY(dest,size,src) strcpy_s((char *)dest,size,(char *)src)
36 #else
37 #define FEVSNPRINTF(x,y,z,a) vsnprintf(x,y,z,a)
38 #define FESTRCPY(dest,size,src) strcpy((char *)dest,(char *)src)
39 #endif
40 
41 #if defined(__linux__) || FE_OS==FE_OSX
42 //#define FESTRLEN_MB(x,y) mblen((char *)x,(FE_UWORD)y)
43 #define FESTRCMP_MB(x,y) strcmp((char *)x,(char *)y)
44 #define FESTRNCMP_MB(x,y,z) strncmp((char *)x,(char *)y,z)
45 #endif
46 
47 #if defined(FE_OS) && FE_OS==FE_FREEBSD
48 #define FESTRCMP_MB(x,y) strcmp((char *)x,(char *)y)
49 #define FESTRNCMP_MB(x,y,z) strncmp((char *)x,(char *)y,z)
50 #endif
51 
52 #define FESTRLEN(x) strlen((char *)x)
53 
54 #define FESTRING_I8 char // presumably 7-bit ASCII
55 #define FESTRING_U8 unsigned char // presumably multibyte
56 
57 #if FE_SSE>=1 && FE_COMPILER==FE_GNU
58 //#define FE_SSE_STRING_GNU
59 typedef int v4si __attribute__ ((vector_size (16)));
60 #endif
61 
62 //* convert macro to String
63 #define FE_STRING2(x) #x
64 #define FE_STRING(x) FE_STRING2(x)
65 
66 //* TODO consider deriving from std::string now that it has
67 //* short string optimization
68 
69 //* WARNING short strings are thread-safe, but rep strings are not
70 //* TODO atomic reference counting on Rep for thread-safe sharing
71 
72 /**************************************************************************//**
73  @brief Automatically reference-counted string container.
74 
75  @ingroup platform
76 
77  Designed to behave as a native type, like float or int.
78  All allocation worries are completely hidden.
79 
80  To assign a string just use simple assignments.
81  @code
82  String name("me");
83  name="you";
84  String id=name;
85  @endcode
86 
87  You can compare strings in a boolean or lexical fashion.
88  @code
89  if(name!="Bob" && name.compare("M")<0)
90  ...
91  @endcode
92 
93  To print a string in printf fashion, use c_str().
94  @code
95  printf("%s\n",name.c_str());
96  @endcode
97 
98  Although the String encoding may start like a (char*) byte-wise,
99  you should always use the c_str() method in conjunction
100  with C-style string operations,
101  especially variable argument functions like *printf.
102 
103  A String object is 32 bytes.
104  Strings shorter than FESTRING_LOCALSIZE (currently 16),
105  including terminator,
106  are stored in a local buffer and compared quickly as two 64-bit words
107  or as a single 128-bit word, depending on the compiler.
108  Longer strings are allocated and can be shared in assignment.
109 
110  We would prefer to derive fe::String from std::string,
111  just adding fe methods to the std::string buffer handling.
112  But, as of Feb 2021, on gcc 8.3.0, same size small string operator==()
113  is 3 times faster with fe::String than std::string.
114  Also, std::string is forbidden from being ref counted,
115  so passing std::string as an argument is a deep copy every time.
116  You don't don't need a full mutex to protect the ref count,
117  but a swap increment appears to take about 4ns (in 2021).
118  The alternative of a deep copy on every string copy can be
119  a little less, or a much much more, depending on the string length.
120  But, for the sake of conformance, this task will likely happen eventually.
121 
122  As a tight core class, String doesn't carry virtual functions.
123 
124  @note Based on Coral GPL_String
125  @note Reference: Stroustrup C++ Ref Man, 2nd ed., pg. 248
126  @note operator cast to (char*) intentionally omitted
127 *//***************************************************************************/
128 class FE_DL_PUBLIC String
129  {
130  private:
131 
132  class FE_DL_PUBLIC Rep
133  {
134  public:
135  void newBuffer(U32 size);
136  void deleteBuffer(void);
137 
138  I32 m_references;
139  FESTRING_U8* m_pBuffer;
140  };
141 
142  public:
143  /// Construct an empty string.
144  String(void);
145 
146  /// Copy constructor.
147  String(const String &operand);
148 
149  /// Construct using a signed byte buffer.
150  String(const FESTRING_I8* operand);
151 
152  /// Construct using a unsigned byte buffer.
153  String(const FESTRING_U8* operand);
154 
155  /// allow init as 0 in templates
156  String(int operand);
157 
158  ~String(void);
159 
160 #if FALSE //* Meyers More Effective C++ #5: No!
161  //* http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/aw/meyerscddemo/demo/mec/m.htm#5970
162  /** Cast the contents of the 8-bit buffer as signed
163  bytes. */
164  operator const FESTRING_I8 *(void) const
165  { return c_str(); }
166 
167  /** Cast the contents of the 8-bit buffer as
168  unsigned bytes. */
169  operator const FESTRING_U8 *(void) const
170  { return rawU8(); }
171 #endif
172 
173  /// Compare to another String.
174  String& operator=(const String& operand);
175 
176  /// Compare to a signed byte buffer (using 8-bit).
177  String& operator=(const FESTRING_I8* operand)
178  { return operator=((const FESTRING_U8 *)operand); };
179 
180  /// Compare to an unsigned byte buffer (using 8-bit).
181  String& operator=(const FESTRING_U8* operand);
182 
183  /// checks if the string is equivalent
184  BWORD equals(const String &operand) const;
185 
186  /** Standard string compare: returns -1, 0, or 1 if the
187  string is alphabetically less than, equal,
188  or greater than the operand */
189  I32 compare(const String &operand) const;
190 
191  BWORD operator<(const String &operand) const
192  { return compare(operand) < 0; }
193 
194  /** Return the substring preceding the last '/'
195 
196  If there is no '/', no text is returned. */
197  String pathname(void) const;
198 
199  /** Return the substring following the last '/'
200 
201  If there is no '/', the entire text is returned. */
202  String basename(void) const;
203 
204  /** Return the substring after the prefix
205 
206  If the string doesn't begin with the prefix,
207  the original text is returned. */
208  String prechop(const String& prefix) const;
209 
210  /** Return the substring without trailing characters
211 
212  This version does not care what the
213  characters are */
214  String prechop(I32 count) const;
215 
216  /** Return the substring before the suffix
217 
218  If the string doesn't end with the suffix,
219  the original text is returned. */
220  String chop(const String& suffix) const;
221 
222  /** Return the substring without trailing characters
223 
224  This version does not care what the
225  characters are */
226  String chop(I32 count) const;
227 
228  /// Returns TRUE if string contains the substring
229  BWORD contains(String find) const;
230 
231  /// Return a string with replaced substrings
232  String substitute(String find,String replace) const;
233 
234  /** Return a string with enviroment substitution
235 
236  Replace substrings like $VARIABLE and ${VARIABLE}
237  with environment variables and or a map.
238 
239  Without arguments, only environment variables
240  are used for substitution.
241 
242  A map can be provided for non-environment variables.
243  In that case, the environment variable can
244  optionally also be checked when a variable is
245  not in the map.
246 
247  If set to throw missing, a exception is thrown
248  is a variable is found that can't be resolved.
249  */
250  String substituteEnv(
251  std::map<String,String>& a_rMap,
252  BWORD a_alsoUseEnv=FALSE,
253  BWORD a_throwMissing=FALSE) const;
254  String substituteEnv(void)
255  {
256  std::map<String,String> map;
257  return substituteEnv(map,TRUE,FALSE);
258  }
259 
260  /** Return a string with sections removed
261 
262  Each substring beginning with the given start
263  up to the given end is removed.
264 
265  If either of the keep options is on,
266  the associated delimiting string is retained.
267  */
268  String stripComments(String a_start="/*",String a_end="*/",
269  BWORD a_keepStart=FALSE,BWORD a_keepEnd=FALSE);
270 
271  /** Compares to another string assuming the given
272  string is a dot-delimited ordered list containing
273  optional substrings.
274  Returns true if strings are exactly the same, or if
275  they match only up to the length of the operand
276  and the operand's terminating zero matches a
277  period. */
278  BWORD dotMatch(const String &operand) const;
279 
280  /// Force all applicable characters to upper case.
281  void forceUppercase(void) { forceCase(true); };
282  /// Force all applicable characters to lower case.
283  void forceLowercase(void) { forceCase(false); };
284 
285  /** Return the number of represented characters,
286  but not necessarily the size of any buffer. */
287  U32 length(void) const;
288 
289  /// Returns true if the contents have zero length
290  BWORD empty(void) const;
291 
292  /// Populate the string in the manner of sprintf().
293  String& sPrintf(const char* fmt, ...);
294 
295  /** Populate the string as with sPrintf(),
296  but by concatenating the results to the
297  existing string. */
298  String& catf(const char* fmt, ...);
299 
300  /// Append the current String with the given text
301  String& cat(const char* operand);
302 
303  /// Append the current String with the given String
304  String& cat(const String& operand);
305 
306  /** Concatenate the strings in a list. */
307  String& cat(std::list<String> &strList, String sep = "");
308 
309  /** Add or remove characters to set the string length
310 
311  If expanded, the given character is used
312  to pad the string. */
313  void resize(U32 size,char c=' ');
314 
315  /** Return the string, adding quotes if it contains
316  a likely delimiter */
317  String maybeQuote(String beginQuote,String endQuote) const;
318  String maybeQuote(String quote="\"") const
319  { return maybeQuote(quote,quote); }
320 
321  /** Return the string,
322  removing outer quotes if they exist */
323  String maybeUnQuote(String beginQuote,String endQuote) const;
324  String maybeUnQuote(String quote="\"") const
325  { return maybeUnQuote(quote,quote); }
326 
327  String parse(String quote="\"", String delimiters=" \t\n",
328  BWORD eachDelimiter=FALSE);
329 
330  I32 lines(void) const;
331  String line(I32 a_lineNumber) const;
332 
333 static String join(const String &a_sep,
334  std::list<String> &a_list);
335 
336 static String join(const String &a_sep,
337  const String &a_1,
338  const String &a_2);
339 
340 static String join(const String &a_sep,
341  const String &a_1,
342  const String &a_2,
343  const String &a_3);
344 
345  /** @brief Populate using variable arg format
346 
347  @internal */
348  String& vsPrintf(const char* fmt,va_list ap,int& size);
349 
350  /** Return the contents of the 8-bit buffer cast as
351  signed bytes. */
352 const FESTRING_I8* c_str(void) const { return (FESTRING_I8*)rawU8(); };
353  /** Return the contents of the 8-bit buffer cast as
354  unsigned bytes. */
355 const FESTRING_U8* rawU8(void) const
356  { FEASSERT(!m_pRep || m_pRep->m_pBuffer);
357  return m_pRep? m_pRep->m_pBuffer: m_pLocal; }
358 
359  /** @todo: string serialization currently hacked in.
360  only works for 8bit and does too much copying */
361  void output(std::ostream &ostrm) const;
362  void input(std::istream &istrm);
363 
364  String& operator+=(const String& operand)
365  { return cat(operand); }
366 
367  int integer(void) const;
368  Real real(void) const;
369  bool match(const String a_pattern) const;
370  bool search(const String a_pattern) const;
371  String replace(const String a_pattern,
372  const String a_replacement) const;
373  String convertGlobToRegex(void) const;
374 
375  /// Compute Fowler-Noll-Vo hash function (64-bit FNV-1)
376  U64 computeFowlerNollVo1(void) const;
377 
378  /** Sort an Array of Strings
379 
380  Array<String> keys=getSomeUnorderedKeys();
381 
382  std::sort(keys.begin(),keys.end(),String::Sort());
383  */
384  struct Sort
385  {
386  bool operator()(const String& rString1,const String& rString2)
387  {
388  return (rString1.compare(rString2)<0);
389  }
390  };
391 
392  private:
393  FESTRING_U8* buffer(void)
394  { FEASSERT(!m_pRep || m_pRep->m_pBuffer);
395  return m_pRep? m_pRep->m_pBuffer: m_pLocal; }
396 
397  void create(const FESTRING_I8* operand);
398 
399  void init(void);
400 
401  void forceCase(BWORD upper);
402 
403  Rep* newRep(void);
404  void deleteRep(void);
405 
406 #ifdef FE_SSE_STRING_GNU
407  union
408  {
409  v4si m_simd;
410  FESTRING_U8 m_pLocal[FESTRING_LOCALSIZE];
411  };
412 #elif FE_CPLUSPLUS >= 201103L
413  alignas(16)
414  FESTRING_U8 m_pLocal[FESTRING_LOCALSIZE];
415 #else
416  FESTRING_U8 m_pLocal[FESTRING_LOCALSIZE];
417 #endif
418  I32 m_length;
419  Rep* m_pRep;
420  };
421 
422 inline String::String(void)
423 {
424  init();
425 }
426 
427 inline void String::init(void)
428 {
429  m_length=0;
430  m_pRep=NULL;
431  memset(m_pLocal,0,FESTRING_LOCALSIZE);
432 }
433 
434 inline String::String(const String& operand)
435 {
436  init();
437  operator=(operand);
438 }
439 
440 inline void String::create(const FESTRING_I8* operand)
441 {
442  m_length=FESTRLEN(operand);
443  U32 bytes=m_length+1;
444  if(bytes<=FESTRING_LOCALSIZE)
445  {
446  m_pRep=NULL;
447  FESTRCPY(m_pLocal,FESTRING_LOCALSIZE,operand);
448  if(bytes<FESTRING_LOCALSIZE)
449  {
450  memset(m_pLocal+bytes,0,FESTRING_LOCALSIZE-bytes);
451  }
452  }
453  else
454  {
455  m_pRep=newRep();
456  m_pRep->newBuffer(bytes);
457  FEASSERT(m_pRep->m_pBuffer);
458  FESTRCPY(m_pRep->m_pBuffer,bytes,operand);
459  memset(m_pLocal,0,FESTRING_LOCALSIZE);
460  }
461 }
462 
463 inline String::String(const FESTRING_I8* operand)
464 {
465  if(!operand)
466  {
467  init();
468  return;
469  }
470  create(operand);
471 #if FESTRING_DEBUG
472  if(m_pRep)
473  {
474  fe_fprintf(stderr,
475  "String::String(FESTRING_I8*) create 0x%p 0x%p \"%s\"\n",
476  this,m_pRep,m_pRep->m_pBuffer);
477  }
478 #endif
479 }
480 
481 inline String::String(const FESTRING_U8* operand)
482 {
483  if(!operand)
484  {
485  init();
486  return;
487  }
488  create((const FESTRING_I8*)operand);
489 #if FESTRING_DEBUG
490  if(m_pRep)
491  {
492  fe_fprintf(stderr,
493  "String::String(FESTRING_U8*) create 0x%p 0x%p \"%s\"\n",
494  this,m_pRep,m_pRep->m_pBuffer);
495  }
496 #endif
497 }
498 
499 inline String::String(int operand)
500 {
501 #if FE_OS==FE_WIN32 || FE_OS==FE_WIN64
502  sprintf_s((FESTRING_I8*)m_pLocal,16,"%-15d",operand);
503 #else
504  sprintf((FESTRING_I8*)m_pLocal,"%-15d",operand);
505 #endif
506  m_length=FESTRLEN(m_pLocal);
507  m_pRep=NULL;
508 }
509 
510 inline String::~String(void)
511 {
512  if(m_pRep)
513  {
514  FEASSERT(m_pRep->m_references>0);
515 
516 #ifdef FE_COUNT_ASM_IMPL
517  if(!(feAsmSwapIncr((int*)(&m_pRep->m_references),-1)-1))
518 #else
519  if(--m_pRep->m_references == 0)
520 #endif
521  {
522 #if FESTRING_DEBUG
523  fe_fprintf(stderr,"~String destroy 0x%p 0x%p \"%s\"\n",
524  this,m_pRep,m_pRep->m_pBuffer);
525 #endif
526  deleteRep();
527  }
528  }
529 }
530 
531 inline String &String::operator=(const FESTRING_U8* operand)
532 {
533  if(m_pRep)
534  {
535  FEASSERT(m_pRep->m_references>0);
536 
537 #ifdef FE_COUNT_ASM_IMPL
538  if(!(feAsmSwapIncr((int*)(&m_pRep->m_references),-1)-1))
539 #else
540  if(--m_pRep->m_references == 0)
541 #endif
542  {
543 #if FESTRING_DEBUG
544  fe_fprintf(stderr,"String::operator=(FESTRING_U8*)"
545  " destroy 0x%p 0x%p \"%s\"\n",
546  this,m_pRep,m_pRep->m_pBuffer);
547 #endif
548  deleteRep();
549  }
550 
551  m_pRep=NULL;
552 
553 /*
554  // still in use elsewhere
555  if(m_pRep->m_references>1)
556  {
557  // abandon old m_pRep (other ref will clean)
558  m_pRep->m_references--;
559  m_pRep=NULL;
560  }
561  else
562  {
563 #if FESTRING_DEBUG
564  fe_fprintf(stderr,"String::operator=(FESTRING_U8*)"
565  " destroy 0x%p 0x%p \"%s\"\n",
566  this,m_pRep,m_pRep->m_pBuffer);
567 #endif
568  deleteRep();
569  }
570 */
571  }
572 
573  create((const FESTRING_I8*)operand);
574 #if FESTRING_DEBUG
575  if(m_pRep)
576  {
577  fe_fprintf(stderr,"String::operator=(FESTRING_U8*) create 0x%p 0x%p %s\n",
578  this,m_pRep,m_pRep->m_pBuffer);
579  }
580 #endif
581  return *this;
582 }
583 
584 inline String &String::operator=(const String &operand)
585 {
586  // protect against string=string
587  if(operand.m_pRep)
588  {
589  FEASSERT(operand.m_pRep->m_references>=0);
590 
591 #ifdef FE_COUNT_ASM_IMPL
592  feAsmIncr((int*)(&operand.m_pRep->m_references),1);
593 #else
594  operand.m_pRep->m_references++;
595 #endif
596  }
597 
598  if(m_pRep)
599  {
600  FEASSERT(m_pRep->m_references>0);
601 
602 #ifdef FE_COUNT_ASM_IMPL
603  if(!(feAsmSwapIncr((int*)(&m_pRep->m_references),-1)-1))
604 #else
605  if(--m_pRep->m_references == 0)
606 #endif
607  {
608 #if FESTRING_DEBUG
609  fe_fprintf(stderr,
610  "String::operator=(String) destroy 0x%p 0x%p \"%s\"\n",
611  this,m_pRep,m_pRep->m_pBuffer);
612 #endif
613  deleteRep();
614  }
615  }
616 
617  m_length=operand.m_length;
618 
619  if(m_pLocal==operand.m_pLocal)
620  {
621 #if FESTRING_DEBUG
622  fe_fprintf(stderr,"String::operator=(FESTRING_U8*)"
623  " string=string (local) \"%s\"\n",m_pLocal);
624 #endif
625  return *this;
626  }
627 
628  FEASSERT(m_pLocal>operand.m_pLocal+FESTRING_LOCALSIZE ||
629  operand.m_pLocal>m_pLocal+FESTRING_LOCALSIZE);
630 
631 // memcpy(m_pLocal,operand.m_pLocal,FESTRING_LOCALSIZE);
632 
633 #if FE_CPLUSPLUS >= 201103L
634  U64* p1=reinterpret_cast<U64*>(m_pLocal);
635  const U64* p2=reinterpret_cast<const U64*>(operand.m_pLocal);
636  p1[0]=p2[0];
637  p1[1]=p2[1];
638 #else
639  U32* p1=reinterpret_cast<U32*>(m_pLocal);
640  const U32* p2=reinterpret_cast<const U32*>(operand.m_pLocal);
641  p1[0]=p2[0];
642  p1[1]=p2[1];
643  p1[2]=p2[2];
644  p1[3]=p2[3];
645 #endif
646 
647  m_pRep=operand.m_pRep;
648 
649 #if FESTRING_DEBUG
650  if(m_pRep)
651  {
652  fe_fprintf(stderr,
653  "String::operator=(FESTRING_U8*)"
654  " copy 0x%p 0x%p \"%s\"\n",
655  this,m_pRep,m_pRep->m_pBuffer);
656  }
657 #endif
658  return *this;
659 }
660 
661 //* TODO check that this works for multibyte
662 inline U32 String::length(void) const
663 {
664  return m_length;
665 }
666 
667 inline BWORD String::empty(void) const
668 {
669  return !m_pLocal[0] && !m_pRep;
670 }
671 
672 #if defined(__GNUC__)
673 #pragma GCC diagnostic push
674 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
675 #endif
676 
677 #if defined(__GNUC__) && ( __GNUC__==4 && __GNUC_MINOR__>=2 && __GNUC_MINOR__<5)
678 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
679 #endif
680 inline BWORD String::equals(const String &operand) const
681 {
682  if(m_length!=operand.m_length)
683  {
684  return FALSE;
685  }
686 
687 #if FESTRING_LOCALSIZE==16
688  if(!m_pRep && !operand.m_pRep)
689  {
690 #ifdef FE_SSE_STRING_GNU
691  //* 4xI32 compare -> for each 32 bits, all set if equal, all zero if not
692  v4si comp=__builtin_ia32_pcmpeqd128(
693  *(v4si*)m_pLocal,
694  *(v4si*)operand.m_pLocal);
695 
696  U32* pComp4=reinterpret_cast<U32*>(&comp);
697 
698 #if FALSE
699  fe_printf("pComp4 0x%x 0x%x 0x%x 0x%x\n",
700  pComp4[0],pComp4[1],pComp4[2],pComp4[3]);
701 
702  long unsigned int* pComp2=reinterpret_cast<long unsigned int*>(&comp);
703  fe_printf("\n\"%s\" \"%s\" %d\n",m_pLocal,operand.m_pLocal,
704  !~(pComp2[0]&pComp2[1]));
705 #endif
706 
707  //* NOTE 64-bit int version does not optimize correctly
708 // return ((pComp2[0]&pComp2[1])==0xFFFFFFFFFFFFFFFF);
709 // return (!~(pComp2[0]&pComp2[1]));
710 
711 // return ((pComp4[0]&pComp4[1]&pComp4[2]&pComp4[3])==0xFFFFFFFF);
712  return (!~(pComp4[0]&pComp4[1]&pComp4[2]&pComp4[3]));
713 #elif FE_CPLUSPLUS >= 201103L
714  const U64* p1=reinterpret_cast<const U64*>(m_pLocal);
715  const U64* p2=reinterpret_cast<const U64*>(operand.m_pLocal);
716  return (p1[0]==p2[0] && p1[1]==p2[1]);
717 #else
718 
719  const U32* p1=reinterpret_cast<const U32*>(m_pLocal);
720  const U32* p2=reinterpret_cast<const U32*>(operand.m_pLocal);
721  return (p1[0]==p2[0] && p1[1]==p2[1] &&
722  p1[2]==p2[2] && p1[3]==p2[3]);
723 #endif
724  }
725 #endif
726 
727  return !FESTRCMP_MB(rawU8(),operand.rawU8());
728 }
729 
730 #if defined(__GNUC__)
731 #pragma GCC diagnostic pop
732 #endif
733 
734 inline I32 String::compare(const String &operand) const
735 {
736  return FESTRCMP_MB(rawU8(),operand.rawU8());
737 }
738 
739 inline String& String::cat(const String& operand)
740 {
741  return cat(operand.c_str());
742 }
743 
744 /// Compare two String's
745 inline BWORD operator == (const String& s1, const String& s2)
746 {
747  return s1.equals(s2);
748 }
749 
750 /// Compare a byte buffer to an String
751 inline BWORD operator == (const char* s1, const String& s2)
752 {
753  return ((const String)s1).equals(s2);
754 }
755 
756 /// Compare an String to a byte buffer
757 inline BWORD operator == (const String& s1, const char* s2)
758 {
759  return s1.equals((const String)s2);
760 }
761 
762 /// Compare two String's (reverse logic)
763 inline BWORD operator != (const String& s1, const String& s2)
764 {
765  return !s1.equals(s2);
766 }
767 
768 /// Compare a byte buffer to an String (reverse logic)
769 inline BWORD operator != (const char* s1, const String& s2)
770 {
771  return !((const String)s1).equals(s2);
772 }
773 
774 /// Compare an String to a byte buffer (reverse logic)
775 inline BWORD operator != (const String& s1, const char* s2)
776 {
777  return !s1.equals((const String)s2);
778 }
779 
780 inline String operator+(const String& s1, const String& s2)
781 {
782  String result=s1;
783  return result.cat(s2);
784 }
785 
786 inline String operator+(const String& s1, const int& i)
787 {
788  String result;
789  return result.sPrintf("%s%d",s1.c_str(),i);
790 }
791 
792 inline String operator+(const int& i, const String& s1)
793 {
794  String result;
795  return result.sPrintf("%d%s",i,s1.c_str());
796 }
797 
798 inline String operator+(const String& s1, const float& f)
799 {
800  String result;
801  return result.sPrintf("%s%.6G",s1.c_str(),f);
802 }
803 
804 inline String operator+(const float& f, const String& s1)
805 {
806  String result;
807  return result.sPrintf("%.6G%s",f,s1.c_str());
808 }
809 
810 /**************************************************************************//**
811  @brief Return a string for an FE_ERRNO code.
812 
813  @ingroup platform
814 *//***************************************************************************/
815 FE_DL_PUBLIC String errorString(int errnum);
816 
817 inline String print(const String& a_rString)
818 {
819  return a_rString;
820 }
821 
822 inline String print(char* a_buffer)
823 {
824  return String(a_buffer);
825 }
826 
827 inline String print(U32 a_integer)
828 {
829  String text;
830  text.sPrintf("%d",a_integer);
831  return text;
832 }
833 
834 inline String print(I32 a_integer)
835 {
836  String text;
837  text.sPrintf("%d",a_integer);
838  return text;
839 }
840 
841 #if FALSE
842 inline String print(int a_integer)
843 {
844  String text;
845  text.sPrintf("%d",a_integer);
846  return text;
847 }
848 #endif
849 
850 inline String print(F32 a_float)
851 {
852  String text;
853  text.sPrintf("%.6G",a_float);
854  return text;
855 }
856 
857 inline String print(F64 a_double)
858 {
859  String text;
860  text.sPrintf("%.6G",a_double);
861  return text;
862 }
863 
864 /** @fn const FESTRING_I8* c_print(const T& t)
865 
866  @brief Converts any object to a char* buffer
867 
868  The argument type must support:
869 
870  @code
871  String print(const T&);
872  @endcode
873 
874  The returned buffer is not persistent and can be invalid
875  after the statement.
876  It should be only used immediately such as within a printf() statement.
877 
878  This function may be implemented with a macro.
879 */
880 #define c_print(x) fe::print(x).c_str()
881 
882 } /* namespace */
883 
884 #endif /* __platform_string_h__ */
const FESTRING_I8 * c_str(void) const
Return the contents of the 8-bit buffer cast as signed bytes.
Definition: String.h:352
void forceLowercase(void)
Force all applicable characters to lower case.
Definition: String.h:283
Sort an Array of Strings.
Definition: String.h:384
String & operator=(const String &operand)
Compare to another String.
Definition: String.h:584
kernel
Definition: namespace.dox:3
void vsPrintf(std::string &target, const char *fmt, va_list ap, int &size)
Format text into a fe::String.
Definition: debug.cc:252
BWORD operator!=(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s (reverse logic)
Definition: DualString.h:229
String errorString(int error)
Return a string for an FE_ERRNO code.
Definition: String.cc:1040
I32 compare(const String &operand) const
Standard string compare: returns -1, 0, or 1 if the string is alphabetically less than...
Definition: String.h:734
BWORD operator==(const DualString &s1, const DualString &s2)
Compare two DualString&#39;s.
Definition: DualString.h:208
void forceUppercase(void)
Force all applicable characters to upper case.
Definition: String.h:281
const FESTRING_U8 * rawU8(void) const
Return the contents of the 8-bit buffer cast as unsigned bytes.
Definition: String.h:355
String & cat(const char *operand)
Append the current String with the given text.
Definition: String.cc:545
BWORD empty(void) const
Returns true if the contents have zero length.
Definition: String.h:667
String & sPrintf(const char *fmt,...)
Populate the string in the manner of sprintf().
Definition: String.cc:529
Automatically reference-counted string container.
Definition: String.h:128
BWORD equals(const String &operand) const
checks if the string is equivalent
Definition: String.h:680
String & operator=(const FESTRING_I8 *operand)
Compare to a signed byte buffer (using 8-bit).
Definition: String.h:177
String(void)
Construct an empty string.
Definition: String.h:422
U32 length(void) const
Return the number of represented characters, but not necessarily the size of any buffer.
Definition: String.h:662