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]
Say.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/Say.hpp>
33 #include <cmath>
34 
35 using namespace vl;
36 
38 {
39  init();
40 }
41 
43 {
44  init();
45  ulonglong = reinterpret_cast<unsigned long long>(d);
46  type = ULONGLONG;
47 }
48 
49 SayArg::SayArg(const std::string& d)
50 {
51  init();
52  str = d.c_str();
53  type = STRING;
54 }
55 
56 SayArg::SayArg(const unsigned char* d)
57 {
58  init();
59  if (d)
60  str = (const char*)d;
61  type = STRING;
62 }
63 
64 SayArg::SayArg(const char* d)
65 {
66  init();
67  if (d)
68  str = d;
69  type = STRING;
70 }
71 
73 {
74  init();
75  str = d;
76  type = STRING;
77 }
78 
79 SayArg::SayArg(double d)
80 {
81  init();
82  float64 = d;
83  type = FLOAT64;
84 }
85 
87 {
88  init();
89  float64 = d;
90  type = FLOAT64;
91 }
92 
93 SayArg::SayArg(unsigned char d)
94 {
95  init();
96  ulonglong = d;
97  type = ULONGLONG;
98 }
99 
100 SayArg::SayArg(signed char d)
101 {
102  init();
103  slonglong = d;
104  type = SLONGLONG;
105 }
106 
107 SayArg::SayArg(unsigned short d)
108 {
109  init();
110  ulonglong = d;
111  type = ULONGLONG;
112 }
113 
114 SayArg::SayArg(signed short d)
115 {
116  init();
117  slonglong = d;
118  type = SLONGLONG;
119 }
120 
121 SayArg::SayArg(unsigned int d)
122 {
123  init();
124  ulonglong = d;
125  type = ULONGLONG;
126 }
127 
128 SayArg::SayArg(signed int d)
129 {
130  init();
131  slonglong = d;
132  type = SLONGLONG;
133 }
134 
135 SayArg::SayArg(unsigned long d)
136 {
137  init();
138  ulonglong = d;
139  type = ULONGLONG;
140 }
141 
142 SayArg::SayArg(signed long d)
143 {
144  init();
145  slonglong = d;
146  type = SLONGLONG;
147 }
148 
149 SayArg::SayArg(unsigned long long d)
150 {
151  init();
152  ulonglong = d;
153  type = ULONGLONG;
154 }
155 
156 SayArg::SayArg(signed long long d)
157 {
158  init();
159  slonglong = d;
160  type = SLONGLONG;
161 }
162 
164 {
165  type = NO_TYPE;
166  float64 = 0;
167  ulonglong = 0;
168  slonglong = 0;
169 }
170 
171 String Say::parse( const Say& pset ) const
172 {
173  String out;
174  String fmt = pset.format_string;
175 
176  int param_idx = 0;
177 
178  int eur = -1;
179  int base = -1;
180  int field = -1;
181  int decimals = -1;
182  int align = -1;
183  int fill = -1;
184  int plus = -1;
185 
186  int fmtstart = -1;
187 
188  // %H+014.5n
189  bool fmtdata = false;
190  for(int i=0; i<(int)fmt.length(); ++i)
191  {
192  int ch = (i<(int)fmt.length()) ? (int)fmt[i+0] : -1;
193  int next_ch = (i<(int)fmt.length()-1) ? (int)fmt[i+1] : -1;
194  int nnext_ch = (i<(int)fmt.length()-2) ? (int)fmt[i+2] : -1;
195 
196  if (!fmtdata)
197  {
198  if (ch == '%' && next_ch == '%')
199  {
200  out += '%';
201  ++i;
202  }
203  else
204  if (ch == '%')
205  {
206  if (param_idx < (int)pset.size())
207  {
208  fmtdata = true;
209  fmtstart = i;
210  }
211  else
212  {
213  out += " !!!too few parameters: %";
214  }
215  }
216  else
217  if (ch >= 0)
218  {
219  out += (unsigned short)ch;
220  }
221  }
222  else
223  {
224 
225  if(eur == -1)
226  {
227  if (ch == '$')
228  {
229  eur = 1;
230  continue;
231  }
232  }
233 
234  if (base == -1)
235  {
236  switch(ch)
237  {
238  case 'b': base = 2; break;
239  case 'o': base = 8; break;
240  case 'd': base = 10; break;
241  case 'h': base = 16; break;
242  }
243  if (base != -1)
244  {
245  if (eur == -1)
246  eur = 0;
247  continue;
248  }
249  }
250 
251  if (plus == -1)
252  {
253  switch(ch)
254  {
255  case '+': plus = 1; break;
256  }
257  if (plus != -1)
258  {
259  if (base == -1)
260  base = 10;
261  if (eur == -1)
262  eur = 0;
263  continue;
264  }
265  }
266 
267  if (fill == -1)
268  {
269  switch(ch)
270  {
271  case '0': fill = '0'; break;
272  case ' ': fill = ' '; break;
273  }
274  if (fill != -1)
275  {
276  if (base == -1)
277  base = 10;
278  if (plus == -1)
279  plus = 0;
280  if (eur == -1)
281  eur = 0;
282  continue;
283  }
284  }
285 
286  if (field == -1)
287  {
288  if (ch >= '0' && ch <= '9')
289  {
290  field = ch - '0';
291  if (next_ch >= '0' && next_ch <= '9')
292  {
293  field = field*10 + next_ch - '0';
294  ++i;
295  }
296  }
297 
298  if (field != -1)
299  {
300  if (base == -1)
301  base = 10;
302  if (plus == -1)
303  plus = 0;
304  if (fill == -1)
305  fill = ' ';
306  if (eur == -1)
307  eur = 0;
308  continue;
309  }
310  }
311 
312  if (decimals == -1)
313  {
314  if(ch == '.')
315  {
316  if (next_ch >= '0' && next_ch <= '9')
317  {
318  decimals = next_ch - '0';
319  ++i;
320  if (nnext_ch >= '0' && nnext_ch <= '9')
321  {
322  decimals = decimals*10 + nnext_ch - '0';
323  ++i;
324  }
325  }
326  }
327 
328  if (decimals != -1)
329  {
330  if (base == -1)
331  base = 10;
332  if (plus == -1)
333  plus = 0;
334  if (fill == -1)
335  fill = ' ';
336  if (field == -1)
337  field = 0;
338  if (eur == -1)
339  eur = 0;
340  continue;
341  }
342  }
343 
344  if (align == -1)
345  {
346  if(ch == '=')
347  align = 0;
348  if(ch == '<')
349  align = 1;
350  if(ch == '>')
351  align = 2;
352 
353  if (align != -1)
354  {
355  if (base == -1)
356  base = 10;
357  if (plus == -1)
358  plus = 0;
359  if (fill == -1)
360  fill = ' ';
361  if (field == -1)
362  field = 0;
363  if (eur == -1)
364  eur = 0;
365  if (decimals == -1)
366  {
367  switch(pset[param_idx].type)
368  {
369  case SayArg::FLOAT64: decimals = 6; break;
370  default: decimals = 0; break;
371  }
372  }
373  continue;
374  }
375  }
376 
377  // generate formatted string
378 
379  // output parameter
380  const SayArg& p = pset[param_idx];
381 
382  if (ch == 'c')
383  {
384  if (fmtstart != i-1)
385  out += " !!! '%c' does not need arguments !!! ";
386 
387  switch(p.type)
388  {
389  case SayArg::FLOAT64: out += (char)p.float64; break;
390  case SayArg::SLONGLONG: out += (char)p.slonglong; break;
391  case SayArg::ULONGLONG: out += (char)p.ulonglong; break;
392  default:
393  out += " !!! wrong argument type for '%c' !!! ";
394  break;
395  }
396 
397  }
398  else
399  if (ch == 's')
400  {
401  if (fmtstart != i-1)
402  out += " !!! '%s' does not need arguments !!! ";
403 
404  switch(p.type)
405  {
406  case SayArg::STRING: out += p.str; break;
407  default:
408  out += " !!! wrong argument type for '%s' !!! ";
409  break;
410  }
411 
412  }
413  else
414  if (ch == 'n' || ch == 'N' || ch == 'e' || ch == 'E')
415  {
416 
417  if (param_idx<(int)pset.size())
418  {
419  if (decimals == -1)
420  {
421  switch(p.type)
422  {
423  case SayArg::FLOAT64: decimals = 6; break;
424  default: decimals = 0; break;
425  }
426  }
427 
428  if (base == -1)
429  base = 10;
430  if (field == -1)
431  field = 0;
432  if (decimals == -1)
433  decimals = 0;
434  if (fill == -1)
435  fill = ' ';
436  if (plus == -1)
437  plus = 0;
438  if (align == -1)
439  align = 2;
440  if (eur == -1)
441  eur = 0;
442 
443  switch(p.type)
444  {
445  case SayArg::FLOAT64: out += format(p.float64, base, field, decimals, align, fill, plus, ch, eur); break;
446  case SayArg::SLONGLONG: out += format(p.slonglong, base, field, decimals, align, fill, plus, ch, eur); break;
447  case SayArg::ULONGLONG: out += format(p.ulonglong, base, field, decimals, align, fill, plus, ch, eur); break;
448  default:
449  out += " !!! wrong argument type for '%n' !!! ";
450  break;
451  }
452  }
453  else
454  {
455  out += " !!!missing parameter!!! ";
456  if (ch != -1)
457  i--;
458  }
459  }
460  else
461  {
462  out += " !!!format error: unexpected '";
463  out += (char)ch;
464  out += "' !!! ";
465  }
466 
467  fmtdata = false;
468  align = -1;
469  base = -1;
470  field = -1;
471  decimals = -1;
472  align = -1;
473  fill = -1;
474  plus = -1;
475  eur = -1;
476 
477  param_idx++;
478  }
479  }
480 
481  if (fmtdata)
482  {
483  out += " !!!truncated format!!! ";
484  param_idx++;
485  }
486 
487  if (param_idx < (int)pset.size())
488  out += " !!!too many parameters!!! ";
489 
490  return out;
491  // ... fare in modo che l'output venga generato anche quando non c'e' il carattere finale ...
492 }
493 
494 String Say::euronotation(const String& str, int base) const
495 {
496  String tmp;
497  int pos = (int)str.length();
498  if ( str.contains('.') )
499  {
500  while(pos--)
501  {
502  if (str[pos] == '.')
503  {
504  tmp.insert(0, ',');
505  break;
506  }
507  tmp.insert(0, str[pos]);
508  }
509  if (pos < 0)
510  pos = (int)str.length();
511  }
512 
513  int count = 0;
514  int wait = 3;
515  if (base == 2)
516  wait = 4;
517  if (base == 16)
518  wait = 2;
519  while(pos--)
520  {
521  if (count && count % wait == 0)
522  {
523  tmp.insert(0, '.');
524  }
525  tmp.insert(0, str[pos]);
526  count ++;
527  }
528 
529  return tmp;
530 }
531 
532 String Say::format(unsigned long long n, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const
533 {
534  if (field < 0)
535  field = -field;
536 
537  if (field > 1024)
538  field = 1024;
539 
540  if (decimals < 0)
541  decimals = -decimals;
542  if (decimals > 20)
543  decimals = 20;
544 
545  if (align != 0 && align != 1 && align != 2)
546  align = 0;
547 
548  if (base > 16)
549  base = 16;
550 
551  if (base < 2)
552  base = 2;
553 
554  String str;
555 
556  const char* hex = "0123456789abcdef";
557 
558  // UNSIGNED INT ALGORITHM
559 
560  int k = base;
561  do
562  {
563  int x = (int)(n % base);
564  int c = x/(k/base);
565  str.insert(0, hex[c]);
566  n = n / base;
567  }
568  while(n);
569 
570  if (decimals)
571  {
572  str += '.';
573  int i = decimals;
574  while(i--)
575  str += '0';
576  }
577 
578  bool negative = false;
579 
580  return pipeline(str, base, field, decimals, finalizer, align, eur, fill, negative, plus);
581 }
582 
583 String Say::format(signed long long nn, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const
584 {
585  if (field < 0)
586  field = -field;
587 
588  if (field > 1024)
589  field = 1024;
590 
591  if (decimals < 0)
592  decimals = -decimals;
593  if (decimals > 20)
594  decimals = 20;
595 
596  if (align != 0 && align != 1 && align != 2)
597  align = 0;
598 
599  if (base > 16)
600  base = 16;
601 
602  if (base < 2)
603  base = 2;
604 
605  String str;
606 
607  const char* hex = "0123456789abcdef";
608 
609  // SIGNED INT ALGORITHM
610 
611  bool negative = nn < 0;
612  unsigned long long n;
613 
614  if (nn<0 && -nn<0) // overflow
615  n = (unsigned long long)nn;
616  else
617  if (nn<0)
618  n = - nn;
619  else
620  n = nn;
621 
622  //if (n < 0)
623  // n = 0;
624 
625  int k = base;
626  do
627  {
628  int x = (int)(n % base);
629  int c = x/(k/base);
630  str.insert(0, hex[c]);
631  n = n / base;
632  }
633  while(n);
634 
635  if (decimals)
636  {
637  str += '.';
638  int i = decimals;
639  while(i--)
640  str += '0';
641  }
642 
643  return pipeline(str, base, field, decimals, finalizer, align, eur, fill, negative, plus);
644 }
645 
646 String Say::format(double num, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const
647 {
648  if (field < 0)
649  field = -field;
650  if (field > 1024)
651  field = 1024;
652 
653  if (decimals < 0)
654  decimals = -decimals;
655  if (decimals > 20)
656  decimals = 20;
657 
658  if (align != 0 && align != 1 && align != 2)
659  align = 0;
660 
661  if (base > 16)
662  base = 16;
663 
664  if (base < 2)
665  base = 2;
666 
667  String str;
668 
669  const char* hex = "0123456789abcdef";
670 
671  double f = num;
672 
673  // INDEFINITE = - 127 192 0 0
674  // -INFINITE = - 127 128 0 0
675  // +INFINITE = + 127 128 0 0
676  float tmp = (float)f;
677  unsigned char *nan= (unsigned char*)&tmp;
678  const char* sign = nan[3] >= 128 ? "-" : "+";
679  unsigned char exp = (nan[3] << 1) + (nan[2] >> 7);
680  nan[2] &= 127;
681  unsigned int frac = nan[0] + (nan[1] << 8) + (nan[2] << 16);
682 
683  bool negative = false;
684  if (exp == 255 && frac == 0)
685  {
686  return String(sign) + "#INF";
687  }
688  else
689  if (exp == 255 && frac != 0)
690  {
691  return "#NAN";
692  }
693  else
694  {
695  // ROUNDING FOR FRACTIONAL PART
696 
697  if (finalizer == 'n' || finalizer == 'N')
698  {
699  double fp = f - floor(f);
700  double eps = base/2;
701  int dec = decimals;
702  do
703  {
704  if ( !(dec--) )
705  break;
706 
707  int c = (int)(fp * base);
708  fp = fp * base - c;
709 
710  eps /= base;
711 
712  if (c<0 || c>15)
713  {
714  return "#ERR";
715  }
716 
717  if (dec == 0) // round only if all the decimals are here
718  {
719  // program rounded fp
720  f += eps/base;
721  break;
722  }
723  }
724  while(fp>0);
725  }
726 
727  if (f < 0)
728  {
729  f = -f;
730  negative = true;
731  }
732  double n = floor(f);
733 
734  // INTEGER PART
735 
736  int count = 0;
737  unsigned int base2 = base*base;
738  unsigned int base3 = base*base*base;
739  unsigned int base4 = base*base*base*base;
740  unsigned int base5 = base*base*base*base*base;
741  unsigned int base6 = base*base*base*base*base*base;
742  unsigned int base7 = base*base*base*base*base*base*base; // maximum number in base 16
743  while (floor(n))
744  {
745  if (n>=base7)
746  {
747  n /= base7;
748  count+=7;
749  }
750  else
751  if (n>=base6)
752  {
753  n /= base6;
754  count+=6;
755  }
756  else
757  if (n>=base5)
758  {
759  n /= base5;
760  count+=5;
761  }
762  else
763  if (n>=base4)
764  {
765  n /= base4;
766  count+=4;
767  }
768  else
769  if (n>=base3)
770  {
771  n /= base3;
772  count+=3;
773  }
774  else
775  if (n>=base2)
776  {
777  n /= base2;
778  count+=2;
779  }
780  else
781  {
782  n = n / base;
783  count++;
784  }
785  }
786 
787  // prevents rounding errors
788  double eps = (base / 2.0) / base;
789  for(int i=0; i<count; ++i)
790  {
791  eps /= base;
792  }
793  n+=eps;
794 
795  if (count)
796  {
797  do
798  {
799  int c = (int)(n * (double)base);
800  n = n * (double)base - floor(n * (double)base);
801  int next = (int)(n * base);
802 
803  if (c<0 || c>15 || next<0 || next>15)
804  {
805  return "#ERR";
806  }
807 
808  str += hex[c];
809  }
810  while(--count);
811  }
812  else
813  str += '0';
814 
815  str += '.';
816 
817  // FRACTIONAL PART
818 
819  double fp = f - floor(f);
820  do
821  {
822  int c = (int)(fp * base);
823  fp = fp * base - c;
824 
825  if (c<0 || c>15)
826  {
827  return "#ERR";
828  }
829 
830  str += hex[c];
831  }
832  while(fp>0);
833 
834  // COMMON PIPELINE
835 
836  // (1) EXPONENTIAL SHIFT
837  // (2) CLIP & FILL DECIMALS
838  // (3) EXPONENTIAL DECORATIONS
839  // (4) EURO NOTATION
840  // (5) FIELD, ALIGN AND SIGN
841  // (6) CASE TRANSFORM
842 
843  return pipeline(str, base, field, decimals, finalizer, align, eur, fill, negative, plus);
844  }
845 }
846 
847 String Say::pipeline(const String& in_str, int base, int field, int decimals, int finalizer, int align, int eur, int fill, int negative, int plus) const
848 {
849  String str = in_str;
850  // EXPONENTIAL SHIFT
851 
852  int shift = 0;
853  // exponential notation
854  if (finalizer == 'e' || finalizer == 'E')
855  {
856  int ptpos = (int)str.length(); // point position
857  int nzpos = -1; // non zero position
858  for(int i=0; i<(int)str.length(); ++i)
859  {
860  if(str[i] != '0' && nzpos == -1 && str[i] != '.')
861  nzpos = i;
862  else
863  if (str[i] == '.')
864  ptpos = i;
865  }
866 
867  if (nzpos == -1)
868  shift = 0;
869  else
870  shift = ptpos - nzpos - ( (ptpos > nzpos) ? 1 : 0 );
871 
872  // remove the point
873  str.remove( ptpos, 1 );
874 
875  // remove all the zeros on the left
876  while( str.length() && str[0] == '0' )
877  str.remove(0);
878 
879  // reinsert the point at the 2-nd position
880  // with up to 2 zero if needed.
881  if (str.length() == 1)
882  str += '0';
883  if (str.length() == 0)
884  str = "00";
885 
886  str.insert(1, '.');
887  }
888 
889  // CLIP AND FILL DECIMALS
890 
891  // position of the dot
892  if ( !str.contains('.') )
893  str += ".0";
894  int pos = str.find('.');
895  // number of decimals
896  int decs = (int)str.length() - pos -1;
897  // trim decimals
898  if (decs > decimals)
899  {
900  // remove also the dot
901  int dot = decimals == 0 ? 1 : 0;
902  str.resize(str.length() - (decs - decimals + dot));
903  }
904  else
905  {
906  // add missing decimals
907  int i = decimals - decs;
908  while(i--)
909  str += '0';
910  }
911 
912  // EXPONENTIAL DECORATION
913 
914  if (finalizer == 'e' || finalizer == 'E')
915  {
916  str += 'e';
917  str += format((signed long long)shift, base, 0, 0, 2, 0, 1, 0,0);
918  }
919  else
920  // EURO NOTATION
921 
922  if (eur)
923  str = euronotation(str, base);
924 
925  // FIELD, SIGN, ALIGN
926 
927  int right = (field - (int)str.length()) / 2;
928  right = right < 0 ? 0 : right;
929 
930  int left = (field - (int)str.length()) - right;
931  left = left < 0 ? 0 : left;
932 
933  if (align == 1) // left
934  {
935  right += left;
936  left = 0;
937  }
938  else
939  if (align == 2) // right
940  {
941  left += right;
942  right = 0;
943  }
944 
945  // fill left
946  str.insert(0, (wchar_t)fill, left);
947 
948  // fill right
949  str.append((wchar_t)fill, right);
950 
951  if (negative)
952  {
953  if (left)
954  str.remove(0);
955  else
956  if (right)
957  str.resize(str.length()-1);
958 
959  str.insert(0, '-');
960  }
961  else
962  if(plus)
963  {
964  if (left)
965  str.remove(0);
966  else
967  if (right)
968  str.resize(str.length()-1);
969 
970  str.insert(0, '+');
971  }
972 
973  // CASE TRANSFORM
974 
975  if (finalizer == 'N' || finalizer == 'E')
976  {
977  for(int i=0; i<(int)str.length(); ++i)
978  if (str[i] >= 'a' && str[i] <= 'z')
979  str[i] = str[i] - 'a' + 'A';
980  }
981 
982  return str;
983 }
984 
double float64
Definition: Say.hpp:88
signed long long slonglong
Definition: Say.hpp:90
String pipeline(const String &str, int base, int field, int decimals, int finalizer, int align, int eur, int fill, int negative, int plus) const
Definition: Say.cpp:847
T sign(T a)
Definition: glsl_math.hpp:669
A simple String formatting class.
Definition: Say.hpp:124
enum vl::SayArg::@7 type
String & resize(int character_count)
Resizes the string to the specified character count.
Definition: String.cpp:146
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
SayArg()
Definition: Say.cpp:37
Used internally by the Say class.
Definition: Say.hpp:44
unsigned long long ulonglong
Definition: Say.hpp:89
Visualization Library main namespace.
String euronotation(const String &str, int base) const
Definition: Say.cpp:494
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
float dot(float a, float b)
Definition: glsl_math.hpp:1111
int length() const
Returns the length of the string.
Definition: String.hpp:133
void init()
Definition: Say.cpp:163
String & append(const String &other)
Appends the specified String to another String.
Definition: String.cpp:597
String parse(const Say &pset) const
Definition: Say.cpp:171
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 format(unsigned long long n, int base, int field, int decimals, int align, int fill, int plus, int finalizer, int eur) const
Definition: Say.cpp:532
T exp(T a)
Definition: glsl_math.hpp:460
String format_string
Definition: Say.hpp:127
String str
Definition: Say.hpp:87
T floor(T a)
Definition: glsl_math.hpp:698
String & insert(int pos, const String &str)
Inserts str at position pos.
Definition: String.cpp:781