varstring.c

00001 /* File:      varstring.c
00002 ** Author(s): kifer
00003 ** Contact:   xsb-contact@cs.sunysb.edu
00004 ** 
00005 ** Copyright (C) The Research Foundation of SUNY, 1999
00006 ** 
00007 ** XSB is free software; you can redistribute it and/or modify it under the
00008 ** terms of the GNU Library General Public License as published by the Free
00009 ** Software Foundation; either version 2 of the License, or (at your option)
00010 ** any later version.
00011 ** 
00012 ** XSB is distributed in the hope that it will be useful, but WITHOUT ANY
00013 ** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 ** FOR A PARTICULAR PURPOSE.  See the GNU Library General Public License for
00015 ** more details.
00016 ** 
00017 ** You should have received a copy of the GNU Library General Public License
00018 ** along with XSB; if not, write to the Free Software Foundation,
00019 ** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 **
00021 ** $Id: varstring.c,v 1.19 2005/12/31 23:16:03 tswift Exp $
00022 ** 
00023 */
00024 
00025 
00026 /*
00027   Usage:
00028 
00029   XSB_StrDefine(foo);  // Declare foo as a variable length string
00030   XSB_StrDefine(boo);  // Declare boo as a variable length string
00031   VarString *goo;    // Declare a pointer to a varstring.
00032 
00033   foo.op->set(&foo,"abc");        // or XSB_StrSet(&foo, "abc");
00034   foo.op->append(&foo,"123");     // or XSB_StrAppend(&foo, "123");
00035   // shrink foo, set the increment to 5
00036   foo.op->shrink(&foo,5);         // or XSB_StrShrink(&foo,5);
00037   foo.op->prepend(&foo,"098");    // or XSB_StrPrepend(&foo,"098");
00038 
00039   boo.op->prepend("pasddsf");
00040 
00041   goo = &boo;
00042   goo->op->strcmp(goo, "jdshdd"); // or XSB_StrStrCmp(goo,"jdshdd");
00043 
00044   if (foo.length > 0)
00045      printf("%s   %d\n", foo.string, foo.length);
00046 
00047   printf("boo: %s\n", goo->string);
00048 
00049 */
00050 
00051 
00052 /* To test: define the string below and compile: cc varstring.c; a.out */
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 /* add char to the end of string, don't null-terminate */
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); // never released!
00123   varstring_init(*vstr);
00124 }
00125 
00126 
00127 /* initialize a var string. This is the only function that isn't a member of
00128    the data structure, because somebody must assign functions to the function
00129    pointers inside struct varstr */
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 /* change the increment and also shrink the allocated space to the minimum */
00155 static inline void vs_shrink(VarString *vstr, int increment)
00156 {
00157   if (vstr->string == NULL)
00158     vs_init(vstr,increment);
00159   else { /* already initialized */
00160     vstr->increment = increment;
00161     /* make sure we don't clobber existing stuff */
00162     vs_adjust_size(vstr, vstr->length+1);
00163   }
00164 }
00165 
00166 
00167 /* ensure that the VarString has room for minsize bytes */
00168 /* dsw changed, so it will never shrink the buffer */
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); /* conditional init */
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   //  vs_adjust_size(vstr, newlength+1); %% dsw changed to avoid too much realloc
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   /* conditional init */
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); /* conditional init */
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 /* destruction is necessary for automatic VarString's,
00277    or else there will be a memory leak */
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     //    xsb_bug("Attempt to deallocate uninitialized variable-length string");
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 /* append block of chars, don't NULL-terminate */
00302 static void vs_appendblk(VarString *vstr, char *blk, int blk_size)
00303 {
00304   int newlength;
00305 
00306   vs_init(vstr,0); /* conditional init */
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 /* append block of chars */
00328 static void vs_prependblk(VarString *vstr, char *blk, int blk_size)
00329 {
00330   int newlength;
00331 
00332   vs_init(vstr,0); /* conditional init */
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); /* conditional init */
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 /* Adjust size to the next multiple of the increment after minsize;
00370    This can enlarge as well as shrink a VarString. 
00371    The caller must make sure that the existing data isn't clobbered by
00372    shrinking. */
00373 static void vs_adjust_size(VarString *vstr, int minsize)
00374 {
00375   int newsize;
00376 
00377   vs_init(vstr,0); /* conditional init */
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

Generated on Wed Jul 26 13:30:43 2006 for XSB by  doxygen 1.4.5