Annotation of parser3/src/main/pa_string.C, revision 1.21
1.4 paf 1: /*
1.21 ! paf 2: $Id: pa_string.C,v 1.20 2001/02/13 10:09:53 paf Exp $
1.4 paf 3: */
4:
1.1 paf 5: #include <string.h>
6:
1.13 paf 7: #include "pa_pool.h"
1.12 paf 8: #include "pa_string.h"
1.5 paf 9: #include "pa_hash.h"
1.1 paf 10:
1.18 paf 11: // String
12:
1.15 paf 13: String::String(Pool& apool) :
1.17 paf 14: Pooled(apool) {
1.2 paf 15: head.count=curr_chunk_rows=CR_PREALLOCATED_COUNT;
1.5 paf 16: append_here=head.rows;
1.2 paf 17: head.preallocated_link=0;
1.5 paf 18: link_row=&head.rows[curr_chunk_rows];
1.8 paf 19: fused_rows=fsize=0;
1.1 paf 20: }
21:
22: void String::expand() {
1.8 paf 23: curr_chunk_rows+=curr_chunk_rows*CR_GROW_PERCENT/100;
1.2 paf 24: Chunk *chunk=static_cast<Chunk *>(
1.15 paf 25: pool.malloc(sizeof(int)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *)));
1.2 paf 26: chunk->count=curr_chunk_rows;
27: link_row->link=chunk;
1.5 paf 28: append_here=chunk->rows;
29: link_row=&chunk->rows[curr_chunk_rows];
1.8 paf 30: link_row->link=0;
1.1 paf 31: }
32:
1.16 paf 33: String::String(const String& src) :
1.17 paf 34: Pooled(src.pool) {
1.8 paf 35: head.count=CR_PREALLOCATED_COUNT;
36:
37: int src_used_rows=src.used_rows();
38: if(src_used_rows<=head.count) {
1.10 paf 39: // all new rows fit into preallocated area
1.8 paf 40: curr_chunk_rows=head.count;
41: memcpy(head.rows, src.head.rows, sizeof(Chunk::Row)*src_used_rows);
42: append_here=&head.rows[src_used_rows];
43: link_row=&head.rows[curr_chunk_rows];
44: } else {
45: // warning:
1.10 paf 46: // heavily relies on the fact
47: // "preallocated area is the same for all strings"
1.8 paf 48: //
49: // info:
50: // allocating only enough mem to fit src string rows
51: // next append would allocate a new chunk
52: //
53: // new rows don't fit into preallocated area: splitting into two chunks
54: // preallocated chunk src to constructing head
55: memcpy(head.rows, src.head.rows, sizeof(Chunk::Row)*head.count);
56: // remaining rows into new_chunk
57: curr_chunk_rows=src_used_rows-head.count;
58: Chunk *new_chunk=static_cast<Chunk *>(
1.15 paf 59: pool.malloc(sizeof(int)+sizeof(Chunk::Row)*curr_chunk_rows+sizeof(Chunk *)));
1.8 paf 60: new_chunk->count=curr_chunk_rows;
61: head.preallocated_link=new_chunk;
62: append_here=link_row=&new_chunk->rows[curr_chunk_rows];
63:
64: Chunk *old_chunk=src.head.preallocated_link;
65: Chunk::Row *new_rows=new_chunk->rows;
66: int rows_left_to_copy=curr_chunk_rows;
67: while(true) {
68: int old_count=old_chunk->count;
69: Chunk *next_chunk=old_chunk->rows[old_count].link;
70: if(next_chunk) {
71: // not last source chunk
72: // taking it all
73: memcpy(new_rows, old_chunk->rows, sizeof(Chunk::Row)*old_count);
74: new_rows+=old_count;
75: rows_left_to_copy-=old_count;
76:
77: old_chunk=next_chunk;
78: } else {
79: // the last source chunk
80: // taking only those rows of chunk that _left_to_copy
81: memcpy(new_rows, old_chunk->rows, sizeof(Chunk::Row)*rows_left_to_copy);
82: break;
83: }
84: }
1.5 paf 85: }
1.8 paf 86: link_row->link=0;
87: fused_rows=src_used_rows;
88: fsize=src.fsize;
1.5 paf 89: }
90:
1.13 paf 91: String& String::real_append(STRING_APPEND_PARAMS) {
1.9 paf 92: if(!src)
93: return *this;
94: int len=strlen(src);
95: if(!len)
96: return *this;
97:
1.1 paf 98: if(chunk_is_full())
99: expand();
100:
101: append_here->item.ptr=src;
1.9 paf 102: fsize+=append_here->item.size=len;
1.13 paf 103: #ifndef NO_STRING_ORIGIN
1.14 paf 104: append_here->item.origin.file=file;
105: append_here->item.origin.line=line;
1.13 paf 106: #endif
1.8 paf 107: append_here++; fused_rows++;
1.1 paf 108:
109: return *this;
110: }
111:
1.16 paf 112: char *String::cstr() const {
1.15 paf 113: char *result=static_cast<char *>(pool.malloc(size()+1));
1.1 paf 114:
115: char *copy_here=result;
1.16 paf 116: const Chunk *chunk=&head;
1.2 paf 117: do {
1.16 paf 118: const Chunk::Row *row=chunk->rows;
1.2 paf 119: for(int i=0; i<chunk->count; i++) {
1.1 paf 120: if(row==append_here)
121: goto break2;
122:
123: memcpy(copy_here, row->item.ptr, row->item.size);
124: copy_here+=row->item.size;
125: row++;
126: }
1.2 paf 127: chunk=row->link;
128: } while(chunk);
1.1 paf 129: break2:
130: *copy_here=0;
131: return result;
132: }
133:
1.16 paf 134: uint String::hash_code() const {
1.7 paf 135: uint result=0;
1.5 paf 136:
1.16 paf 137: const Chunk *chunk=&head;
1.5 paf 138: do {
1.16 paf 139: const Chunk::Row *row=chunk->rows;
1.5 paf 140: for(int i=0; i<chunk->count; i++) {
141: if(row==append_here)
142: goto break2;
143:
1.6 paf 144: result=Hash::generic_code(result, row->item.ptr, row->item.size);
1.5 paf 145: row++;
146: }
147: chunk=row->link;
148: } while(chunk);
149: break2:
150: return result;
151: }
152:
1.16 paf 153: bool String::operator == (const String& src) const {
1.8 paf 154: if(size() != src.size())
155: return false;
156:
1.16 paf 157: const Chunk *a_chunk=&head;
158: const Chunk *b_chunk=&src.head;
159: const Chunk::Row *a_row=a_chunk->rows;
160: const Chunk::Row *b_row=b_chunk->rows;
1.9 paf 161: int a_offset=0;
162: int b_offset=0;
163: Chunk::Row *a_end=append_here;
164: Chunk::Row *b_end=src.append_here;
1.11 paf 165: int a_countdown=a_chunk->count;
166: int b_countdown=b_chunk->count;
1.9 paf 167: bool a_break=false;
168: bool b_break=false;
169: while(true) {
170: int size_diff=
171: (a_row->item.size-a_offset)-
172: (b_row->item.size-b_offset);
173:
174: if(size_diff==0) { // a has same size as b
175: if(memcmp(a_row->item.ptr+a_offset, b_row->item.ptr+b_offset, a_row->item.size-a_offset)!=0)
176: return false;
1.11 paf 177: a_row++; a_countdown--; a_offset=0;
178: b_row++; b_countdown--; b_offset=0;
1.9 paf 179: } else if (size_diff>0) { // a longer
180: if(memcmp(a_row->item.ptr+a_offset, b_row->item.ptr+b_offset, b_row->item.size-b_offset)!=0)
181: return false;
182: a_offset+=b_row->item.size-b_offset;
1.11 paf 183: b_row++; b_countdown--; b_offset=0;
1.9 paf 184: } else { // b longer
185: if(memcmp(a_row->item.ptr+a_offset, b_row->item.ptr+b_offset, a_row->item.size-a_offset)!=0)
186: return false;
187: b_offset+=a_row->item.size-a_offset;
1.11 paf 188: a_row++; a_countdown--; a_offset=0;
1.9 paf 189: }
190:
191: a_break=a_row==a_end;
192: b_break=b_row==b_end;
193: if(a_break || b_break)
194: break;
195:
1.11 paf 196: if(!a_countdown) {
1.9 paf 197: a_chunk=a_row->link;
198: a_row=a_chunk->rows;
1.11 paf 199: a_countdown=a_chunk->count;
1.9 paf 200: }
1.11 paf 201: if(!b_countdown) {
1.9 paf 202: b_chunk=b_row->link;
203: b_row=b_chunk->rows;
1.11 paf 204: b_countdown=b_chunk->count;
1.9 paf 205: }
206: }
207: return a_break==b_break;
1.5 paf 208: }
1.18 paf 209:
210: String& String::append(const String_iterator& begin, const String_iterator& end) {
211: return z;
212: }
213:
1.21 ! paf 214: // Char_types
1.18 paf 215:
1.21 ! paf 216: Char_types::Char_types() {
! 217: memset(types, 0, sizeof(types));
1.18 paf 218: }
219:
220: // String_iterator
1.19 paf 221:
222: // home string
223: String& string;
224: // the row in which we are
225: Chunk::Row *read_here;
226: // position in that row's string fragment
227: int offset;
228: // when read_here reaches this row, move to the next chunk
229: Chunk::Row *link_row;
230:
231: bool feof;
232:
1.21 ! paf 233: String_iterator::String_iterator(String& astring) : string(astring) {
! 234: read_here=string.head.rows;
! 235: position=string.size()==0?0:read_here->item.ptr;
! 236: link_row=string.preallocated_link;
1.19 paf 237: }
238:
239: char String_iterator::operator() {
1.21 ! paf 240: return position?*position:0;
1.19 paf 241: }
242:
243: void String_iterator::skip() {
1.21 ! paf 244: if(!position)
1.19 paf 245: return;
246:
1.21 ! paf 247: if(++position==
! 248: read_here->item.ptr+
! 249: read_here->item.size) {
! 250:
! 251: // next row
1.19 paf 252: if(++read_here==string.append_here) {
253: feof=true;
254: return;
255: }
256: if(read_here==link_row) {
257: Chunk *chunk=link_row->link;
258: if(!chunk)
259: string.pool.exception().raise(
260: "String_iterator::skip() missed "
261: "read_here==string.append_here check");
262:
263: read_here=chunk->rows;
264: link_row=chunk->rows[chunk->count];
265: }
1.21 ! paf 266: position=read_here->item.ptr;
1.19 paf 267: }
268: }
269:
270: bool String_iterator::skip_to(char c) {
1.21 ! paf 271: if(!position)
! 272: return false;
! 273:
! 274: while(true) {
! 275: if(char *found=static_cast<char *>(
! 276: memchr(ptr, c, read_here->size-(position-read_here->ptr)))) {
! 277: position=found;
1.19 paf 278: return true;
1.20 paf 279: }
280:
1.21 ! paf 281: // next row
1.20 paf 282: if(++read_here==string.append_here) {
1.21 ! paf 283: position=0;
1.20 paf 284: return false;
285: }
286: if(read_here==link_row) {
287: Chunk *chunk=link_row->link;
288: if(!chunk)
289: string.pool.exception().raise(
290: "String_iterator::skip_to(char) missed "
291: "read_here==string.append_here check");
292:
293: read_here=chunk->rows;
294: link_row=chunk->rows[chunk->count];
295: }
1.21 ! paf 296: position=read_here->item.ptr;
1.20 paf 297: }
1.19 paf 298: }
299:
300: int String_iterator::skip_to(Char_type& types) {
1.21 ! paf 301: if(!position)
! 302: return false;
! 303:
! 304: while(true) {
! 305: int countdown=read_here->size-(position-read_here->ptr)));
! 306: for(; countdown--; position++)
! 307: if(int type=types.get(*position))
! 308: return type;
! 309:
! 310: // next row
! 311: if(++read_here==string.append_here) {
! 312: position=0;
! 313: return 0;
! 314: }
! 315: if(read_here==link_row) {
! 316: Chunk *chunk=link_row->link;
! 317: if(!chunk)
! 318: string.pool.exception().raise(
! 319: "String_iterator::skip_to(Char_type) missed "
! 320: "read_here==string.append_here check");
! 321:
! 322: read_here=chunk->rows;
! 323: link_row=chunk->rows[chunk->count];
! 324: }
! 325: position=read_here->item.ptr;
! 326: }
1.19 paf 327: }
E-mail: