50 #include "EST_String.h" 52 #include "string_version.h" 71 #if !__GSUB_REENTRANT__ 72 static struct subst *substitutions=NULL;
73 int num_substitutions=0;
85 int EST_String::locate(
const char *s,
int len,
int from,
int &start,
int &end)
const 94 if (from < 0 && -from < size)
96 int endpos=size+from+1;
100 while ((nextsub=strstr(str()+p, s)))
108 else if (from>=0 && from <= size)
109 sub= strstr(str()+from, s);
124 int EST_String::locate(
EST_Regex &ex,
int from,
int &start,
int &end,
int *starts,
int *ends)
const 126 int match_start, match_end;
128 if (from < 0 && -from < size)
130 int endpos=size+from+1;
134 while (ex.
run(str(), p, match_start, match_end, starts, ends))
145 else if (from >=0 && from <= size)
147 if (ex.
run(str(), from, match_start, match_end, starts, ends))
160 int EST_String::extract(
const char *s,
int len,
int pos,
int &start,
int &end)
const 168 return locate(s, len, 0, start, end);
170 if (pos <= size-len && memcmp(str()+pos, s, len)==0)
180 int EST_String::extract(
EST_Regex &ex,
int pos,
int &start,
int &end)
const 182 int match_start, match_end;
185 return locate(ex, 0, start, end);
187 if (pos < size && ex.
run(str(), pos, match_start, match_end) && match_start == pos)
197 EST_String EST_String::chop_internal(
int from,
int len, EST_chop_direction mode)
const 212 if (start >=0 && end <=size && size > 0)
216 return EST_String(str(), size, 0, start);
break;
218 return EST_String(str(), size, start, end-start);
break;
226 EST_String EST_String::chop_internal(
const char *it,
int len,
int from, EST_chop_direction mode)
const 228 CHECK_STRING_ARG(it);
232 if (it && locate(it, len, from, start, end))
236 return EST_String(str(), size, 0, start);
break;
238 return EST_String(str(), size, start, end-start);
break;
246 EST_String EST_String::chop_internal (
EST_Regex &it,
int from, EST_chop_direction mode)
const 250 if (locate(it, from, start, end))
254 return EST_String(str(), size, 0, start);
break;
256 return EST_String(str(), size, start, end-start);
break;
265 int EST_String::gsub_internal (
const char *os,
int olength,
const char *s,
int length)
267 CHECK_STRING_ARG(os);
270 int pos=0, n=0, change=0;
276 #if __GSUB_REENTRANT__ 279 } *substitutions=NULL;
281 int num_substitutions=0;
284 if (s && os && size > 0 && *os !=
'\0')
288 while (locate(os, olength, pos, start, end))
290 if (num_substitutions <= n)
291 substitutions = wrealloc(substitutions,
struct subst, (num_substitutions +=10));
293 substitutions[n].start = start;
294 substitutions[n].end = end;
296 change += length - (end-start);
305 from = (
const char *)memory;
310 {new_memory = chunk_allocate(size+change+1);}
315 cp_make_updatable(memory, size);
324 int start = substitutions[i].start;
325 int end = substitutions[i].end;
326 memcpy(p, from+at, start-at);
328 memcpy(p, s, length);
333 memcpy(p, from+at, size-at);
347 #if __GSUB_REENTRANT__ 349 wfree(substitutions);
356 int EST_String::gsub_internal (
EST_Regex &ex,
const char *s,
int length)
362 bracket_num = length;
364 int pos=0, n=0, change=0;
370 #if __GSUB_REENTRANT__ 371 struct subst *substitutions=NULL;
373 int num_substitutions=0;
381 int start, starts[EST_Regex_max_subexpressions], ends[EST_Regex_max_subexpressions], mlen;
382 while ((start = search(ex, mlen, pos, starts, ends))>=0)
385 if (num_substitutions <= n)
386 substitutions = wrealloc(substitutions,
struct subst, (num_substitutions +=10));
388 substitutions[n].start = start;
389 substitutions[n].end = start+mlen;
392 change += length - mlen;
395 int slen = ends[bracket_num]-starts[bracket_num];
396 change += slen - mlen;
397 substitutions[n].slen = slen;
398 substitutions[n].s = walloc(
char, slen);
399 memcpy(substitutions[n].s, (
const char *)memory+starts[bracket_num], slen);
410 from = (
const char *)memory;
415 {new_memory = chunk_allocate(size+change+1);}
420 cp_make_updatable(memory, size);
429 int start = substitutions[i].start;
430 int end = substitutions[i].end;
431 memcpy(p, from+at, start-at);
435 memcpy(p, s, length);
440 memcpy(p, substitutions[i].s, substitutions[i].slen);
441 wfree(substitutions[i].s);
442 substitutions[i].s=NULL;
443 p += substitutions[i].slen;
447 memcpy(p, from+at, size-at);
458 #if __GSUB_REENTRANT__ 460 wfree(substitutions);
468 int (&starts)[EST_Regex_max_subexpressions],
469 int (&ends)[EST_Regex_max_subexpressions])
477 #if __GSUB_REENTRANT__ 478 struct subst *substitutions=NULL;
480 int num_substitutions=0;
490 for(i=0; i<size; i++)
494 if (memory[i] >=
'0' &&memory[i] <=
'9')
496 int snum = memory[i] -
'0';
497 if (ends[snum] >= 0 && starts[snum] >=0)
499 if (num_substitutions <= n)
500 substitutions = wrealloc(substitutions,
struct subst, (num_substitutions +=10));
502 substitutions[n].start = i-1;
503 substitutions[n].end = i+1;
504 substitutions[n].s = ((
char *)(
void *)(
const char *)source.memory) + starts[snum];
505 substitutions[n].slen = ends[snum] - starts[snum];
506 change += substitutions[n].slen - 2;
513 else if (memory[i] ==
'\\')
520 from = (
const char *)memory;
525 {new_memory = chunk_allocate(size+change+1);}
530 cp_make_updatable(memory, size);
539 int start = substitutions[i].start;
540 int end = substitutions[i].end;
541 memcpy(p, from+at, start-at);
544 memcpy(p, substitutions[i].s, substitutions[i].slen);
545 substitutions[i].s=NULL;
546 p += substitutions[i].slen;
549 memcpy(p, from+at, size-at);
560 #if __GSUB_REENTRANT__ 562 wfree(substitutions);
572 int EST_String::split_internal(
EST_String result[],
int max,
573 const char *s_seperator,
int slen,
584 while (pos < length())
588 if ((*
this)(pos) == quote)
592 while (pos < length())
594 if ((*
this)(pos) == quote)
597 if ((*
this)(pos) != quote)
609 int mstart, mend, matched;
611 matched = locate(s_seperator, slen, pos, mstart, mend);
613 matched = locate(*re_seperator, pos, mstart, mend);
623 else if (pos ==lastspace)
643 result[n++] =
EST_String(*
this, start, end-start);
661 int len=safe_strlen(s);
663 if (extract(s, len, pos, start, end))
664 return start==pos && end==len;
673 if (extract(s.
str(), s.size, pos, start, end))
674 return start==pos && end==s.size;
682 return e.
run_match(
"", pos, starts, ends) >0;
684 return e.
run_match(str(), pos, starts, ends) >0;
693 int bl = safe_strlen(b);
703 memmove((
char *)c + al, b, bl);
721 memmove((
char *)c+al,b.
str(),bl);
731 int al = safe_strlen(a);
741 memmove((
char *)c + al, b.
str(), bl);
759 for(
int j=0; j<n; j++)
760 strncpy(((
char *)it)+j*l, (
const char *)s, l);
770 int bl = safe_strlen(b);
774 memory = chunk_allocate(bl+1, b, bl);
779 grow_chunk(memory, size, size+bl+1);
781 memmove((
char *)memory + size,b,bl);
782 memory(size+bl)=
'\0';
795 memory = NON_CONST_CHUNKPTR(b.memory);
800 grow_chunk(memory, size, size+bl+1);
803 memmove((
char *)memory + size,b.
str(),bl);
805 memory(size+bl)=
'\0';
818 memory = chunk_allocate(size+1, s, size);
829 int start= start_or_fill;
831 len=safe_strlen(s)-start;
835 memory = chunk_allocate(len+1, s+start, len);
841 char fill = start_or_fill;
846 memory = chunk_allocate(len+1);
848 for(
int j=0; j<len;j++)
866 memory = chunk_allocate(len+1, s+start, len);
878 if (start == 0 && len == s.size)
879 memory = NON_CONST_CHUNKPTR(s.memory);
881 memory = chunk_allocate(len+1, s.memory, start, len);
899 #if __FSF_COMPATIBILITY__ 903 memory= chunk_allocate(2, &c, 1);
909 CHECK_STRING_ARG(str);
910 int len = safe_strlen(str);
913 else if (!shareing() && len < size)
914 memcpy((
char *)memory, str, len+1);
916 memory = chunk_allocate(len+1, str, len);
923 memory = chunk_allocate(2, &c, 1);
932 memory = NON_CONST_CHUNKPTR(s.memory);
935 *(
struct EST_dumb_string *)
this = *(
struct EST_dumb_string *)(&s);
945 for (i=0; i < s.
length(); i++)
947 t[i] = tolower(s(i));
958 for (i=0; i < s.
length(); i++)
960 t[i] = toupper(s(i));
974 while (locate(s, pos, start, end))
990 int len=safe_strlen(s);
992 while (locate(s, len, pos, start, end))
1007 while (locate(ex, pos, start, end))
1018 const char quotequote[3] = {quotec, quotec,
'\0'};
1022 result.
gsub(quotequote+1, quotequote+0);
1030 const char quotequote[3] = {quotec, quotec,
'\0'};
1036 result.
gsub(quotequote+0, quotequote+1);
1040 if (result[0] == quotec && result[result.
length()-1] == quotec )
1047 return result.
at(1, result.
length()-2);
1057 if (contains(RXwhite) || contains(quotec))
1058 return quote(quotec);
1067 if ((*
this)(0) == quotec && (*
this)(length()-1) == quotec )
1068 return unquote(quotec);
1077 return (s << str.
str());
1099 result.memory= chunk_allocate(len+1, (
const char *)s1, s1.
length());
1101 int p = s1.length();
1103 { strncpy((
char *)result.memory + p, (
const char *)s2, s2.
length()); p += s2.length(); }
1105 { strncpy((
char *)result.memory + p, (
const char *)s3, s3.
length()); p += s3.length(); }
1107 { strncpy((
char *)result.memory + p, (
const char *)s4, s4.
length()); p += s4.length(); }
1109 { strncpy((
char *)result.memory + p, (
const char *)s5, s5.
length()); p += s5.length(); }
1111 { strncpy((
char *)result.memory + p, (
const char *)s6, s6.
length()); p += s6.length(); }
1113 { strncpy((
char *)result.memory + p, (
const char *)s7, s7.
length()); p += s7.length(); }
1115 { strncpy((
char *)result.memory + p, (
const char *)s8, s8.
length()); p += s8.length(); }
1117 { strncpy((
char *)result.memory + p, (
const char *)s9, s9.
length()); p += s9.length(); }
1119 result.memory(p) =
'\0';
1126 if (a.size == 0 && b.size == 0)
1128 else if (a.size == 0)
1130 else if (b.size == 0)
1133 return strcmp(a.
str(), b.
str());
1136 int compare(
const EST_String &a,
const char *b)
1138 if (a.size == 0 && (b==NULL || *b ==
'\0'))
1140 else if (a.size == 0)
1142 else if (b == NULL || *b ==
'\0')
1145 return strcmp(a.
str(), b);
1149 const unsigned char *table)
1151 if (a.size == 0 && b.size == 0)
1153 else if (a.size == 0)
1155 else if (b.size == 0)
1158 return EST_strcasecmp(a.
str(), b.
str(), table);
1161 int fcompare(
const EST_String &a,
const char *b,
1162 const unsigned char *table)
1164 int bsize = (b ? strlen((
const char *)b) : 0);
1165 if (a.size == 0 && bsize == 0)
1167 else if (a.size == 0)
1169 else if (bsize == 0)
1172 return EST_strcasecmp(a.
str(), (
const char *)b, table);
1175 int operator == (
const char *a,
const EST_String &b)
1177 CHECK_STRING_ARG(a);
1184 return (*a == b(0)) && strcmp(a, b.
str())==0;
1191 else if (b.size == 0)
1194 return a.size == b.size && a(0) == b(0) && memcmp(a.
str(),b.
str(),a.size)==0;
1217 sprintf(buf, format, i);
1242 sprintf(buf, format, i);
1251 sprintf(buf,
"%f", f);
1260 sprintf(buf,
"%f", d);
1265 long EST_String::Long(
bool *valid)
const 1269 long val = strtol(str(), &end, 10);
1271 if (end==NULL|| *end !=
'\0')
1280 printf(
"bad integer number format '%s'\n",
1281 (
const char *)str());
1292 int EST_String::Int(
bool *valid)
const 1294 long val = Long(valid);
1296 if (valid && !*valid)
1299 if (val > INT_MAX || val < INT_MIN)
1308 printf(
"number out of range for integer %ld",
1317 double EST_String::Double(
bool *valid)
const 1321 double val = strtod(str(), &end);
1323 if (end==NULL|| *end !=
'\0')
1332 printf(
"bad decimal number format '%s'",
1333 (
const char *)str());
1344 float EST_String::Float(
bool *valid)
const 1346 double val = Double(valid);
1348 if (valid && !*valid)
1351 if (val > FLT_MAX || val < -FLT_MAX)
1360 printf(
"number out of range for float %f",
EST_String at(int from, int len=0) const
Return part at position.
EST_String(void)
Construct an empty string.
int subst(EST_String source, int(&starts)[EST_Regex_max_subexpressions], int(&ends)[EST_Regex_max_subexpressions])
Substitute the result of a match into a string.
static EST_String Number(int i, int base=10)
Build string from an integer.
EST_String quote_if_needed(const char quotec) const
Return in quotes if there is something to protect (e.g. spaces)
int freq(const char *s) const
Number of occurrences of substring.
static const char * version
Global version string.
int matches(const char *e, int pos=0) const
Exactly match this string?
EST_String unquote_if_needed(const char quotec) const
Remove quotes if any.
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)
int gsub(const char *os, const EST_String &s)
Substitute one string for another.
const char * str(void) const
Get a const-pointer to the actual memory.
int EST_string_size
Type of string size field.
EST_String unquote(const char quotec) const
Remove quotes and unprotect internal quotes.
EST_String & operator+=(const char *b)
Add C string to end of EST_String.
EST_String quote(const char quotec) const
Return the string in quotes with internal quotes protected.
int run(const char *on, int from, int &start, int &end, int *starts=NULL, int *ends=NULL)
Run to find a matching substring.
EST_String & operator=(const char *str)
Assign C string to EST_String.
int run_match(const char *on, int from=0, int *starts=NULL, int *ends=NULL)
Run to see if it matches the entire string.
static const EST_String Empty
Constant empty string.
int length(void) const
Length of string ({not} length of underlying chunk)