00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #undef DEBUG_VARSTRING
00054
00055
00056 #include "xsb_config.h"
00057
00058 #include <stdio.h>
00059 #include <stdlib.h>
00060 #include <errno.h>
00061 #include <sys/types.h>
00062 #include <string.h>
00063
00064 #include "wind2unix.h"
00065
00066 #include "auxlry.h"
00067 #include "cell_xsb.h"
00068 #include "memory_xsb.h"
00069 #ifndef DEBUG_VARSTRING
00070 #include "error_xsb.h"
00071 #endif
00072
00073 #include "varstring_xsb.h"
00074
00075
00076 #define DEFAULT_VARSTR_INCREMENT 128
00077 #define NEWLENGTH(vstr,additional_size) \
00078 vstr->length + additional_size +1
00079
00080
00081 static void vs_init(VarString*, int);
00082 static void vs_set(VarString*, char*);
00083 static void vs_setv(VarString*, VarString*);
00084 static void vs_append(VarString*, char*);
00085 static void vs_prepend(VarString*, char*);
00086 static inline void vs_appendv(VarString*, VarString*);
00087 static inline void vs_appendc(VarString*, char);
00088 static inline void vs_prependv(VarString*, VarString*);
00089 static inline int vs_compare(VarString*, VarString*);
00090 static inline int vs_strcmp(VarString*, char*);
00091 static inline void vs_destroy(VarString*);
00092 static inline void vs_shrink(VarString*, int);
00093 static inline void vs_ensure_size(VarString*, int);
00094
00095
00096 static void vs_appendblk(VarString *vstr,char*,int);
00097 static void vs_prependblk(VarString *vstr,char*,int);
00098 static void vs_adjust_size(VarString *vstr, int add_size);
00099 static inline void vs_null_terminate(VarString *vstr);
00100
00101 DllExport struct varstr_ops VarStrOps = {vs_set,vs_setv,
00102 vs_append,vs_prepend,
00103 vs_appendv,vs_appendc,vs_prependv,
00104 vs_compare,vs_strcmp,
00105 vs_appendblk,vs_prependblk,
00106 vs_null_terminate,
00107 vs_ensure_size,
00108 vs_shrink,vs_destroy};
00109
00110
00111 DllExport void call_conv varstring_init(VarString *vstr)
00112 {
00113 vstr->size = 0;
00114 vstr->increment = 0;
00115 vstr->length =0;
00116 vstr->string = NULL;
00117 vstr->op = &VarStrOps;
00118 }
00119
00120 DllExport void call_conv varstring_create(VarString **vstr)
00121 {
00122 *vstr = (VarString *) mem_alloc(sizeof(VarString),OTHER_SPACE);
00123 varstring_init(*vstr);
00124 }
00125
00126
00127
00128
00129
00130 static void vs_init(VarString *vstr, int increment)
00131 {
00132 if (vstr->string != NULL)
00133 return;
00134
00135 if (increment < 1)
00136 increment = DEFAULT_VARSTR_INCREMENT;
00137
00138 if (NULL == (vstr->string = (char *)mem_calloc(1, increment,OTHER_SPACE))) {
00139 #ifdef DEBUG_VARSTRING
00140 fprintf(stderr, "Cannot allocate memory for a variable-length string\n");
00141 return;
00142 #else
00143 xsb_abort("Cannot allocate memory for a variable-length string");
00144 #endif
00145 }
00146
00147 vstr->increment = increment;
00148 vstr->size = increment;
00149 vstr->length = 0;
00150 vstr->string[0] = '\0';
00151 }
00152
00153
00154
00155 static inline void vs_shrink(VarString *vstr, int increment)
00156 {
00157 if (vstr->string == NULL)
00158 vs_init(vstr,increment);
00159 else {
00160 vstr->increment = increment;
00161
00162 vs_adjust_size(vstr, vstr->length+1);
00163 }
00164 }
00165
00166
00167
00168
00169 static inline void vs_ensure_size(VarString *vstr, int minsize)
00170 {
00171 vs_init(vstr,0);
00172
00173 if (minsize > vstr->size) vs_adjust_size(vstr, minsize+1);
00174 }
00175
00176
00177 static void vs_set(VarString *vstr, char *str)
00178 {
00179 int newlength;
00180
00181 vs_init(vstr,0);
00182
00183 if (str == NULL) {
00184 #ifdef DEBUG_VARSTRING
00185 fprintf(stderr, "Assigning a NULL pointer to a variable-length string\n");
00186 return;
00187 #else
00188 xsb_bug("Assigning a NULL pointer to a variable-length string");
00189 #endif
00190 }
00191
00192 newlength = strlen(str);
00193
00194
00195 vs_ensure_size(vstr, newlength+1);
00196
00197 strcpy(vstr->string, str);
00198 vstr->length=newlength;
00199 }
00200
00201 static void vs_setv(VarString *vstr, VarString *vstr1)
00202 {
00203 vs_set(vstr, vstr1->string);
00204 }
00205
00206 static void vs_append(VarString *vstr, char *str)
00207 {
00208 if (str == NULL) {
00209 #ifdef DEBUG_VARSTRING
00210 fprintf(stderr, "Appending a NULL string\n");
00211 return;
00212 #else
00213 xsb_bug("Appending a NULL string");
00214 #endif
00215 }
00216 vs_appendblk(vstr, str, strlen(str));
00217 vs_null_terminate(vstr);
00218 }
00219
00220 static inline void vs_appendc(VarString *vstr, char code) {
00221 if (vstr->size < vstr->length+1)
00222 vs_adjust_size(vstr,vstr->length+1);
00223 *(vstr->string+vstr->length) = code;
00224 vstr->length++;
00225 *(vstr->string+vstr->length) = '\0';
00226 }
00227
00228 static void vs_prepend(VarString *vstr, char *str)
00229 {
00230 if (str == NULL) {
00231 #ifdef DEBUG_VARSTRING
00232 fprintf(stderr, "Appending a NULL string\n");
00233 return;
00234 #else
00235 xsb_bug("Appending a NULL string");
00236 #endif
00237 }
00238 vs_prependblk(vstr, str, strlen(str));
00239 }
00240
00241 static inline void vs_appendv(VarString *vstr, VarString *vstr1)
00242 {
00243 vs_append(vstr, vstr1->string);
00244 }
00245
00246 static inline void vs_prependv(VarString *vstr, VarString *vstr1)
00247 {
00248 vs_prepend(vstr, vstr1->string);
00249 }
00250
00251 static inline int vs_compare(VarString *vstr, VarString *vstr1)
00252 {
00253
00254 vs_init(vstr,0);
00255 vs_init(vstr1,0);
00256
00257 return strcmp(vstr->string, vstr1->string);
00258 }
00259
00260 static inline int vs_strcmp(VarString *vstr, char *str)
00261 {
00262 vs_init(vstr,0);
00263
00264 if (str == NULL) {
00265 #ifdef DEBUG_VARSTRING
00266 fprintf(stderr, "Comparing string with a NULL pointer\n");
00267 return 0;
00268 #else
00269 xsb_bug("Comparing string with a NULL pointer");
00270 #endif
00271 }
00272
00273 return strcmp(vstr->string, str);
00274 }
00275
00276
00277
00278 static inline void vs_destroy(VarString *vstr)
00279 {
00280 if (vstr->string == NULL) {
00281 #ifdef DEBUG_VARSTRING
00282 fprintf(stderr,
00283 "Attempt to deallocate uninitialized variable-length string\n");
00284 return;
00285 #else
00286 return;
00287
00288 #endif
00289 }
00290 #ifdef DEBUG_VARSTRING
00291 fprintf(stderr,
00292 "Deallocating a variable-length string\n");
00293 #endif
00294 mem_dealloc(vstr->string,vstr->size,OTHER_SPACE);
00295 vstr->string = NULL;
00296 vstr->size = 0;
00297 vstr->length = 0;
00298 vstr->increment = 0;
00299 }
00300
00301
00302 static void vs_appendblk(VarString *vstr, char *blk, int blk_size)
00303 {
00304 int newlength;
00305
00306 vs_init(vstr,0);
00307
00308 if (blk == NULL) {
00309 #ifdef DEBUG_VARSTRING
00310 fprintf(stderr, "Appending a NULL string\n");
00311 return;
00312 #else
00313 xsb_bug("Appending a NULL string");
00314 #endif
00315 }
00316
00317 newlength = NEWLENGTH(vstr,blk_size);
00318
00319 if (newlength > vstr->size)
00320 vs_adjust_size(vstr, newlength);
00321
00322 strncpy(vstr->string+vstr->length, blk, blk_size);
00323 vstr->length=vstr->length + blk_size;
00324 }
00325
00326
00327
00328 static void vs_prependblk(VarString *vstr, char *blk, int blk_size)
00329 {
00330 int newlength;
00331
00332 vs_init(vstr,0);
00333
00334 if (blk == NULL) {
00335 #ifdef DEBUG_VARSTRING
00336 fprintf(stderr, "Prepending a NULL string\n");
00337 return;
00338 #else
00339 xsb_bug("Prepending a NULL string");
00340 #endif
00341 }
00342
00343 newlength = NEWLENGTH(vstr,blk_size);
00344
00345 if (newlength > vstr->size)
00346 vs_adjust_size(vstr, newlength);
00347
00348 memmove(vstr->string+blk_size, vstr->string, vstr->length+1);
00349 strncpy(vstr->string, blk, blk_size);
00350 vstr->length=vstr->length + blk_size;
00351 }
00352
00353
00354 static inline void vs_null_terminate(VarString *vstr)
00355 {
00356 int newlength;
00357
00358 vs_init(vstr,0);
00359
00360 newlength = NEWLENGTH(vstr,0);
00361
00362 if (newlength > vstr->size)
00363 vs_adjust_size(vstr, newlength);
00364
00365 vstr->string[vstr->length] = '\0';
00366 }
00367
00368
00369
00370
00371
00372
00373 static void vs_adjust_size(VarString *vstr, int minsize)
00374 {
00375 int newsize;
00376
00377 vs_init(vstr,0);
00378
00379 newsize = (minsize/vstr->increment +1) * (vstr->increment);
00380
00381 if (NULL == (vstr->string = (char *)mem_realloc_nocheck(vstr->string, vstr->size,
00382 newsize,OTHER_SPACE))) {
00383 #ifdef DEBUG_VARSTRING
00384 fprintf(stderr, "No room to expand a variable-length string\n");
00385 return;
00386 #else
00387 vstr->size = 0;
00388 vstr->length = 0;
00389 xsb_memory_error("memory","No room to expand a variable-length string");
00390 #endif
00391 }
00392
00393 #ifdef DEBUG_VARSTRING
00394 if (newsize > vstr->size)
00395 fprintf(stderr, "Expanding a VarString from %d to %d\n",
00396 vstr->size, newsize);
00397 else if (newsize < vstr->size)
00398 fprintf(stderr, "Shrinking a VarString from %d to %d\n",
00399 vstr->size, newsize);
00400 #endif
00401
00402 vstr->size = newsize;
00403 }
00404
00405
00406
00407 #ifdef DEBUG_VARSTRING
00408
00409 int main (int argc, char** argv)
00410 {
00411 XSB_StrDefine(foo);
00412 XSB_StrDefine(boo);
00413 XSB_StrDefine(goo);
00414 VarString *loo;
00415
00416 XSB_StrSet(&foo, "abc");
00417 printf("foo1: %s %d/%d\n", foo.string, foo.length, foo.size);
00418 foo.op->append(&foo, "123");
00419 printf("foo2: %s %d/%d\n", foo.string, foo.length, foo.size);
00420 foo.op->prepend(&foo, "098");
00421 printf("foo3: %s %d/%d\n", foo.string, foo.length, foo.size);
00422
00423 boo.op->prepend(&boo, "booooooo");
00424 printf("boo: %s %d/%d\n", boo.string, boo.length, boo.size);
00425
00426 boo.op->shrink(&boo, 3);
00427 boo.op->appendv(&boo, &foo);
00428
00429 loo = &boo;
00430 printf("boo2: %s %d/%d\n", loo->string, boo.length, boo.size);
00431
00432 foo.op->shrink(&foo,60);
00433 if (foo.length > 0)
00434 printf("foo4: %s %d/%d\n", foo.string, foo.length, foo.size);
00435
00436 boo.op->set(&boo,"123");
00437 XSB_StrAppend(loo,"---");
00438 printf("boo3: %s %d/%d\n", loo->string, boo.length, boo.size);
00439
00440 boo.op->append(&boo,"4567");
00441 printf("boo4: %s %d/%d\n", loo->string, boo.length, boo.size);
00442
00443 printf("initialized: boo=%p foo=%p goo=%p\n",
00444 boo.string, foo.string, goo.string);
00445
00446 XSB_StrSetV(loo, &foo);
00447 printf("boo5: %s %d/%d\n", loo->string, boo.length, boo.size);
00448
00449 XSB_StrEnsureSize(loo, 1000);
00450
00451 XSB_StrAppendBlk(loo,NULL,5);
00452 XSB_StrAppend(loo,NULL);
00453
00454 XSB_StrDestroy(&foo);
00455 XSB_StrDestroy(loo);
00456 goo.op->destroy(&goo);
00457
00458 }
00459
00460 #endif