gstr.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gstr.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gstr.h"
23 #include "gdebug.h"
24 #include <cmath>
25 #include <algorithm>
26 #include <functional>
27 #include <ctype.h>
28 #include <iomanip>
29 #include <climits>
30 #include <string>
31 #include <sstream>
32 
33 std::string G::Str::escaped( const std::string & s_in , const std::string & specials , char c_escape )
34 {
35  std::string s( s_in ) ;
36  escape( s , specials , c_escape ) ;
37  return s ;
38 }
39 
40 void G::Str::escape( std::string & s , const std::string & specials , char c_escape )
41 {
42  size_type pos = 0U ;
43  for(;;)
44  {
45  pos = s.find_first_of( specials , pos ) ;
46  if( pos == std::string::npos )
47  break ;
48 
49  s.insert( pos , 1U , c_escape ) ;
50  pos++ ;
51  pos++ ;
52  }
53 }
54 
55 bool G::Str::replace( std::string & s , const std::string & from , const std::string & to , size_type * pos_p )
56 {
57  if( from.length() == 0 )
58  return false ;
59 
60  size_type pos = pos_p == NULL ? 0 : *pos_p ;
61  if( pos >= s.length() )
62  return false ;
63 
64  pos = s.find( from , pos ) ;
65  if( pos == std::string::npos )
66  {
67  return false ;
68  }
69  else
70  {
71  s.replace( pos , from.length() , to ) ;
72  if( pos_p != NULL )
73  *pos_p = pos + to.length() ;
74  return true ;
75  }
76 }
77 
78 unsigned int G::Str::replaceAll( std::string & s , const std::string & from , const std::string & to )
79 {
80  unsigned int count = 0U ;
81  for( size_type pos = 0U ; replace(s,from,to,&pos) ; count++ )
82  ; // no-op
83  return count ;
84 }
85 
86 unsigned int G::Str::replaceAll( std::string & s , const char * from , const char * to )
87 {
88  // this char* overload is an optimisation to avoid constructing
89  // temporaries when starting with a c-string -- we only construct
90  // std-strings if there is work to do
91 
92  if( s.find(from) != std::string::npos )
93  {
94  unsigned int count = 0U ;
95  for( size_type pos = 0U ; replace(s,from,to,&pos) ; count++ )
96  ; // no-op
97  return count ;
98  }
99  else
100  {
101  return 0U ;
102  }
103 }
104 
105 void G::Str::removeAll( std::string & s , char c )
106 {
107  const std::string::iterator end = s.end() ;
108  s.erase( std::remove_if( s.begin() , end , std::bind1st(std::equal_to<char>(),c) ) , end ) ;
109 }
110 
111 void G::Str::trimLeft( std::string & s , const std::string & ws , size_type limit )
112 {
113  size_type n = s.find_first_not_of( ws ) ;
114  if( limit != 0U && ( n == std::string::npos || n > limit ) )
115  n = limit >= s.length() ? std::string::npos : limit ;
116  if( n == std::string::npos )
117  s = std::string() ;
118  else if( n != 0U )
119  s.erase( 0U , n ) ;
120 }
121 
122 void G::Str::trimRight( std::string & s , const std::string & ws , size_type limit )
123 {
124  size_type n = s.find_last_not_of( ws ) ;
125  if( limit != 0U && ( n == std::string::npos || s.length() > (limit+n+1U) ) )
126  n = limit >= s.length() ? std::string::npos : (s.length()-limit-1U) ;
127  if( n == std::string::npos )
128  s = std::string() ;
129  else if( n != 0U )
130  s.resize( n+1U ) ;
131 }
132 
133 void G::Str::trim( std::string & s , const std::string & ws )
134 {
135  trimLeft(s,ws) ; trimRight(s,ws) ;
136 }
137 
138 std::string G::Str::trimmed( const std::string & s_in , const std::string & ws )
139 {
140  std::string s( s_in ) ;
141  trim( s , ws ) ;
142  return s ;
143 }
144 
145 namespace
146 {
147  struct IsDigit : std::unary_function<char,bool>
148  {
149  bool operator()( char c ) const { return !! isdigit( c ) ; }
150  } ;
151 }
152 bool G::Str::isNumeric( const std::string & s , bool allow_minus_sign )
153 {
154  const std::string::const_iterator end = s.end() ;
155  std::string::const_iterator p = s.begin() ;
156  if( allow_minus_sign && p != end && *p == '-' ) ++p ;
157  return std::find_if( p , end , std::not1(IsDigit()) ) == end ;
158 }
159 
160 namespace
161 {
162  struct IsPrintableAscii : std::unary_function<char,bool>
163  {
164  bool operator()( char c ) const { return c >= 0x20 && c < 0x7f ; }
165  } ;
166 }
167 bool G::Str::isPrintableAscii( const std::string & s )
168 {
169  const std::string::const_iterator end = s.end() ;
170  return std::find_if( s.begin() , end , std::not1(IsPrintableAscii()) ) == end ;
171 }
172 
173 bool G::Str::isUShort( const std::string & s )
174 {
175  try
176  {
177  G_IGNORE_RETURN(unsigned short) toUShort(s) ;
178  }
179  catch( Overflow & )
180  {
181  return false ;
182  }
183  catch( InvalidFormat & )
184  {
185  return false ;
186  }
187  return true ;
188 }
189 
190 bool G::Str::isUInt( const std::string & s )
191 {
192  try
193  {
194  G_IGNORE_RETURN(unsigned int) toUInt(s) ;
195  }
196  catch( Overflow & )
197  {
198  return false ;
199  }
200  catch( InvalidFormat & )
201  {
202  return false ;
203  }
204  return true ;
205 }
206 
207 bool G::Str::isULong( const std::string & s )
208 {
209  try
210  {
211  G_IGNORE_RETURN(unsigned long) toULong(s) ;
212  }
213  catch( Overflow & )
214  {
215  return false ;
216  }
217  catch( InvalidFormat & )
218  {
219  return false ;
220  }
221  return true ;
222 }
223 
224 std::string G::Str::fromBool( bool b )
225 {
226  return b ? "true" : "false" ;
227 }
228 
229 std::string G::Str::fromDouble( double d )
230 {
231  std::ostringstream ss ;
232  ss << std::setprecision(16) << d ; // was "setprecision(DBL_DIG+1)
233  return ss.str() ;
234 }
235 
236 std::string G::Str::fromInt( int i )
237 {
238  std::ostringstream ss ;
239  ss << i ;
240  return ss.str() ;
241 }
242 
243 std::string G::Str::fromLong( long l )
244 {
245  std::ostringstream ss ;
246  ss << l ;
247  return ss.str() ;
248 }
249 
250 std::string G::Str::fromShort( short s )
251 {
252  std::ostringstream ss ;
253  ss << s ;
254  return ss.str() ;
255 }
256 
257 std::string G::Str::fromUInt( unsigned int ui )
258 {
259  std::ostringstream ss ;
260  ss << ui ;
261  return ss.str() ;
262 }
263 
264 std::string G::Str::fromULong( unsigned long ul )
265 {
266  std::ostringstream ss ;
267  ss << ul ;
268  return ss.str() ;
269 }
270 
271 std::string G::Str::fromUShort( unsigned short us )
272 {
273  std::ostringstream ss ;
274  ss << us ;
275  return ss.str() ;
276 }
277 
278 bool G::Str::toBool( const std::string & s )
279 {
280  std::string str = lower( s ) ;
281  if( str == "true" )
282  {
283  return true ;
284  }
285  else if( str == "false" )
286  {
287  return false ;
288  }
289  else
290  {
291  throw InvalidFormat( s ) ;
292  return false ; // never gets here -- the return pacifies some compilers
293  }
294 }
295 
296 double G::Str::toDouble( const std::string &s )
297 {
298  char * end = NULL ;
299  double result = ::strtod( s.c_str(), &end ) ;
300 
301  if( end == 0 || end[0] != '\0' )
302  throw InvalidFormat( s ) ;
303 
304  if( result == HUGE_VAL || result == -(HUGE_VAL) )
305  throw Overflow( s ) ;
306 
307  return result ;
308 }
309 
310 int G::Str::toInt( const std::string &s )
311 {
312  long long_val = toLong( s ) ;
313  int int_val = static_cast<int>( long_val ) ;
314 
315  if( int_val != long_val )
316  throw Overflow( s ) ;
317 
318  return int_val ;
319 }
320 
321 long G::Str::toLong( const std::string &s )
322 {
323  char * end = NULL ;
324  long result = ::strtol( s.c_str(), &end, 0 ) ;
325 
326  if( end == 0 || end[0] != '\0' )
327  throw InvalidFormat( s ) ;
328 
329  if( result == LONG_MAX || result == LONG_MIN )
330  throw Overflow( s ) ;
331 
332  return result ;
333 }
334 
335 short G::Str::toShort( const std::string &s )
336 {
337  long long_val = toLong( s ) ;
338  short short_val = static_cast<short>( long_val ) ;
339 
340  if( short_val != long_val )
341  throw Overflow( s ) ;
342 
343  return short_val ;
344 }
345 
346 unsigned int G::Str::toUInt( const std::string &s , bool limited )
347 {
348  unsigned long ulong_val = toULong( s ) ;
349  unsigned int uint_val = static_cast<unsigned int>( ulong_val ) ;
350 
351  if( uint_val != ulong_val )
352  {
353  if( limited )
354  uint_val = UINT_MAX ;
355  else
356  throw Overflow( s ) ;
357  }
358 
359  return uint_val ;
360 }
361 
362 unsigned long G::Str::toULong( const std::string &s , bool limited )
363 {
364  char * end = NULL ;
365  unsigned long result = ::strtoul( s.c_str() , &end , 10 ) ;
366 
367  if( end == 0 || end[0] != '\0' )
368  throw InvalidFormat( s ) ;
369 
370  if( result == ULONG_MAX )
371  {
372  if( limited )
373  result = ULONG_MAX ;
374  else
375  throw Overflow( s ) ;
376  }
377 
378  return result ;
379 }
380 
381 unsigned short G::Str::toUShort( const std::string &s , bool limited )
382 {
383  unsigned long ulong_val = toULong( s ) ;
384  unsigned short ushort_val = static_cast<unsigned short>( ulong_val ) ;
385 
386  if( ushort_val != ulong_val )
387  {
388  if( limited )
389  ushort_val = USHRT_MAX ;
390  else
391  throw Overflow( s ) ;
392  }
393 
394  return ushort_val ;
395 }
396 
397 namespace
398 {
399  struct ToLower : std::unary_function<char,char>
400  {
401  char operator()( char c ) { return static_cast<char>( tolower(c) ) ; }
402  } ;
403 }
404 void G::Str::toLower( std::string & s )
405 {
406  std::transform( s.begin() , s.end() , s.begin() , ToLower() ) ;
407 }
408 std::string G::Str::lower( const std::string & in )
409 {
410  std::string out = in ;
411  toLower( out ) ;
412  return out ;
413 }
414 
415 namespace
416 {
417  struct ToUpper : std::unary_function<char,char>
418  {
419  char operator()( char c ) { return static_cast<char>( toupper(c) ) ; }
420  } ;
421 }
422 void G::Str::toUpper( std::string & s )
423 {
424  std::transform( s.begin() , s.end() , s.begin() , ToUpper() ) ;
425 }
426 std::string G::Str::upper( const std::string & in )
427 {
428  std::string out = in ;
429  toUpper( out ) ;
430  return out ;
431 }
432 
433 namespace
434 {
435  template <typename Tchar = char , typename Tuchar = unsigned char>
436  struct PrintableAppender : std::unary_function<Tchar,void>
437  {
438  std::string & s ;
439  Tchar escape_in ;
440  char escape_out ;
441  bool eight_bit ;
442  PrintableAppender( std::string & s_ , Tchar escape_ , bool eight_bit_ ) :
443  s(s_) ,
444  escape_in(escape_) ,
445  escape_out(static_cast<char>(escape_)) ,
446  eight_bit(eight_bit_)
447  {
448  }
449  void operator()( Tchar c )
450  {
451  const Tuchar uc = static_cast<Tuchar>(c) ;
452  if( c == escape_in )
453  {
454  s.append( 2U , escape_out ) ;
455  }
456  else if( !eight_bit && uc >= 0x20U && uc < 0x7FU && uc != 0xFFU )
457  {
458  s.append( 1U , static_cast<char>(c) ) ;
459  }
460  else if( eight_bit && ( ( uc >= 0x20U && uc < 0x7FU ) || uc >= 0xA0 ) && uc != 0xFFU )
461  {
462  s.append( 1U , static_cast<char>(c) ) ;
463  }
464  else
465  {
466  s.append( 1U , escape_out ) ;
467  if( static_cast<char>(c) == '\n' )
468  {
469  s.append( 1U , 'n' ) ;
470  }
471  else if( static_cast<char>(c) == '\r' )
472  {
473  s.append( 1U , 'r' ) ;
474  }
475  else if( static_cast<char>(c) == '\t' )
476  {
477  s.append( 1U , 't' ) ;
478  }
479  else if( c == 0 )
480  {
481  s.append( 1U , '0' ) ;
482  }
483  else
484  {
485  s.append( 1U , 'x' ) ;
486  const char * const map = "0123456789abcdef" ;
487  unsigned long n = uc ;
488  if( sizeof(Tchar) == 1 )
489  {
490  n &= 0xFFUL ;
491  s.append( 1U , map[(n/16UL)%16UL] ) ;
492  s.append( 1U , map[n%16UL] ) ;
493  }
494  else
495  {
496  n &= 0xFFFFUL ;
497  s.append( 1U , map[(n/4096UL)%16UL] ) ;
498  s.append( 1U , map[(n/256UL)%16UL] ) ;
499  s.append( 1U , map[(n/16UL)%16UL] ) ;
500  s.append( 1U , map[n%16UL] ) ;
501  }
502  }
503  }
504  }
505  } ;
506 }
507 std::string G::Str::printable( const std::string & in , char escape )
508 {
509  std::string result ;
510  result.reserve( in.length() + 1U ) ;
511  std::for_each( in.begin() , in.end() , PrintableAppender<char,unsigned char>(result,escape,true) ) ;
512  return result ;
513 }
514 std::string G::Str::toPrintableAscii( const std::string & in , char escape )
515 {
516  std::string result ;
517  result.reserve( in.length() + 1U ) ;
518  std::for_each( in.begin() , in.end() , PrintableAppender<char,unsigned char>(result,escape,false) ) ;
519  return result ;
520 }
521 std::string G::Str::toPrintableAscii( char c , char escape )
522 {
523  std::string result ;
524  PrintableAppender<char,unsigned char> append_printable( result , escape , false ) ;
525  append_printable( c ) ;
526  return result ;
527 }
528 std::string G::Str::toPrintableAscii( const std::wstring & in , wchar_t escape )
529 {
530  std::string result ;
531  result.reserve( in.length() * 3U ) ;
532  std::for_each( in.begin() , in.end() , PrintableAppender<wchar_t,unsigned long>(result,escape,false) ) ;
533  return result ;
534 }
535 
536 std::string G::Str::readLineFrom( std::istream & stream , const std::string & eol )
537 {
538  std::string result ;
539  readLineFrom( stream , eol.empty() ? std::string(1U,'\n') : eol , result , true ) ;
540  return result ;
541 }
542 
543 void G::Str::readLineFrom( std::istream & stream , const std::string & eol , std::string & line , bool pre_erase )
544 {
545  G_ASSERT( eol.length() != 0U ) ;
546 
547  if( pre_erase )
548  line.erase() ;
549 
550  // this is a special speed optimisation for a two-character terminator with a one-character initial string ;-)
551  if( eol.length() == 2U && eol[0] != eol[1] && line.length() == 1U )
552  {
553  // Save the initial character, use std::getline() for speed (terminating
554  // on the second character of the two-character terminator), check that the
555  // one-character terminator was actually part of the required two-character
556  // terminator, remove the first character of the two-character terminator,
557  // and finally re-insert the initial character.
558  //
559  const char c = line[0] ;
560  line.erase() ; // since getline() doesnt erase it if already at eof
561  std::getline( stream , line , eol[1] ) ; // fast
562  const std::string::size_type line_length = line.length() ;
563  bool complete = line_length > 0U && line[line_length-1U] == eol[0] ;
564  if( complete )
565  {
566  line.resize( line_length - 1U ) ;
567  line.insert( 0U , &c , 1U ) ;
568  }
569  else
570  {
571  line.insert( 0U , &c , 1U ) ;
572  if( stream.good() )
573  {
574  line.append( 1U , eol[1] ) ;
575  readLineFromImp( stream , eol , line ) ;
576  }
577  }
578  }
579  else
580  {
581  readLineFromImp( stream , eol , line ) ;
582  }
583 }
584 
585 void G::Str::readLineFromImp( std::istream & stream , const std::string & eol , std::string & line )
586 {
587  const size_type limit = line.max_size() ;
588  const size_type eol_length = eol.length() ;
589  const char eol_final = eol.at( eol_length - 1U ) ;
590  size_type line_length = line.length() ;
591 
592  bool changed = false ;
593  char c ;
594  for(;;)
595  {
596  stream.get( c ) ; // sets the fail bit at eof
597  if( stream.fail() )
598  {
599  // work more like std::getline() in <string> -- reset the failbit and set eof
600  // (remember that clear() sets all the flags explicitly to the given values)
601  stream.clear( ( stream.rdstate() & ~std::ios_base::failbit ) | std::ios_base::eofbit ) ;
602  break ;
603  }
604 
605  if( line_length == limit ) // pathological case -- see also std::getline()
606  {
607  stream.setstate( std::ios_base::failbit ) ;
608  break ;
609  }
610 
611  line.append( 1U , c ) ; // fast enough if 'line' has sufficient capacity
612  changed = true ;
613  ++line_length ;
614 
615  if( line_length >= eol_length && c == eol_final ) // optimisation
616  {
617  const size_type offset = line_length - eol_length ;
618  if( line.find(eol,offset) == offset )
619  {
620  line.erase(offset) ;
621  break ;
622  }
623  }
624  }
625  if( !changed )
626  {
627  // set the failbit
628  // (remember that setstate() sets the flag(s) identified by the given bitmask to 1)
629  stream.setstate( std::ios_base::failbit ) ;
630  }
631 }
632 
633 std::string G::Str::wrap( std::string text , const std::string & prefix_1 ,
634  const std::string & prefix_2 , size_type width )
635 {
636  std::string ws( " \t\n" ) ;
637  std::ostringstream ss ;
638  for( bool first_line = true ; text.length() ; first_line = false )
639  {
640  const size_type prefix_length =
641  first_line ? prefix_1.length() : prefix_2.length() ;
642  size_type w = (width > prefix_length) ? (width-prefix_length) : width ;
643 
644  const size_type pos_nl = text.find_first_of("\n") ;
645  if( pos_nl != std::string::npos && pos_nl != 0U && pos_nl < w )
646  {
647  w = pos_nl ;
648  }
649 
650  std::string line = text ;
651  if( text.length() > w ) // (should use wcwidth() for utf-8 compatibility)
652  {
653  line = text.substr( 0U , w ) ;
654  if( text.find_first_of(ws,w) != w )
655  {
656  const size_type white_space = line.find_last_of( ws ) ;
657  const size_type black_space = line.find_first_not_of( ws ) ;
658  if( white_space != std::string::npos &&
659  black_space != std::string::npos &&
660  (white_space+1U) != black_space )
661  {
662  line = line.substr( 0U , white_space ) ;
663  }
664  }
665  }
666 
667  if( line.length() != 0U )
668  {
669  ss << ( first_line ? prefix_1 : prefix_2 ) << line << std::endl ;
670  }
671 
672  text = text.length() == line.length() ?
673  std::string() : text.substr(line.length()) ;
674 
675  const size_type black_space = text.find_first_not_of( ws ) ;
676  if( black_space != 0U && black_space != std::string::npos )
677  {
678  unsigned int newlines = 0U ;
679  for( size_type pos = 0U ; pos < black_space ; ++pos )
680  {
681  if( text.at(pos) == '\n' )
682  {
683  newlines++ ;
684  if( newlines > 1U )
685  ss << prefix_2 << std::endl ;
686  }
687  }
688 
689  text = text.substr( black_space ) ;
690  }
691  }
692  return ss.str() ;
693 }
694 
695 namespace
696 {
697  template <typename T>
698  void splitIntoTokens_( const std::string & in , T & out , const std::string & ws )
699  {
700  typedef G::Str::size_type size_type ;
701  for( size_type p = 0U ; p != std::string::npos ; )
702  {
703  p = in.find_first_not_of( ws , p ) ;
704  if( p != std::string::npos )
705  {
706  size_type end = in.find_first_of( ws , p ) ;
707  size_type len = end == std::string::npos ? end : (end-p) ;
708  out.push_back( in.substr(p,len) ) ;
709  p = end ;
710  }
711  }
712  }
713 }
714 void G::Str::splitIntoTokens( const std::string & in , Strings & out , const std::string & ws )
715 {
716  splitIntoTokens_( in , out , ws ) ;
717 }
718 void G::Str::splitIntoTokens( const std::string & in , StringArray & out , const std::string & ws )
719 {
720  splitIntoTokens_( in , out , ws ) ;
721 }
722 
723 namespace
724 {
725  template <typename T>
726  void splitIntoFields_( const std::string & in_in , T & out , const std::string & ws ,
727  char escape , bool discard_bogus )
728  {
729  typedef G::Str::size_type size_type ;
730  std::string all( ws ) ;
731  if( escape != '\0' )
732  all.append( 1U , escape ) ;
733 
734  if( in_in.length() )
735  {
736  std::string in = in_in ;
737  size_type start = 0U ;
738  size_type last_pos = in.length() - 1U ;
739  size_type pos = 0U ;
740  for(;;)
741  {
742  if( pos >= in.length() ) break ;
743  pos = in.find_first_of( all , pos ) ;
744  if( pos == std::string::npos ) break ;
745  if( in.at(pos) == escape )
746  {
747  const bool valid = pos != last_pos && in.find(all,pos+1U) == (pos+1U) ;
748  if( valid || discard_bogus )
749  in.erase( pos , 1U ) ;
750  else
751  pos++ ;
752  pos++ ;
753  }
754  else
755  {
756  out.push_back( in.substr(start,pos-start) ) ;
757  pos++ ;
758  start = pos ;
759  }
760  }
761  out.push_back( in.substr(start,pos-start) ) ;
762  }
763  }
764 }
765 void G::Str::splitIntoFields( const std::string & in , Strings & out , const std::string & ws ,
766  char escape , bool discard_bogus )
767 {
768  splitIntoFields_( in , out , ws , escape , discard_bogus ) ;
769 }
770 void G::Str::splitIntoFields( const std::string & in , StringArray & out , const std::string & ws ,
771  char escape , bool discard_bogus )
772 {
773  splitIntoFields_( in , out , ws , escape , discard_bogus ) ;
774 }
775 
776 namespace
777 {
778  template <typename T>
779  struct Joiner : std::unary_function<const T&,void>
780  {
781  T & result ;
782  const T & sep ;
783  bool & first ;
784  Joiner( T & result_ , const T & sep_ , bool & first_ ) :
785  result(result_) ,
786  sep(sep_) ,
787  first(first_)
788  {
789  first = true ;
790  }
791  void operator()( const T & s )
792  {
793  if( !first ) result.append( sep ) ;
794  result.append( s ) ;
795  first = false ;
796  }
797  } ;
798 }
799 std::string G::Str::join( const Strings & strings , const std::string & sep )
800 {
801  std::string result ;
802  bool first = true ;
803  std::for_each( strings.begin() , strings.end() , Joiner<std::string>(result,sep,first) ) ;
804  return result ;
805 }
806 std::string G::Str::join( const StringArray & strings , const std::string & sep )
807 {
808  std::string result ;
809  bool first = true ;
810  std::for_each( strings.begin() , strings.end() , Joiner<std::string>(result,sep,first) ) ;
811  return result ;
812 }
813 
814 namespace
815 {
816  template <typename T>
817  struct Firster : std::unary_function<const T&,const typename T::first_type&>
818  {
819  const typename T::first_type & operator()( const T & pair ) { return pair.first ; }
820  } ;
821 }
823 {
824  Strings result ;
825  std::transform( map.begin() , map.end() , std::back_inserter(result) , Firster<StringMap::value_type>() ) ;
826  return result ;
827 }
828 
829 std::string G::Str::ws()
830 {
831  return std::string(" \t\n\r") ;
832 }
833 
834 std::string G::Str::head( const std::string & in , std::string::size_type pos , const std::string & default_ )
835 {
836  return
837  pos == std::string::npos ?
838  default_ :
839  ( pos == 0U ? std::string() : ( (pos+1U) >= in.length() ? in : in.substr(0U,pos) ) ) ;
840 }
841 
842 std::string G::Str::tail( const std::string & in , std::string::size_type pos , const std::string & default_ )
843 {
844  return
845  pos == std::string::npos ?
846  default_ :
847  ( (pos+1U) >= in.length() ? std::string() : in.substr(pos+1U) ) ;
848 }
849 
850 bool G::Str::tailMatch( const std::string & in , const std::string & ending )
851 {
852  return
853  ending.empty() ||
854  ( in.length() >= ending.length() &&
855  in.substr( in.length() - ending.length() ) == ending ) ;
856  // 0 == in.compare( in.length() - ending.length() , ending.length() , ending ) // faster, but not gcc2.95
857 }
858 
static std::string fromBool(bool b)
Converts boolean 'b' to a string.
Definition: gstr.cpp:224
std::string::size_type size_type
Definition: gstr.h:45
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
Definition: gstr.cpp:507
static bool toBool(const std::string &s)
Converts string 's' to a bool.
Definition: gstr.cpp:278
static unsigned int toUInt(const std::string &s, bool limited=false)
Converts string 's' to an unsigned int.
Definition: gstr.cpp:346
static int toInt(const std::string &s)
Converts string 's' to an int.
Definition: gstr.cpp:310
std::list< std::string > Strings
A std::list of std::strings.
Definition: gstrings.h:39
static std::string wrap(std::string text, const std::string &prefix_first_line, const std::string &prefix_subsequent_lines, size_type width=70U)
Does word-wrapping.
Definition: gstr.cpp:633
static bool tailMatch(const std::string &in, const std::string &ending)
Returns true if the given string has the given ending.
Definition: gstr.cpp:850
static void splitIntoFields(const std::string &in, Strings &out, const std::string &seperators, char escape= '\0', bool discard_bogus_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:765
static void escape(std::string &, const std::string &specials, char escape= '\\')
Prefixes each occurrence of one of the special characters with the escape character.
Definition: gstr.cpp:40
static std::string fromDouble(double d)
Converts double 'd' to a string.
Definition: gstr.cpp:229
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:44
std::string::size_type size_type
A std::size_t type.
Definition: md5.h:43
static void splitIntoTokens(const std::string &in, Strings &out, const std::string &ws)
Splits the string into 'ws'-delimited tokens.
Definition: gstr.cpp:714
static short toShort(const std::string &s)
Converts string 's' to a short.
Definition: gstr.cpp:335
static bool isNumeric(const std::string &s, bool allow_minus_sign=false)
Returns true if every character is a decimal digit.
Definition: gstr.cpp:152
static std::string fromInt(int i)
Converts int 'i' to a string.
Definition: gstr.cpp:236
static std::string tail(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the last part of the string after the given position.
Definition: gstr.cpp:842
static void trim(std::string &s, const std::string &ws)
Trims both ends of s, taking off any of the 'ws' characters.
Definition: gstr.cpp:133
static void trimLeft(std::string &s, const std::string &ws, size_type limit=0U)
Trims the lhs of s, taking off up to 'limit' of the 'ws' characters.
Definition: gstr.cpp:111
static std::string fromLong(long l)
Converts long 'l' to a string.
Definition: gstr.cpp:243
static std::string lower(const std::string &s)
Returns a copy of 's' in which all uppercase characters have been replaced by lowercase characters...
Definition: gstr.cpp:408
static void toLower(std::string &s)
Replaces all uppercase characters in string 's' by lowercase characters.
Definition: gstr.cpp:404
static Strings keys(const StringMap &string_map)
Extracts the keys from a map of strings.
Definition: gstr.cpp:822
#define G_ASSERT(test)
Definition: gassert.h:30
static std::string fromUInt(unsigned int ui)
Converts unsigned int 'ui' to a string.
Definition: gstr.cpp:257
static bool replace(std::string &s, const std::string &from, const std::string &to, size_type *pos_p=NULL)
Replaces 'from' with 'to', starting at offset '*pos_p'.
Definition: gstr.cpp:55
static unsigned int replaceAll(std::string &s, const std::string &from, const std::string &to)
Does a global replace on string 's', replacing all occurences of sub-string 'from' with 'to'...
Definition: gstr.cpp:78
static std::string head(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the first part of the string up to just before the given position.
Definition: gstr.cpp:834
static void trimRight(std::string &s, const std::string &ws, size_type limit=0U)
Trims the rhs of s, taking off up to 'limit' of the 'ws' characters.
Definition: gstr.cpp:122
static double toDouble(const std::string &s)
Converts string 's' to a double.
Definition: gstr.cpp:296
static std::string fromShort(short s)
Converts short 's' to a string.
Definition: gstr.cpp:250
static bool isUShort(const std::string &s)
Returns true if the string can be converted into an unsigned short without throwing an exception...
Definition: gstr.cpp:173
static std::string upper(const std::string &s)
Returns a copy of 's' in which all lowercase characters have been replaced by uppercase characters...
Definition: gstr.cpp:426
static std::string fromUShort(unsigned short us)
Converts unsigned short 'us' to a string.
Definition: gstr.cpp:271
static std::string escaped(const std::string &, const std::string &specials, char escape= '\\')
Prefixes each occurrence of one of the special characters with the escape character.
Definition: gstr.cpp:33
static std::string trimmed(const std::string &s, const std::string &ws)
Returns a trim()med version of s.
Definition: gstr.cpp:138
static std::string readLineFrom(std::istream &stream, const std::string &eol=std::string())
Reads a line from the stream using the given line terminator.
Definition: gstr.cpp:536
static bool isPrintableAscii(const std::string &s)
Returns true if every character is a 7-bit, non-control character (ie.
Definition: gstr.cpp:167
std::map< std::string, std::string > StringMap
A std::map of std::strings.
Definition: gstrings.h:49
static long toLong(const std::string &s)
Converts string 's' to a long.
Definition: gstr.cpp:321
static unsigned short toUShort(const std::string &s, bool limited=false)
Converts string 's' to an unsigned short.
Definition: gstr.cpp:381
static unsigned long toULong(const std::string &s, bool limited=false)
Converts string 's' to an unsigned long.
Definition: gstr.cpp:362
static bool isUInt(const std::string &s)
Returns true if the string can be converted into an unsigned integer without throwing an exception...
Definition: gstr.cpp:190
static void removeAll(std::string &, char)
Removes all occurrences of the character from the string.
Definition: gstr.cpp:105
static bool isULong(const std::string &s)
Returns true if the string can be converted into an unsigned long without throwing an exception...
Definition: gstr.cpp:207
static std::string fromULong(unsigned long ul)
Converts unsigned long 'ul' to a string.
Definition: gstr.cpp:264
static std::string join(const Strings &strings, const std::string &sep)
Concatenates a set of strings.
Definition: gstr.cpp:799
static std::string ws()
A convenience function returning standard whitespace characters.
Definition: gstr.cpp:829
static std::string toPrintableAscii(char c, char escape= '\\')
Returns a 7-bit printable representation of the given input character.
Definition: gstr.cpp:521
static void toUpper(std::string &s)
Replaces all lowercase characters in string 's' by uppercase characters.
Definition: gstr.cpp:422