Edinburgh Speech Tools  2.1-release
EST_String.cc
Go to the documentation of this file.
1  /*************************************************************************/
2  /* */
3  /* Centre for Speech Technology Research */
4  /* University of Edinburgh, UK */
5  /* Copyright (c) 1997 */
6  /* All Rights Reserved. */
7  /* */
8  /* Permission is hereby granted, free of charge, to use and distribute */
9  /* this software and its documentation without restriction, including */
10  /* without limitation the rights to use, copy, modify, merge, publish, */
11  /* distribute, sublicense, and/or sell copies of this work, and to */
12  /* permit persons to whom this work is furnished to do so, subject to */
13  /* the following conditions: */
14  /* 1. The code must retain the above copyright notice, this list of */
15  /* conditions and the following disclaimer. */
16  /* 2. Any modifications must be clearly marked as such. */
17  /* 3. Original authors' names are not deleted. */
18  /* 4. The authors' names are not used to endorse or promote products */
19  /* derived from this software without specific prior written */
20  /* permission. */
21  /* */
22  /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23  /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24  /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25  /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26  /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27  /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28  /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29  /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30  /* THIS SOFTWARE. */
31  /* */
32  /*************************************************************************/
33  /* Authors : Alan W Black (awb@cstr.ed.ac.uk) */
34  /* Date : January, February 1997 */
35  /* -------------------------------------------------------------------- */
36  /* */
37  /* A non-GNU implementation of a EST_String class to use with non-G++ */
38  /* compilers. */
39  /* */
40  /* Note this is not a full implementation of libg++'s EST_String class */
41  /* just the bits we need */
42  /* */
43  /*************************************************************************/
44 
45 
46 #include <iostream>
47 #include <cstring>
48 #include <cstdio>
49 #include <cctype>
50 #include "EST_String.h"
51 // #include "EST_error.h"
52 #include "string_version.h"
53 #include "EST_math.h"
54 
55 extern "C" {
56 #include "regexp.h"
57 }
58 
59 const char *EST_String::version = "CSTR String Class " STRING_VERSION " " STRING_DATE;
60 
62 
64 
65 struct subst {
67  char *s;
68  int slen;
69 } ;
70 
71 #if !__GSUB_REENTRANT__
72 static struct subst *substitutions=NULL;
74 #endif
75 
76 
77  /********************************************************************\
78  * *
79  * Locate is the basic utility method behind many of the *
80  * manipulations, it finds something in a EST_String, returns a *
81  * success or failure flag and sets start and end to where it was. *
82  * *
83  \********************************************************************/
84 
85 size_t EST_String::locate(const char *s, size_t len, ssize_t from, size_t &start, size_t &end) const
86 {
88 
89  const char *sub=NULL;
90 
91  if (!s)
92  return 0;
93 
94  if (from < 0 && -from < (ssize_t) size)
95  {
96  size_t endpos=size+from+1;
97  size_t p=0;
98  const char *nextsub;
99 
100  while ((nextsub=strstr(str()+p, s)))
101  {
102  p=nextsub-str()+1;
103  if (p > endpos)
104  break;
105  sub=nextsub;
106  }
107  }
108  else if (from>=0 && from <= (ssize_t) size)
109  sub= strstr(str()+from, s);
110 
111  if (sub != NULL)
112  {
113  start = sub-str();
114  end = start + len;
115  return 1;
116  }
117  else
118  {
119  return 0;
120  }
121 
122 }
123 
124 size_t EST_String::locate(EST_Regex &ex, ssize_t from, size_t &start, size_t &end, size_t *starts, size_t *ends) const
125 {
126  size_t match_start, match_end;
127 
128  if (from < 0 && -from < (ssize_t) size)
129  {
130  size_t endpos=size+from+1;
131  size_t p=0;
132  int found=0;
133 
134  while (ex.run(str(), p, match_start, match_end, starts, ends))
135  {
136  found++;
137  start=match_start;
138  end=match_end;
139  p = match_start+1;
140  if (p > endpos)
141  break;
142  }
143  return found >0;
144  }
145  else if (from >=0 && from <= (ssize_t) size)
146  {
147  if (ex.run(str(), from, match_start, match_end, starts, ends))
148  {
149  start = match_start;
150  end=match_end;
151  return 1;
152  }
153  else
154  return 0;
155  }
156  else
157  return 0;
158 }
159 
160 int EST_String::extract(const char *s, size_t len, ssize_t pos, size_t &start, size_t &end) const
161 {
162  CHECK_STRING_ARG(s);
163 
164  if (!s)
165  return 0;
166 
167  if (pos < 0)
168  return locate(s, len, 0, start, end);
169 
170  if (pos <= (ssize_t) (size-len) && memcmp(str()+pos, s, len)==0)
171  {
172  start = pos;
173  end = pos + len;
174  return 1;
175  }
176  else
177  return 0;
178 }
179 
180 int EST_String::extract(EST_Regex &ex, ssize_t pos, size_t &start, size_t &end) const
181 {
182  size_t match_start, match_end;
183 
184  if (pos < 0)
185  return locate(ex, 0, start, end);
186 
187  if (pos < (ssize_t) size && ex.run(str(), pos, match_start, match_end) && match_start == (size_t)pos)
188  {
189  start = match_start;
190  end = match_end;
191  return 1;
192  }
193  else
194  return 0;
195 }
196 
197 EST_String EST_String::chop_internal(ssize_t from, size_t len, EST_chop_direction mode) const
198 {
199  size_t start, end;
200 
201  if (from < 0)
202  {
203  start = size+from;
204  }
205  else
206  {
207  start = from;
208  }
209 
210  end=start+len;
211 
212  if (end <=size && size > 0)
213  switch (mode)
214  {
215  case Chop_Before:
216  return EST_String(str(), size, 0, start); break;
217  case Chop_At:
218  return EST_String(str(), size, start, end-start); break;
219  case Chop_After:
220  return EST_String(str(), size, end, -1);
221  }
222  return EST_String();
223 
224 }
225 
226 EST_String EST_String::chop_internal(const char *it, size_t len, ssize_t from, EST_chop_direction mode) const
227 {
228  CHECK_STRING_ARG(it);
229 
230  size_t start, end;
231 
232  if (it && locate(it, len, from, start, end))
233  switch (mode)
234  {
235  case Chop_Before:
236  return EST_String(str(), size, 0, start); break;
237  case Chop_At:
238  return EST_String(str(), size, start, end-start); break;
239  case Chop_After:
240  return EST_String(str(), size, end, -1);
241  }
242  return EST_String();
243 
244 }
245 
246 EST_String EST_String::chop_internal (EST_Regex &it, ssize_t from, EST_chop_direction mode) const
247 {
248  size_t start=0, end=0;
249 
250  if (locate(it, from, start, end))
251  switch (mode)
252  {
253  case Chop_Before:
254  return EST_String(str(), size, 0, start); break;
255  case Chop_At:
256  return EST_String(str(), size, start, end-start); break;
257  case Chop_After:
258  return EST_String(str(), size, end, -1);
259  }
260  return EST_String();
261 
262 }
263 
264 
265 int EST_String::gsub_internal (const char *os, int olength, const char *s, int length)
266 {
267  CHECK_STRING_ARG(os);
268  CHECK_STRING_ARG(s);
269 
270  int pos=0, n=0, change=0;
271  EST_ChunkPtr new_memory;
272 
273  const char *from;
274  char *to;
275 
276 #if __GSUB_REENTRANT__
277  struct subst {
279  } *substitutions=NULL;
280 
281  int num_substitutions=0;
282 #endif
283 
284  from = (const char *)memory;
285  if (s && os && size > 0 && *os != '\0' && from)
286  {
287  {
288  size_t start, end;
289  while (locate(os, olength, pos, start, end))
290  {
291  if (num_substitutions <= n)
292  substitutions = wrealloc(substitutions, struct subst, (num_substitutions +=10));
293 
294  substitutions[n].start = start;
295  substitutions[n].end = end;
296 
297  change += length - (end-start);
298 
299  n++;
300  pos=end;
301  }
302  }
303 
304  // dubious dealings with the inside of the string
305 
306  if (change > 0)
307  {
308  // Spurious braces make temporary ref to chunk go away
309  {new_memory = chunk_allocate(size+change+1);}
310  to = new_memory;
311  }
312  else
313  {
314  cp_make_updatable(memory, size);
315  to = memory;
316  }
317 
318  int i, at=0;
319  char *p=to;
320 
321  for(i=0; i<n; i++)
322  {
323  int start = substitutions[i].start;
324  int end = substitutions[i].end;
325  memcpy(p, from+at, start-at);
326  p += start-at;
327  memcpy(p, s, length);
328  p += length;
329  at=end;
330  }
331  if (p != from+at)
332  memcpy(p, from+at, size-at);
333 
334  p += size-at;
335  *p = '\0';
336 
337  if (change > 0)
338  memory = new_memory;
339 
340 
341  size += change;
342  }
343 
344  // cout << "gsub n=" << memory.count() << "\n";
345 
346 #if __GSUB_REENTRANT__
347  if (substitutions)
348  wfree(substitutions);
349 #endif
350 
351  return n;
352 
353 }
354 
355 int EST_String::gsub_internal (EST_Regex &ex, const char *s, int length)
356 {
357 
358  int bracket_num=-1;
359 
360  if (s==NULL)
361  bracket_num = length;
362 
363  int pos=0, n=0, change=0;
364  EST_ChunkPtr new_memory;
365 
366  const char *from = (const char*)memory;
367  char *to;
368 
369 #if __GSUB_REENTRANT__
370  struct subst *substitutions=NULL;
371 
372  int num_substitutions=0;
373 #endif
374 
375  // printf("match '%s'\n", (const char *)(*this));
376 
377  if (size > 0 && from != NULL)
378  {
379  {
381  while ((start = search(ex, mlen, pos, starts, ends)) != EST_STRING_ERR_IDX)
382  {
383  // printf("match %d-%d, %d-%d, %d-%d\n", start, start+mlen, starts[0], ends[0], starts[1], ends[1]);
384  if (num_substitutions <= n)
385  substitutions = wrealloc(substitutions, struct subst, (num_substitutions +=10));
386 
387  substitutions[n].start = start;
388  substitutions[n].end = start+mlen;
389 
390  if (s)
391  change += length - mlen;
392  else
393  {
394  int slen = ends[bracket_num]-starts[bracket_num];
395  change += slen - mlen;
396  substitutions[n].slen = slen;
397  substitutions[n].s = walloc(char, slen);
398  memcpy(substitutions[n].s, (const char *)memory+starts[bracket_num], slen);
399 
400  }
401 
402  n++;
403  pos=start+mlen;
404  }
405  }
406 
407  // dubious dealings with the inside of the string
408 
409  if (change > 0)
410  {
411  // Spurious braces make temporary ref to chunk go away
412  {new_memory = chunk_allocate(size+change+1);}
413  to = new_memory;
414  }
415  else
416  {
417  cp_make_updatable(memory, size);
418  to = memory;
419  }
420 
421  int i, at=0;
422  char *p=to;
423 
424  for(i=0; i<n; i++)
425  {
426  int start = substitutions[i].start;
427  int end = substitutions[i].end;
428  memcpy(p, from+at, start-at);
429  p += start-at;
430  if (s)
431  {
432  memcpy(p, s, length);
433  p += length;
434  }
435  else
436  {
437  memcpy(p, substitutions[i].s, substitutions[i].slen);
438  wfree(substitutions[i].s);
439  substitutions[i].s=NULL;
440  p += substitutions[i].slen;
441  }
442  at=end;
443  }
444  if ( (from + at) != p) /* Do not copy if source == destination */
445  memcpy(p, from+at, size-at);
446 
447  p += size-at;
448  *p = '\0';
449 
450  if (change > 0)
451  memory = new_memory;
452 
453  size += change;
454  }
455 
456 #if __GSUB_REENTRANT__
457  if (substitutions)
458  wfree(substitutions);
459 #endif
460 
461  return n;
462 
463 }
464 
466  size_t (&starts)[EST_Regex_max_subexpressions],
467  size_t (&ends)[EST_Regex_max_subexpressions])
468 {
469  size_t n=0;
470  ssize_t change=0;
471  EST_ChunkPtr new_memory;
472 
473  const char *from;
474  char *to;
475 
476 #if __GSUB_REENTRANT__
477  struct subst *substitutions=NULL;
478 
479  size_t num_substitutions=0;
480 #endif
481 
482  // printf("match '%s'\n", (const char *)(*this));
483 
484  size_t i;
485  if (size > 0)
486  {
487  int escaped=0;
488 
489  for(i=0; i<size; i++)
490  {
491  if (escaped)
492  {
493  if (memory[i] >= '0' &&memory[i] <= '9')
494  {
495  int snum = memory[i] - '0';
496  if (ends[snum] != EST_STRING_ERR_IDX && starts[snum] != EST_STRING_ERR_IDX)
497  {
498  if (num_substitutions <= n)
499  substitutions = wrealloc(substitutions, struct subst, (num_substitutions +=10));
500 
501  substitutions[n].start = i-1;
502  substitutions[n].end = i+1;
503  substitutions[n].s = ((char *)(void *)(const char *)source.memory) + starts[snum];
504  substitutions[n].slen = ends[snum] - starts[snum];
505  change += substitutions[n].slen - 2;
506 
507  n++;
508  }
509  }
510  escaped=0;
511  }
512  else if (memory[i] == '\\')
513  escaped=1;
514  }
515 
516 
517  // dubious dealings with the inside of the string
518 
519  from = (const char *)memory;
520 
521  if (change > 0)
522  {
523  // Spurious braces make temporary ref to chunk go away
524  {new_memory = chunk_allocate(size+change+1);}
525  to = new_memory;
526  }
527  else
528  {
529  cp_make_updatable(memory, size);
530  to = memory;
531  }
532 
533  int at=0;
534  char *p=to;
535 
536  for(i=0; i<n; i++)
537  {
538  int start = substitutions[i].start;
539  int end = substitutions[i].end;
540  memcpy(p, from+at, start-at);
541  p += start-at;
542 
543  memcpy(p, substitutions[i].s, substitutions[i].slen);
544  substitutions[i].s=NULL;
545  p += substitutions[i].slen;
546  at=end;
547  }
548  memcpy(p, from+at, size-at);
549 
550  p += size-at;
551  *p = '\0';
552 
553  if (change > 0)
554  memory = new_memory;
555 
556  size += change;
557  }
558 
559 #if __GSUB_REENTRANT__
560  if (substitutions)
561  wfree(substitutions);
562 #endif
563 
564  return n;
565 }
566 
567 // Pass in the two possible separators as pointers so we don't have to
568 // duplicate all the code. Inline definitions of the friend functions
569 // takes care of the pretty interface.
570 
571 int EST_String::split_internal(EST_String result[], int max,
572  const char *s_seperator, size_t slen,
573  EST_Regex *re_seperator,
574  char quote) const
575 {
576  int n=0;
577  size_t pos=0;
578  size_t start, end;
579  size_t lastspace=0;
580 
581  if (size>0)
582  {
583  while (pos < length())
584  {
585  start= -1;
586  end= -1;
587  if ((*this)(pos) == quote)
588  {
589  start=pos;
590  pos++;
591  while (pos < length())
592  {
593  if ((*this)(pos) == quote)
594  {
595  pos++;
596  if ((*this)(pos) != quote)
597  break;
598  else
599  pos++;
600  }
601  else
602  pos++;
603  }
604  end=pos;
605  }
606  else
607  {
608  size_t mstart, mend, matched;
609  if (s_seperator)
610  matched = locate(s_seperator, slen, pos, mstart, mend);
611  else
612  matched = locate(*re_seperator, pos, mstart, mend);
613 
614  if (matched)
615  if (mstart != pos)
616  {
617  start=pos;
618  end=mstart;
619  pos=mend;
620  lastspace=mend;
621  }
622  else if (pos ==lastspace)
623  {
624  start=pos;
625  end=pos;
626  pos=mend;
627  lastspace=mend;
628  }
629  else
630  {
631  pos=mend;
632  lastspace=mend;
633  }
634  else
635  {
636  start=pos;
637  end=length();
638  pos=end;
639  }
640  }
641  if (start!= EST_STRING_ERR_IDX)
642  result[n++] = EST_String(*this, start, end-start);
643  if (n==max)
644  break;
645  }
646  }
647 
648  return n;
649 }
650 
651 int EST_String::matches(const char *s, ssize_t pos) const
652 {
653  CHECK_STRING_ARG(s);
654 
655  size_t start, end;
656 
657  if (!s)
658  return 0;
659 
660  size_t len=safe_strlen(s);
661 
662  if (extract(s, len, pos, start, end))
663  return ((ssize_t)start)==pos && end==len;
664  else
665  return 0;
666 }
667 
668 int EST_String::matches(const EST_String &s, ssize_t pos) const
669 {
670  size_t start, end;
671 
672  if (extract(s.str(), s.size, pos, start, end))
673  return ((ssize_t)start)==pos && end==s.size;
674  else
675  return 0;
676 }
677 
678 int EST_String::matches(EST_Regex &e, ssize_t pos, size_t *starts, size_t *ends) const
679 {
680  if (size==0)
681  return e.run_match("", pos, starts, ends) >0;
682  else
683  return e.run_match(str(), pos, starts, ends) >0;
684 }
685 
686 
687 EST_String operator + (const EST_String &a, const char *b)
688 {
689  CHECK_STRING_ARG(b);
690 
691  int al = a.size;
692  int bl = safe_strlen(b);
693 
694  if (al == 0)
695  return EST_String(b, 0, bl);
696  if (bl == 0)
697  return EST_String(a);
698 
699  EST_ChunkPtr c = chunk_allocate(al+bl+1, a.str(), al);
700 
701  if (bl>0)
702  memmove((char *)c + al, b, bl);
703  c(al+bl)='\0';
704 
705  return EST_String(al+bl, c);
706 }
707 
709 {
710  int al = a.size;
711  int bl = b.size;
712 
713  if (al == 0)
714  return EST_String(b);
715  if (bl == 0)
716  return EST_String(a);
717 
718  EST_ChunkPtr c = chunk_allocate(al+bl+1, a.str(), al);
719 
720  memmove((char *)c+al,b.str(),bl);
721  c(al+bl)='\0';
722 
723  return EST_String(al+bl, c);
724 }
725 
726 EST_String operator + (const char *a, const EST_String &b)
727 {
728  CHECK_STRING_ARG(a);
729 
730  int al = safe_strlen(a);
731  int bl = b.size;
732 
733  if (bl == 0)
734  return EST_String(a, 0, al);
735  if (al == 0)
736  return EST_String(b);
737 
738  EST_ChunkPtr c = chunk_allocate(al+bl+1, a, al);
739 
740  memmove((char *)c + al, b.str(), bl);
741 
742  c(al+bl)='\0';
743 
744  return EST_String(al+bl, c);
745 }
746 
748 {
749 
750  if (n<1)
751  return "";
752  int j;
753  int l = s.length();
754  int sz = n * l;
755  char *dest;
756  const char *src;
757  EST_String it(NULL, 0, sz);
758  src = (const char *)s;
759  dest = (char*)it;
760  if (src== NULL || dest == NULL) return "";
761 
762  /* If s is an empty string, then return an empty string */
763  if (l <= 0) return it;
764 
765  for(j=0; j<n; j++)
766  memcpy(dest+j*l, src, l);
767  dest[n*l]='\0';
768 
769  return it;
770 }
771 
773 
774 {
775  CHECK_STRING_ARG(b);
776 
777  int bl = safe_strlen(b);
778 
779  if (size == 0)
780  {
781  memory = chunk_allocate(bl+1, b, bl);
782  size = bl;
783  return *this;
784  }
785 
786  grow_chunk(memory, size, size+bl+1);
787 
788  memmove((char *)memory + size,b,bl);
789  memory(size+bl)='\0';
790  size += bl;
791 
792  return *this;
793 }
794 
796 
797 {
798  int bl = b.size;
799 
800  if (size == 0)
801  {
802  memory = NON_CONST_CHUNKPTR(b.memory);
803  size = b.size;
804  return *this;
805  }
806 
807  grow_chunk(memory, size, size+bl+1);
808 
809  if (bl >0)
810  memmove((char *)memory + size,b.str(),bl);
811 
812  memory(size+bl)='\0';
813  size += bl;
814 
815  return *this;
816 }
817 
818 EST_String::EST_String(const char *s)
819 {
820  CHECK_STRING_ARG(s);
821 
822  size=safe_strlen(s);
823 
824  if (size != 0)
825  memory = chunk_allocate(size+1, s, size);
826  else
827  memory=NULL;
828  }
829 
830 
831 EST_String::EST_String(const char *s, int start_or_fill, ssize_t len)
832 {
833 
834  if (s)
835  {
836  int start= start_or_fill;
837  if (len <0)
838  len=safe_strlen(s)-start;
839 
840  size=len;
841  if (size != 0)
842  memory = chunk_allocate(len+1, s+start, len);
843  else
844  memory=NULL;
845  }
846  else
847  {
848  char fill = start_or_fill;
849  if (len<0) len=0;
850  size=len;
851  if (size != 0)
852  {
853  memory = chunk_allocate(len+1);
854  char *p = memory;
855  for(int j=0; j<len;j++)
856  p[j] = fill;
857  p[len]='\0';
858  }
859  else
860  memory=NULL;
861  }
862 }
863 
864 EST_String::EST_String(const char *s, size_t s_size, size_t start, ssize_t len)
865 {
866  CHECK_STRING_ARG(s);
867 
868  if (len <0)
869  len=s_size-start;
870 
871  size=len;
872  if (size != 0)
873  memory = chunk_allocate(len+1, s+start, len);
874  else
875  memory=NULL;
876 }
877 
879 {
880  size_t actual_len;
881  if (len <0)
882  actual_len = s.size-start;
883  else
884  actual_len = len;
885 
886  size=len;
887 
888  if (start == 0 && actual_len == s.size)
889  memory = NON_CONST_CHUNKPTR(s.memory);
890  else if (size != 0)
891  memory = chunk_allocate(len+1, s.memory, start, actual_len);
892  else
893  memory = NULL;
894 }
895 
896 /*
897 EST_String::EST_String(const EST_String &s)
898 {
899 #if 1
900  static EST_ChunkPtr hack = NON_CONST_CHUNKPTR(s.memory);
901  memory = NON_CONST_CHUNKPTR(s.memory);
902  size = s.size;
903 #else
904  *(struct EST_dumb_string *)this = *(struct EST_dumb_string *)(&s);
905 #endif
906 }
907 */
908 
910 {
911  CHECK_STRING_ARG(str);
912  size_t len = safe_strlen(str);
913  if (!len)
914  memory = NULL;
915  else if (!shareing() && len < size)
916  memcpy((char *)memory, str, len+1);
917  else if (len)
918  memory = chunk_allocate(len+1, str, len);
919  size=len;
920  return *this;
921 }
922 
924 {
925  memory = chunk_allocate(2, &c, 1);
926  size=1;
927  return *this;
928 }
929 
931 {
932 #if 1
933 /* static EST_ChunkPtr hack = s.memory; */
934  memory = NON_CONST_CHUNKPTR(s.memory);
935  size = s.size;
936 #else
937  *(struct EST_dumb_string *)this = *(struct EST_dumb_string *)(&s);
938 #endif
939  return *this;
940 }
941 
943 {
944  EST_String t = EST_String(s.size, chunk_allocate(s.size+1, s.str(), s.size));
945  size_t i;
946 
947  for (i=0; i < s.length(); i++)
948  if (isupper(s(i)))
949  t[i] = tolower(s(i));
950  else
951  t[i] = s(i);
952  return t;
953 }
954 
956 {
957  EST_String t = EST_String(s.size, chunk_allocate(s.size+1, s.str(), s.size));
958  size_t i;
959 
960  for (i=0; i < s.length(); i++)
961  if (islower(s(i)))
962  t[i] = toupper(s(i));
963  else
964  t[i] = s(i);
965  return t;
966 }
967 
968 
969 size_t
971 {
972  ssize_t pos=0;
973  size_t n=0;
974  size_t start, end;
975 
976  while (locate(s, pos, start, end))
977  {
978  n++;
979  pos=end;
980  }
981  return n;
982 }
983 
984 size_t
985 EST_String::freq(const char *s) const
986 {
987  CHECK_STRING_ARG(s);
988 
989  ssize_t pos=0;
990  size_t n=0;
991  size_t start, end;
992  size_t len=safe_strlen(s);
993 
994  while (locate(s, len, pos, start, end))
995  {
996  n++;
997  pos=end;
998  }
999  return n;
1000 }
1001 
1002 size_t
1004 {
1005  ssize_t pos=0;
1006  size_t n=0;
1007  size_t start, end=0;
1008 
1009  while (locate(ex, pos, start, end))
1010  {
1011  n++;
1012  pos=end;
1013  }
1014  return n;
1015 }
1016 
1017 EST_String EST_String::quote(const char quotec) const
1018 {
1019 
1020  const char quotequote[3] = {quotec, quotec, '\0'};
1021 
1022  EST_String result(*this);
1023 
1024  result.gsub(quotequote+1, quotequote+0);
1025 
1026  return EST_String::cat(quotequote+1, result, quotequote+1);
1027 }
1028 
1029 EST_String EST_String::unquote(const char quotec) const
1030 {
1031 
1032  const char quotequote[3] = {quotec, quotec, '\0'};
1033 
1034  EST_String result(*this);
1035 
1036  // cout << "before unqote '" << result << "'\n";
1037 
1038  result.gsub(quotequote+0, quotequote+1);
1039 
1040  // cout << "after unqote '" << result << "'\n";
1041 
1042  if (result[0] == quotec && result[result.length()-1] == quotec )
1043  {
1044 #if 1
1045  /* Spurious local variable to get arounf SunCC 4.0 being broken */
1046  EST_String res= result.at(1, result.length()-2);
1047  return res;
1048 #else
1049  return result.at(1, result.length()-2);
1050 #endif
1051  }
1052  else
1053  return result;
1054 }
1055 
1056 EST_String EST_String::quote_if_needed(const char quotec) const
1057 {
1058 
1059  if (contains(RXwhite) || contains(quotec))
1060  return quote(quotec);
1061 
1062  return *this;
1063 }
1064 
1065 
1067 {
1068 
1069  if ((*this)(0) == quotec && (*this)(length()-1) == quotec )
1070  return unquote(quotec);
1071 
1072  return *this;
1073 }
1074 
1075 ostream &operator << (ostream &s, const EST_String &str)
1076 
1077 {
1078  if (str.size > 0)
1079  return (s << str.str());
1080  else
1081  return (s << "");
1082 }
1083 
1085  const EST_String s2,
1086  const EST_String s3,
1087  const EST_String s4,
1088  const EST_String s5,
1089  const EST_String s6,
1090  const EST_String s7,
1091  const EST_String s8,
1092  const EST_String s9
1093  )
1094 {
1095  int len=(s1.length()+s2.length()+s3.length()+s4.length()+s5.length() +
1096  s6.length()+s7.length()+s8.length()+s9.length());
1097 
1098  EST_String result;
1099 
1100  result.size=len;
1101  result.memory= chunk_allocate(len+1, (const char *)s1, s1.length());
1102 
1103  int p = s1.length();
1104  if (s2.length())
1105  { strncpy((char *)result.memory + p, (const char *)s2, s2.length()); p += s2.length(); }
1106  if (s3.length())
1107  { strncpy((char *)result.memory + p, (const char *)s3, s3.length()); p += s3.length(); }
1108  if (s4.length())
1109  { strncpy((char *)result.memory + p, (const char *)s4, s4.length()); p += s4.length(); }
1110  if (s5.length())
1111  { strncpy((char *)result.memory + p, (const char *)s5, s5.length()); p += s5.length(); }
1112  if (s6.length())
1113  { strncpy((char *)result.memory + p, (const char *)s6, s6.length()); p += s6.length(); }
1114  if (s7.length())
1115  { strncpy((char *)result.memory + p, (const char *)s7, s7.length()); p += s7.length(); }
1116  if (s8.length())
1117  { strncpy((char *)result.memory + p, (const char *)s8, s8.length()); p += s8.length(); }
1118  if (s9.length())
1119  { strncpy((char *)result.memory + p, (const char *)s9, s9.length()); p += s9.length(); }
1120 
1121  result.memory(p) = '\0';
1122 
1123  return result;
1124 }
1125 
1126 int compare(const EST_String &a, const EST_String &b)
1127 {
1128  if (a.size == 0 && b.size == 0)
1129  return 0;
1130  else if (a.size == 0)
1131  return -1;
1132  else if (b.size == 0)
1133  return 1;
1134  else
1135  return strcmp(a.str(), b.str());
1136 }
1137 
1138 int compare(const EST_String &a, const char *b)
1139 {
1140  if (a.size == 0 && (b==NULL || *b == '\0'))
1141  return 0;
1142  else if (a.size == 0)
1143  return -1;
1144  else if (b == NULL || *b == '\0')
1145  return 1;
1146  else
1147  return strcmp(a.str(), b);
1148 }
1149 
1150 int fcompare(const EST_String &a, const EST_String &b,
1151  const unsigned char *table)
1152 {
1153  if (a.size == 0 && b.size == 0)
1154  return 0;
1155  else if (a.size == 0)
1156  return -1;
1157  else if (b.size == 0)
1158  return 1;
1159  else
1160  return EST_strcasecmp(a.str(), b.str(), table);
1161 }
1162 
1163 int fcompare(const EST_String &a, const char *b,
1164  const unsigned char *table)
1165 {
1166  int bsize = (b ? strlen((const char *)b) : 0);
1167  if (a.size == 0 && bsize == 0)
1168  return 0;
1169  else if (a.size == 0)
1170  return -1;
1171  else if (bsize == 0)
1172  return 1;
1173  else
1174  return EST_strcasecmp(a.str(), (const char *)b, table);
1175 }
1176 
1177 int operator == (const char *a, const EST_String &b)
1178 {
1179  CHECK_STRING_ARG(a);
1180 
1181  if (!a)
1182  return 0;
1183  else if (b.size==0)
1184  return *a == '\0';
1185  else
1186  return (*a == b(0)) && strcmp(a, b.str())==0;
1187 }
1188 
1189 int operator == (const EST_String &a, const EST_String &b)
1190 {
1191  if (a.size==0)
1192  return b.size == 0;
1193  else if (b.size == 0)
1194  return 0;
1195  else
1196  return a.size == b.size && a(0) == b(0) && memcmp(a.str(),b.str(),a.size)==0;
1197 }
1198 
1200 {
1201  char buf[64];
1202  const char *format;
1203 
1204  switch (b)
1205  {
1206  case 8:
1207  format="0%o";
1208  break;
1209  case 10:
1210  format="%d";
1211  break;
1212  case 16:
1213  format="0x%x";
1214  break;
1215  default:
1216  format="??%d??";
1217  break;
1218  }
1219  sprintf(buf, format, i);
1220 
1221  return EST_String(buf);
1222 }
1223 
1225 {
1226  char buf[64];
1227  const char *format;
1228 
1229  switch (b)
1230  {
1231  case 8:
1232  format="0%lo";
1233  break;
1234  case 10:
1235  format="%ld";
1236  break;
1237  case 16:
1238  format="0x%lx";
1239  break;
1240  default:
1241  format="??%ld??";
1242  break;
1243  }
1244  sprintf(buf, format, i);
1245 
1246  return EST_String(buf);
1247 }
1248 
1250 {
1251  char buf[64];
1252 
1253  sprintf(buf, "%f", f);
1254 
1255  return EST_String(buf);
1256 }
1257 
1259 {
1260  char buf[64];
1261 
1262  sprintf(buf, "%f", d);
1263 
1264  return EST_String(buf);
1265 }
1266 
1267 long EST_String::Long(bool *valid) const
1268 {
1269  char *end;
1270 
1271  long val = strtol(str(), &end, 10);
1272 
1273  if (end==NULL|| *end != '\0')
1274  {
1275  if (valid != NULL)
1276  {
1277  *valid=0;
1278  return 0L;
1279  }
1280  else
1281  {
1282  printf("bad integer number format '%s'\n",
1283  (const char *)str());
1284  exit(0);
1285  }
1286  }
1287 
1288  if (valid)
1289  *valid=1;
1290 
1291  return val;
1292 }
1293 
1294 int EST_String::Int(bool *valid) const
1295 {
1296  long val = Long(valid);
1297 
1298  if (valid && !*valid)
1299  return 0L;
1300 
1301  if (val > INT_MAX || val < INT_MIN)
1302  {
1303  if (valid != NULL)
1304  {
1305  *valid=0;
1306  return 0L;
1307  }
1308  else
1309  {
1310  printf("number out of range for integer %ld",
1311  val);
1312  exit(0);
1313  }
1314  }
1315 
1316  return val;
1317 }
1318 
1319 double EST_String::Double(bool *valid) const
1320 {
1321  char *end;
1322 
1323  double val = strtod(str(), &end);
1324 
1325  if (end==NULL|| *end != '\0')
1326  {
1327  if (valid != NULL)
1328  {
1329  *valid=0;
1330  return 0.0;
1331  }
1332  else
1333  {
1334  printf("bad decimal number format '%s'",
1335  (const char *)str());
1336  exit(0);
1337  }
1338  }
1339 
1340  if (valid)
1341  *valid=1;
1342 
1343  return val;
1344 }
1345 
1346 float EST_String::Float(bool *valid) const
1347 {
1348  double val = Double(valid);
1349 
1350  if (valid && !*valid)
1351  return 0.0;
1352 
1353  if (val > FLT_MAX || val < -FLT_MAX)
1354  {
1355  if (valid != NULL)
1356  {
1357  *valid=0;
1358  return 0.0;
1359  }
1360  else
1361  {
1362  printf("number out of range for float %f",
1363  val);
1364  exit(0);
1365  }
1366  }
1367 
1368  return val;
1369 }
1370 
1371 
1372 
int Int(void) const
Definition: EST_String.h:259
float end(const EST_Item &item)
Definition: EST_item_aux.cc:96
#define walloc(TYPE, SIZE)
Definition: EST_walloc.h:52
int subst(EST_String source, size_t(&starts)[EST_Regex_max_subexpressions], size_t(&ends)[EST_Regex_max_subexpressions])
Substitute the result of a match into a string.
Definition: EST_String.cc:465
InputSource source
Definition: rxp.c:24
EST_String unquote(const char quotec) const
Remove quotes and unprotect internal quotes.
Definition: EST_String.cc:1029
EST_String(void)
Construct an empty string.
Definition: EST_String.h:201
void grow_chunk(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size newsize)
Definition: EST_Chunk.cc:311
EST_String quote_if_needed(const char quotec) const
Return in quotes if there is something to protect (e.g. spaces)
Definition: EST_String.cc:1056
static EST_String Number(int i, int base=10)
Build string from an integer.
Definition: EST_String.cc:1199
size_t freq(const char *s) const
Number of occurrences of substring.
Definition: EST_String.cc:985
A Regular expression class to go with the CSTR EST_String class.
Definition: EST_Regex.h:56
#define safe_strlen(S)
Definition: EST_String.h:98
ostream & operator<<(ostream &s, const EST_String &str)
Definition: EST_String.cc:1075
#define EST_Regex_max_subexpressions
Definition: EST_Regex.h:150
EST_String operator+(const EST_String &a, const char *b)
Definition: EST_String.cc:687
long Long(void) const
Definition: EST_String.h:263
static const char * version
Global version string.
Definition: EST_String.h:107
int ssize_t
#define STRING_DATE
size_t num_substitutions
Definition: EST_String.cc:73
#define STRING_VERSION
void extract(EST_Track &orig, float start, float end, EST_Track &res)
EST_String upcase(const EST_String &s)
Definition: EST_String.cc:955
size_t EST_string_size
Type of string size field.
Definition: EST_String.h:113
int contains(EST_TList< int > &l, int n)
Definition: EST_cluster.cc:82
static EST_String cat(const EST_String s1, const EST_String s2=Empty, const EST_String s3=Empty, const EST_String s4=Empty, const EST_String s5=Empty, const EST_String s6=Empty, const EST_String s7=Empty, const EST_String s8=Empty, const EST_String s9=Empty)
Definition: EST_String.cc:1084
float max(float a, float b)
Definition: EST_cluster.cc:143
#define FLT_MAX
Definition: EST_math.h:134
int gsub(const char *os, const EST_String &s)
Substitute one string for another.
Definition: EST_String.h:391
EST_String EST_String_nullString
Definition: EST_String.cc:63
EST_String downcase(const EST_String &s)
Definition: EST_String.cc:942
EST_FMatrix sub(const EST_FMatrix &a, ssize_t row, ssize_t col)
Definition: vec_mat_aux.cc:187
EST_Regex RXwhite("[ \n\t\r]+")
White space.
float Float(void) const
Definition: EST_String.h:267
int run_match(const char *on, size_t from=0, size_t *starts=NULL, size_t *ends=NULL)
Run to see if it matches the entire string.
Definition: EST_Regex.cc:277
int operator==(const char *a, const EST_String &b)
Definition: EST_String.cc:1177
#define EST_STRING_ERR_IDX
Definition: EST_String.h:116
#define wrealloc(PTR, TYPE, SIZE)
Definition: EST_walloc.h:53
NULL
Definition: EST_WFST.cc:55
f
Definition: EST_item_aux.cc:48
int fcompare(const EST_String &a, const EST_String &b, const unsigned char *table)
Definition: EST_String.cc:1150
int matches(const char *e, ssize_t pos=0) const
Exactly match this string?
Definition: EST_String.cc:651
EST_String & operator+=(const char *b)
Add C string to end of EST_String.
Definition: EST_String.cc:772
void cp_make_updatable(EST_ChunkPtr &cp, EST_Chunk::EST_chunk_size inuse)
Definition: EST_Chunk.cc:280
EST_String operator*(const EST_String &s, int n)
Definition: EST_String.cc:747
#define CHECK_STRING_ARG(S)
Definition: EST_String.h:99
float start(const EST_Item &item)
Definition: EST_item_aux.cc:52
EST_ChunkPtr chunk_allocate(size_t bytes)
Definition: EST_Chunk.cc:231
size_t length(void) const
Length of string ({not} length of underlying chunk)
Definition: EST_String.h:231
EST_String & operator=(const char *str)
Assign C string to EST_String.
Definition: EST_String.cc:909
LISP quote(LISP item)
Definition: siod.cc:252
int EST_strcasecmp(const char *s1, const char *s2, const unsigned char *charmap)
const char * str(void) const
Get a const-pointer to the actual memory.
Definition: EST_String.h:235
double Double(void) const
Definition: EST_String.h:271
EST_String unquote_if_needed(const char quotec) const
Remove quotes if any.
Definition: EST_String.cc:1066
int compare(const EST_String &a, const EST_String &b)
Definition: EST_String.cc:1126
EST_String
EST_String at(int from, int len=0) const
Return part at position.
Definition: EST_String.h:292
void wfree(void *p)
Definition: walloc.c:131
EST_String quote(const char quotec) const
Return the string in quotes with internal quotes protected.
Definition: EST_String.cc:1017
static const EST_String Empty
Constant empty string.
Definition: EST_String.h:110
int run(const char *on, size_t from, size_t &start, size_t &end, size_t *starts=NULL, size_t *ends=NULL)
Run to find a matching substring.
Definition: EST_Regex.cc:244