Annotation of parser3/src/main/pa_string.C, revision 1.172.2.21.2.3
1.45 paf 1: /** @file
1.55 paf 2: Parser: string class. @see untasize_t.C.
1.46 paf 3:
1.172.2.11 paf 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.138 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.164 paf 6: */
1.46 paf 7:
1.172.2.21.2. (paf 8:): static const char* IDENT_STRING_C="$Date: 2003/03/18 16:00:07 $";
1.4 paf 9:
1.70 paf 10: #include "pcre.h"
11:
1.12 paf 12: #include "pa_string.h"
1.22 paf 13: #include "pa_exception.h"
1.61 paf 14: #include "pa_table.h"
1.101 parser 15: #include "pa_dictionary.h"
1.132 paf 16: #include "pa_charset.h"
1.60 paf 17:
1.172.2.2 paf 18: // helpers
1.139 paf 19:
1.172.2.2 paf 20: /// String::match uses this as replace & global search table columns
1.139 paf 21:
1.172.2.4 paf 22: const int MAX_MATCH_GROUPS=100;
23:
1.172.2.14 paf 24: class String_match_table_template_columns: public ArrayString {
1.172.2.2 paf 25: public:
1.172.2.4 paf 26: String_match_table_template_columns() {
1.172.2.21.2. (paf 27:): *this+=new String("prematch");
28:): *this+=new String("match");
29:): *this+=new String("postmatch");
1.172.2.4 paf 30: for(int i=0; i<MAX_MATCH_GROUPS; i++) {
1.172.2.21.2. (paf 31:): char *cname=new char[3/*strlen("100")*/+1/*terminating 0*/];
32:): *this+=new String(cname, sprintf(cname, "%d", 1+i));
1.172.2.2 paf 33: }
1.172.2.21 paf 34: }
1.172.2.4 paf 35: };
36:
1.172.2.21.2. (paf 37:): Table string_match_table_template(new String_match_table_template_columns);
1.172.2.2 paf 38:
1.172.2.21.2. (paf 39:): // String::ArrayFragment methods
40:):
41:): String::ArrayFragment& String::ArrayFragment::append(const ArrayFragment& src,
42:): size_t substr_start, size_t substr_end) {
43:): if(substr_start==substr_end)
44:): return *this;
45:):
46:): size_t fragment_start=0;
47:): size_t fragment_end;
48:): for(Array_iterator<element_type> i(src); ; fragment_start=fragment_end) {
49:): const element_type& fragment=i.next();
50:): fragment_end=fragment_start+fragment.size;
51:):
52:): if(substr_start<fragment_start) // not reached fragments which may include 'substr'?
53:): continue;
54:):
55:): // found first fragment including piece of 'substr'
56:): size_t piece_end=min(substr_end, fragment_end);
57:): *this+=Fragment(fragment.lang, piece_end-substr_start);
58:):
59:): while(substr_end>fragment_end) { // are there more fragments including pieces of 'substr'?
60:): const element_type& fragment=i.next();
61:): fragment_end=fragment_start+fragment.size;
62:):
63:): if(substr_end>fragment_end) // are there still more?
64:): simple_append(Fragment(fragment.lang, fragment.size)); // appending whole fragment
65:): else { // no, it was last
66:): simple_append(Fragment(fragment.lang, substr_end-fragment_start));
67:): goto break2;
68:): }
69:): }
70:):
71:): break;
72:): }
73:): break2:
74:):
75:): return *this;
76:): }
77:): /*
78:): void String::ArrayFragment::mid(ArrayFragment& result, size_t substr_start, size_t substr_end) {
79:): }
80:): */
81:):
82:): // String methods
1.172.2.2 paf 83:
1.172.2.21.2. (paf 84:): String::String(const char* src, size_t src_size, bool tainted): body(CORD_EMPTY) {
1.41 paf 85: if(src)
1.75 paf 86: if(tainted)
87: APPEND_TAINTED(src, src_size, 0, 0);
1.41 paf 88: else
1.75 paf 89: APPEND_CLEAN(src, src_size, 0, 0);
1.1 paf 90: }
1.140 paf 91:
1.172.2.21.2. (paf 92:): String::String(const String& src): body(src.body), fragments(src.fragments) {}
1.28 paf 93:
1.13 paf 94: String& String::real_append(STRING_APPEND_PARAMS) {
1.9 paf 95: if(!src)
96: return *this;
1.26 paf 97: if(!size)
98: size=strlen(src);
99: if(!size)
1.9 paf 100: return *this;
1.122 paf 101:
1.172.2.21.2. (paf 102:): body=CORD_cat_char_star(body, src, size);
103:): fragments+=Fragment(lang, size);
1.1 paf 104:
105: return *this;
106: }
107:
1.172.2.21.2. (paf 108:): static int CORD_batched_iter_fn_generic_hash_code(const char * s, void * client_data) {
109:): uint& result=*static_cast<uint*>(client_data);
110:): generic_hash_code(result, s);
111:): };
1.16 paf 112: uint String::hash_code() const {
1.7 paf 113: uint result=0;
1.172.2.21.2. (paf 114:): CORD_iter5(body, 0, 0, CORD_batched_iter_fn_generic_hash_code, &result);
1.5 paf 115: return result;
116: }
117:
1.172.2.21.2. (paf 118:): const String& String::mid(size_t substr_start, size_t substr_end) const {
119:): String& result=*new String;
1.33 paf 120:
1.172.2.21.2. (paf 121:): substr_start=min(substr_start, size());
122:): substr_end=max(substr_start, substr_end);
123:): if(substr_start==substr_end)
124:): return result;
1.52 paf 125:
1.172.2.21.2. (paf 126:): // first: letters themselves
127:): result.body=CORD_substr(body, substr_start, substr_end-substr_start);
1.46 paf 128:
1.172.2.21.2. (paf 129:): // next: their langs
130:): result.fragments.append(fragments, substr_start, substr_end);
1.53 paf 131:
1.60 paf 132: // SAPI::log(pool(), "piece of '%s' from %d to %d is '%s'",
1.172.2.21.2. (paf 133:): //cstr(), substr_start, substr_end, result.cstr());
1.53 paf 134: return result;
1.54 paf 135: }
136:
1.172.2.21.2. (paf 137:): size_t String::pos(CORD substr,
138:): size_t this_offset, Untaint_lang lang) const {
139:): // first: letters themselves
140:): size_t substr_start=CORD_str(body, this_offset, substr);
141:): if(substr_start==CORD_NOT_FOUND)
142:): return NOT_FOUND;
143:):
144:): // next: check the lang when specified
145:):
146:): if(lang==UL_UNSPECIFIED) // ignore lang?
147:): return substr_start;
148:):
149:): // substr must be in one fragment, and fragments' lang must = lang
150:): size_t substr_end=substr_start+CORD_len(substr);
151:): size_t fragment_start=0;
152:): size_t fragment_end;
153:): for(Array_iterator<ArrayFragment::element_type> i(fragments); i.has_next(); fragment_start=fragment_end) {
154:): const Fragment& fragment=i.next();
155:): fragment_end=fragment_start+fragment.size;
156:):
157:): if(substr_start<fragment_start) // not reached fragments which may include 'result'?
158:): continue;
159:):
160:): if(substr_end>fragment_end) // end of substr OUT of current fragment?
161:): break;
162:):
163:): return fragment.lang==lang?substr_end:NOT_FOUND;
164:): }
165:):
166:): return NOT_FOUND;
1.58 paf 167: }
168:
1.172.2.21.2. (paf 169:): size_t String::pos(const String& substr,
170:): size_t this_offset, Untaint_lang lang) const {
171:): return pos(substr.body, this_offset, lang);
1.60 paf 172: }
173:
1.172.2.14 paf 174: void String::split(ArrayString& result,
1.172.2.21.2. (paf 175:): size_t& pos_after,
176:): const char* delim,
1.172.2.10 paf 177: Untaint_lang lang, int limit) {
1.125 paf 178: size_t self_size=size();
1.172.2.21.2. (paf 179:): if(size_t delim_size=strlen(delim)) {
1.60 paf 180: int pos_before;
181: // while we have 'delim'...
1.172.2.21.2. (paf 182:): for(; (pos_before=pos(delim, pos_after, lang))>=0 && limit; limit--) {
183:): result+=&mid(pos_after, pos_before);
1.60 paf 184: pos_after=pos_before+delim_size;
185: }
186: // last piece
1.124 paf 187: if(pos_after<self_size && limit) {
1.172.2.21.2. (paf 188:): result+=&mid(pos_after, self_size);
1.124 paf 189: pos_after=self_size;
1.60 paf 190: }
191: } else { // empty delim
1.172.2.21.2. (paf 192:): result+=this;
193:): pos_after+=self_size;
1.60 paf 194: }
195: }
196:
1.172.2.14 paf 197: void String::split(ArrayString& result,
1.172.2.21.2. (paf 198:): size_t& pos_after,
1.60 paf 199: const String& delim, Untaint_lang lang,
1.172.2.21.2. (paf 200:): int limit) const {
201:): if(delim) {
1.60 paf 202: int pos_before;
203: // while we have 'delim'...
204: for(; (pos_before=pos(delim, pos_after, lang))>=0 && limit; limit--) {
1.172.2.21.2. (paf 205:): result+=&mid(pos_after, pos_before);
1.60 paf 206: pos_after=pos_before+delim.size();
207: }
208: // last piece
209: if(pos_after<size() && limit) {
1.172.2.21.2. (paf 210:): result+=&mid(pos_after, size());
1.60 paf 211: pos_after=size();
212: }
213: } else { // empty delim
1.172.2.21.2. (paf 214:): result+=this;
215:): pos_after+=size();
1.60 paf 216: }
1.61 paf 217: }
218:
1.172.2.21.2. (paf 219:): static void regex_options(const String& options, int *result, bool& need_pre_post_match){
1.63 paf 220: struct Regex_option {
1.172.2.11 paf 221: const char* keyL;
222: const char* keyU;
1.63 paf 223: int clear, set;
224: int *result;
1.154 paf 225: bool *flag;
1.63 paf 226: } regex_option[]={
1.153 paf 227: {"i", "I", 0, PCRE_CASELESS, result}, // a=A
228: {"s", "S", 0, PCRE_DOTALL, result}, // \n\n$ [default]
229: {"x", "U", 0, PCRE_EXTENDED, result}, // whitespace in regex ignored
230: {"m", "M", PCRE_DOTALL, PCRE_MULTILINE, result}, // ^aaa\n$^bbb\n$
231: {"g", "G", 0, true, result+1}, // many rows
1.154 paf 232: {"'", 0, 0, 0, 0, &need_pre_post_match},
233: {0}
1.63 paf 234: };
1.171 paf 235: result[0]=PCRE_EXTRA | PCRE_DOTALL | PCRE_DOLLAR_ENDONLY;
1.63 paf 236: result[1]=0;
237:
238: if(options)
1.153 paf 239: for(Regex_option *o=regex_option; o->keyL; o++)
1.172.2.21.2. (paf 240:): if(options.pos(o->keyL)>=0
241:): || (o->keyU && options.pos(o->keyU)>=0)) {
1.154 paf 242: if(o->flag)
243: *o->flag=true;
244: else { // result
245: *o->result &= ~o->clear;
246: *o->result |= o->set;
247: }
1.63 paf 248: }
249: }
250:
1.172.2.21.2. (paf 251:): Table* String::match(Charset& source_charset,
1.172.2.4 paf 252: const String& regexp,
1.172.2.21.2. (paf 253:): const String& options,
1.172.2.4 paf 254: Row_action row_action, void *info,
1.172.2.20 paf 255: bool& just_matched) const {
1.172.2.21.2. (paf 256:): if(!regexp)
257:): throw Exception(Exception::undefined_type,
258:): Exception::undefined_source,
1.73 paf 259: "regexp is empty");
1.154 paf 260:
1.172.2.21.2. (paf 261:): const char* pattern=regexp.cstr();
1.172.2.11 paf 262: const char* errptr;
1.62 paf 263: int erroffset;
1.172.2.21.2. (paf 264:): bool need_pre_post_match=false;
1.154 paf 265: int option_bits[2]; regex_options(options, option_bits, need_pre_post_match);
1.172.2.20 paf 266: bool global=option_bits[1]!=0;
1.172.2.21.2. (paf 267:): pcre *code=pcre_compile(pattern, option_bits[0],
1.62 paf 268: &errptr, &erroffset,
1.172.2.1 paf 269: source_charset.pcre_tables);
1.62 paf 270:
1.67 paf 271: if(!code)
1.172.2.21.2. (paf 272:): throw Exception(Exception::undefined_type,
273:): ®exp.mid(erroffset, regexp.size()),
1.74 paf 274: "regular expression syntax error - %s", errptr);
1.62 paf 275:
1.172.2.20 paf 276: int subpatterns=pcre_info(code, 0, 0);
277: if(subpatterns<0) {
1.100 parser 278: pcre_free(code);
1.149 paf 279: throw Exception(0,
1.172.2.21.2. (paf 280:): ®exp,
1.76 paf 281: "pcre_info error (%d)",
1.172.2.20 paf 282: subpatterns);
1.63 paf 283: }
284:
1.172.2.21.2. (paf 285:): C subject=cstr();
1.172.2.4 paf 286: const int ovecsize=(1/*match*/+MAX_MATCH_GROUPS)*3;
1.155 paf 287: int ovector[ovecsize];
288:
289: // create table
1.172.2.21.2. (paf 290:): Table* table=new Table(string_match_table_template);
1.63 paf 291:
1.64 paf 292: int exec_option_bits=0;
1.154 paf 293: int prestart=0;
294: int poststart=0;
295: int postfinish=size();
1.63 paf 296: while(true) {
297: int exec_substrings=pcre_exec(code, 0,
1.172.2.21.2. (paf 298:): subject, subject.size, prestart,
1.64 paf 299: exec_option_bits, ovector, ovecsize);
1.63 paf 300:
301: if(exec_substrings==PCRE_ERROR_NOMATCH) {
1.100 parser 302: pcre_free(code);
1.172.2.21.2. (paf 303:): row_action(table, 0/*last time, no raw*/, 0, 0, poststart, postfinish, info);
1.172.2.20 paf 304: if(global || subpatterns)
305: return table; // global or with subpatterns=true+result
306: else {
1.172.2.21.2. (paf 307:): just_matched=false; return 0; // not global=no result
1.172.2.20 paf 308: }
1.63 paf 309: }
310:
311: if(exec_substrings<0) {
1.100 parser 312: pcre_free(code);
1.172.2.21.2. (paf 313:): throw Exception(Exception::undefined_type,
314:): ®exp,
1.76 paf 315: "regular expression execute error (%d)",
1.63 paf 316: exec_substrings);
317: }
318:
1.154 paf 319: int prefinish=ovector[0];
320: poststart=ovector[1];
1.172.2.21.2. (paf 321:): ArrayString* row=new ArrayString;
1.172.2.4 paf 322: if(need_pre_post_match) {
1.172.2.21.2. (paf 323:): *row+=&mid(0, prefinish); // .prematch column value
324:): *row+=&mid(prefinish, poststart); // .match
325:): *row+=&mid(poststart, postfinish); // .postmatch
1.172.2.4 paf 326: } else {
1.172.2.21.2. (paf 327:): *row+=0; // .prematch column value
328:): *row+=0; // .match
329:): *row+=0; // .postmatch
1.172.2.4 paf 330: }
1.63 paf 331:
332: for(int i=1; i<exec_substrings; i++) {
1.69 paf 333: // -1:-1 case handled peacefully by mid() itself
1.172.2.21.2. (paf 334:): *row+=&mid(ovector[i*2+0], ovector[i*2+1]); // .i column value
1.63 paf 335: }
336:
1.172.2.20 paf 337: row_action(table, row, prestart, prefinish, poststart, postfinish, info);
1.63 paf 338:
1.172.2.20 paf 339: if(!global || prestart==poststart) { // not global | going to hang
1.100 parser 340: pcre_free(code);
1.172.2.21.2. (paf 341:): row_action(table, 0/*last time, no row*/, 0, 0, poststart, postfinish, info);
1.172.2.20 paf 342: return table;
1.63 paf 343: }
1.154 paf 344: prestart=poststart;
1.63 paf 345:
346: /*
347: if(option_bits[0] & PCRE_MULTILINE)
1.64 paf 348: exec_option_bits|=PCRE_NOTBOL; // start of subject+startoffset not BOL
1.63 paf 349: */
350: }
1.82 parser 351: }
352:
1.172.2.21.2. (paf 353:): String& String::change_case(Charset& source_charset, Change_case_kind kind) {
354:): String& result=*new String();
1.172.2.4 paf 355:
1.172.2.1 paf 356: const unsigned char *tables=source_charset.pcre_tables;
1.82 parser 357:
358: const unsigned char *a;
359: const unsigned char *b;
360: switch(kind) {
361: case CC_UPPER:
362: a=tables+lcc_offset;
363: b=tables+fcc_offset;
364: break;
365: case CC_LOWER:
366: a=tables+lcc_offset;
367: b=0;
368: break;
369: default:
1.172.2.21.2. (paf 370:): throw Exception(Exception::undefined_type,
371:): this,
1.82 parser 372: "unknown change case kind #%d",
373: static_cast<int>(kind)); // never
374: a=b=0; // calm, compiler
375: break; // never
376: }
377:
1.172.2.21.2. (paf 378:): C new_cstr=cstr();
379:): const char *end=new_cstr+new_cstr.size;
380:): char *dest=new_cstr;
381:): for(const char* current=new_cstr; current<end; current++) {
382:): unsigned char c=a[(unsigned char)*current];
383:): if(b)
384:): c=b[c];
1.82 parser 385:
1.172.2.21.2. (paf 386:): *dest++=(char)c;
387:): }
388:): result.body=new_cstr;
389:): result.fragments.append(fragments, 0, fragments.count());
1.89 parser 390:
1.101 parser 391: return result;
392: }
393:
1.172.2.21.2. (paf 394:): const String& String::replace(const Dictionary& dict) const {
395:): String& result=*new String();
396:): C old_cstr=cstr();
397:): const char* current=old_cstr;
398:): size_t old_pos=0;
399:):
400:): char *new_cstr=new char[(size_t)ceil(old_cstr.size*dict.max_ratio())];
401:): char *dest=new_cstr;
402:): size_t remaining_size=old_cstr.size;
403:): do {
404:): if(Table::element_type row=dict.first_that_starts(current, remaining_size)) {
405:): { // prematch
406:): size_t now_pos=current-old_cstr;
407:): if(now_pos!=old_pos) {
408:): result.fragments.append(fragments, old_pos, now_pos);
409:): old_pos=now_pos;
410:): }
1.101 parser 411: }
412:
1.172.2.21.2. (paf 413:): const String* a=row->get(0); size_t a_size=a->size();
414:): // skip 'a' in 'current', in fragment lang index && reduce work size
415:): current+=a_size; old_pos+=a_size; remaining_size-=a_size;
416:):
417:): if(row->count()>1) { // are there any b?
418:): const String* b=row->get(1); size_t b_size=b->size();
419:): if(b_size) {
420:): // write 'b' to 'dest' && skip 'b' in 'dest'
421:): b->store_to(dest, String::UL_AS_IS); dest+=b_size;
1.170 paf 422:
1.172.2.21.2. (paf 423:): // append match fragments
424:): result.fragments.append(b->fragments, 0, b->fragments.count());
425:): }
426:): }
427:): } else {
428:): // write a char to b && reduce work size
429:): *dest++=*current++; remaining_size--;
430:): }
431:): } while(remaining_size);
1.156 paf 432:
1.172.2.21.2. (paf 433:): { // postmatch
434:): size_t now_pos=current-old_cstr;
435:): if(now_pos!=old_pos) // have something at end?
436:): result.fragments.append(fragments, old_pos, now_pos-old_pos);
437:): }
1.156 paf 438:
1.172.2.21.2. (paf 439:): result.body=new_cstr;
1.89 parser 440: return result;
441: }
442:
1.172.2.10 paf 443: double String::as_double() {
1.89 parser 444: double result;
1.172.2.4 paf 445: char buf[MAX_STRING];
446: if(size()>MAX_STRING-1)
447: throw Exception("number.format",
1.172.2.21.2. (paf 448:): this,
1.172.2.4 paf 449: "invalid number too long a string (%u>%u)", size(), MAX_STRING-1);
1.172.2.5 paf 450: char *eol=store_to(buf, String::UL_AS_IS); *eol=0;
1.172.2.11 paf 451: const char* cstr=buf;
1.172.2.4 paf 452:
1.161 paf 453: while(*cstr && isspace(*cstr))
454: cstr++;
455: if(!*cstr)
1.162 paf 456: return 0;
1.161 paf 457:
1.102 parser 458: char *error_pos;
1.89 parser 459: // 0xABC
1.99 parser 460: if(cstr[0]=='0')
461: if(cstr[1]=='x' || cstr[1]=='X')
462: result=(double)(unsigned long)strtol(cstr, &error_pos, 0);
463: else
1.102 parser 464: result=(double)strtod(cstr+1/*skip leading 0*/, &error_pos);
1.89 parser 465: else
1.99 parser 466: result=(double)strtod(cstr, &error_pos);
1.89 parser 467:
1.159 paf 468: while(char c=*error_pos++)
469: if(!isspace(c))
470: throw Exception("number.format",
1.172.2.21.2. (paf 471:): this,
1.159 paf 472: "invalid number (double)");
1.89 parser 473:
474: return result;
475: }
1.172.2.10 paf 476: int String::as_int() {
1.89 parser 477: int result;
1.172.2.4 paf 478: char buf[MAX_STRING];
479: if(size()>MAX_STRING-1)
480: throw Exception("number.format",
1.172.2.21.2. (paf 481:): this,
1.172.2.4 paf 482: "invalid number too long a string (%u>%u)", size(), MAX_STRING-1);
1.172.2.5 paf 483: char *eol=store_to(buf, String::UL_AS_IS); *eol=0;
1.172.2.11 paf 484: const char* cstr=buf;
1.172.2.4 paf 485:
1.161 paf 486: while(*cstr && isspace(*cstr))
487: cstr++;
488: if(!*cstr)
1.162 paf 489: return 0;
1.161 paf 490:
1.102 parser 491: char *error_pos;
1.89 parser 492: // 0xABC
1.99 parser 493: if(cstr[0]=='0')
494: if(cstr[1]=='x' || cstr[1]=='X')
495: result=(int)(unsigned long)strtol(cstr, &error_pos, 0);
496: else
1.102 parser 497: result=(int)strtol(cstr+1/*skip leading 0*/, &error_pos, 0);
1.89 parser 498: else
499: result=(int)strtol(cstr, &error_pos, 0);
500:
1.159 paf 501: while(char c=*error_pos++)
502: if(!isspace(c))
503: throw Exception("number.format",
1.172.2.21.2. (paf 504:): this,
1.159 paf 505: "invalid number (int)");
1.82 parser 506:
507: return result;
1.61 paf 508: }
1.113 parser 509:
1.172.2.4 paf 510: inline void uint2uchars(uint word, uchar *bytes) {
511: bytes[0]=word&0xFF;
512: bytes[1]=(word>>8)&0xFF;
513: bytes[2]=(word>>16)&0xFF;
514: bytes[3]=(word>>24)&0xFF;
515: }
516: inline uint uchars2uint(uchar *bytes) {
517: return bytes[3]<<24
518: | bytes[2]<<16
519: | bytes[1]<<8
520: | bytes[0];
521: }
522:
1.172.2.21.2. (paf 523:): void String::serializesize_t prolog_size, char *& buf, size_t& buf_size) const {
1.113 parser 524: buf_size=
525: prolog_size
1.172.2.18 paf 526: +fused*(sizeof(String_UL)+sizeof(size_t))
1.113 parser 527: +size();
1.172.2.21.2. (paf 528:): buf=new char[buf_size];
1.172.2.4 paf 529: char *cur=buf+prolog_size;
1.113 parser 530:
1.172.2.4 paf 531: STRING_FOREACH_FRAGMENT(
1.123 paf 532: // lang
1.172.2.4 paf 533: memcpy(cur, &fragment->lang, sizeof(fragment->lang));
534: cur+=sizeof(fragment->lang);
1.123 paf 535: // size
1.172.2.4 paf 536: // bug on some sparc platform [you can't work with integers on odd pointers]
537: // forces us to use byte array instead
538: uchar bytes[4];
539: uint2uchars(fragment->size, bytes);
540: memcpy(cur, &bytes, sizeof(bytes)); cur+=sizeof(bytes);
1.123 paf 541: // bytes
1.172.2.4 paf 542: memcpy(cur, fragment->ptr, fragment->size);
543: cur+=fragment->size;
1.123 paf 544: );
1.113 parser 545: }
1.172.2.11 paf 546: bool String::deserialize(size_t prolog_size, void *buf, size_t buf_size, const char* file) {
1.135 paf 547: if(buf_size<=prolog_size)
1.148 paf 548: return false;
1.135 paf 549:
1.126 paf 550: char *cur=(char *)buf+prolog_size;
1.113 parser 551: buf_size-=prolog_size;
552:
553: while(buf_size) {
1.172.2.18 paf 554: if(sizeof(String_UL)+sizeof(size_t)>buf_size) // lang+size
1.148 paf 555: return false;
556:
1.172.2.6 paf 557: String_UL lang=*(String_UL *)(cur);
1.172.2.4 paf 558: size_t size=uchars2uint((uchar *)cur);
1.128 paf 559:
1.172.2.18 paf 560: size_t piece_size=sizeof(String_UL)+sizeof(size_t)+size;
1.148 paf 561: if(piece_size>buf_size) // buffer overrun, can be on incomplete cache files
562: return false;
563:
1.172.2.18 paf 564: const char* ptr=(const char*)(cur+sizeof(String_UL)+sizeof(size_t));
1.126 paf 565: APPEND(ptr, size, lang, file, 0);
1.113 parser 566:
567: cur+=piece_size;
568: buf_size-=piece_size;
569: }
1.148 paf 570: return true;
1.113 parser 571: }
E-mail: