languages/compiler/space.c

Go to the documentation of this file.
00001 
00002 #include <stdio.h>    /* for printf */
00003 #include <stdlib.h>   /* malloc, free */
00004 #include <string.h>   /* memmove */
00005 
00006 #include "header.h"
00007 
00008 #define HEAD 2*sizeof(int)
00009 #define EXTENDER 40
00010 
00011 
00012 /*  This modules provides a simple mechanism for arbitrary length writable
00013     strings, called 'blocks'. They are 'symbol *' items rather than 'char *'
00014     items however.
00015 
00016     The calls are:
00017 
00018         symbol * b = create_b(n);
00019             - create an empty block b with room for n symbols
00020         b = increase_capacity(b, n);
00021             - increase the capacity of block b by n symbols (b may change)
00022         b2 = copy_b(b)
00023             - copy block b into b2
00024         lose_b(b);
00025             - lose block b
00026         b = move_to_b(b, n, p);
00027             - set the data in b to be the n symbols at address p
00028         b = add_to_b(b, n, p);
00029             - add the n symbols at address p to the end of the data in b
00030         SIZE(b)
00031             - is the number of symbols in b
00032         For example:
00033 
00034         symbol * b = create_b(0);
00035         {   int i;
00036             char p[10];
00037             for (i = 0; i < 100; i++) {
00038                 sprintf(p, " %d", i);
00039                 add_s_to_b(b, p);
00040             }
00041         }
00042 
00043     and b contains " 0 1 2 ... 99" spaced out as symbols.
00044 */
00045 
00046 /*  For a block b, SIZE(b) is the number of symbols so far written into it,
00047     CAPACITY(b) the total number it can contain, so SIZE(b) <= CAPACITY(b).
00048     In fact blocks have 1 extra character over the promised capacity so
00049     they can be zero terminated by 'b[SIZE(b)] = 0;' without fear of
00050     overwriting.
00051 */
00052 
00053 extern symbol * create_b(int n) {
00054     symbol * p = (symbol *) (HEAD + (char *) MALLOC(HEAD + (n + 1) * sizeof(symbol)));
00055     CAPACITY(p) = n;
00056     SIZE(p) = 0;
00057     return p;
00058 }
00059 
00060 extern void report_b(FILE * out, symbol * p) {
00061     int i;
00062     for (i = 0; i < SIZE(p); i++) fprintf(out, "%c", p[i]);
00063 }
00064 
00065 extern void lose_b(symbol * p) {
00066     if (p == 0) return;
00067     FREE((char *) p - HEAD);
00068 }
00069 
00070 extern symbol * increase_capacity(symbol * p, int n) {
00071     symbol * q = create_b(CAPACITY(p) + n + EXTENDER);
00072     memmove(q, p, CAPACITY(p) * sizeof(symbol));
00073     SIZE(q) = SIZE(p);
00074     lose_b(p); return q;
00075 }
00076 
00077 extern symbol * move_to_b(symbol * p, int n, symbol * q) {
00078     int x = n - CAPACITY(p);
00079     if (x > 0) p = increase_capacity(p, x);
00080     memmove(p, q, n * sizeof(symbol)); SIZE(p) = n; return p;
00081 }
00082 
00083 extern symbol * add_to_b(symbol * p, int n, symbol * q) {
00084     int x = SIZE(p) + n - CAPACITY(p);
00085     if (x > 0) p = increase_capacity(p, x);
00086     memmove(p + SIZE(p), q, n * sizeof(symbol)); SIZE(p) += n; return p;
00087 }
00088 
00089 extern symbol * copy_b(symbol * p) {
00090     int n = SIZE(p);
00091     symbol * q = create_b(n);
00092     move_to_b(q, n, p);
00093     return q;
00094 }
00095 
00096 int space_count = 0;
00097 
00098 extern void * check_malloc(int n) {
00099     space_count++;
00100     return malloc(n);
00101 }
00102 
00103 extern void check_free(void * p) {
00104     space_count--;
00105     free(p);
00106 }
00107 
00108 /* To convert a block to a zero terminated string:  */
00109 
00110 extern char * b_to_s(symbol * p) {
00111     int n = SIZE(p);
00112     char * s = (char *)malloc(n + 1);
00113     {
00114         int i;
00115         for (i = 0; i < n; i++) {
00116             if (p[i] > 255) {
00117                 printf("In b_to_s, can't convert p[%d] to char because it's 0x%02x\n", i, (int)p[i]);
00118                 exit(1);
00119             }
00120             s[i] = (char)p[i];
00121         }
00122     }
00123     s[n] = 0;
00124     return s;
00125 }
00126 
00127 /* To add a zero terminated string to a block. If p = 0 the
00128    block is created. */
00129 
00130 extern symbol * add_s_to_b(symbol * p, const char * s) {
00131     int n = strlen(s);
00132     int k;
00133     if (p == 0) p = create_b(n);
00134     k = SIZE(p);
00135     {
00136         int x = k + n - CAPACITY(p);
00137         if (x > 0) p = increase_capacity(p, x);
00138     }
00139     {
00140         int i;
00141         for (i = 0; i < n; i++) p[i + k] = s[i];
00142     }
00143     SIZE(p) += n;
00144     return p;
00145 }
00146 
00147 /* The next section defines string handling capabilities in terms
00148    of the lower level block handling capabilities of space.c */
00149 /* -------------------------------------------------------------*/
00150 
00151 struct str {
00152     symbol * data;
00153 };
00154 
00155 /* Create a new string. */
00156 extern struct str * str_new() {
00157 
00158     struct str * output = (struct str *) malloc(sizeof(struct str));
00159     output->data = create_b(0);
00160     return output;
00161 }
00162 
00163 /* Delete a string. */
00164 extern void str_delete(struct str * str) {
00165 
00166     lose_b(str->data);
00167     free(str);
00168 }
00169 
00170 /* Append a str to this str. */
00171 extern void str_append(struct str * str, struct str * add) {
00172 
00173     symbol * q = add->data;
00174     str->data = add_to_b(str->data, SIZE(q), q);
00175 }
00176 
00177 /* Append a character to this str. */
00178 extern void str_append_ch(struct str * str, char add) {
00179 
00180     symbol q[1];
00181     q[0] = add;
00182     str->data = add_to_b(str->data, 1, q);
00183 }
00184 
00185 /* Append a low level block to a str. */
00186 extern void str_append_b(struct str * str, symbol * q) {
00187 
00188     str->data = add_to_b(str->data, SIZE(q), q);
00189 }
00190 
00191 /* Append a (char *, null teminated) string to a str. */
00192 extern void str_append_string(struct str * str, const char * s) {
00193 
00194     str->data = add_s_to_b(str->data, s);
00195 }
00196 
00197 /* Append an integer to a str. */
00198 extern void str_append_int(struct str * str, int i) {
00199 
00200     char s[30];
00201     sprintf(s, "%d", i);
00202     str_append_string(str, s);
00203 }
00204 
00205 /* Clear a string */
00206 extern void str_clear(struct str * str) {
00207 
00208     SIZE(str->data) = 0;
00209 }
00210 
00211 /* Set a string */
00212 extern void str_assign(struct str * str, char * s) {
00213 
00214     str_clear(str);
00215     str_append_string(str, s);
00216 }
00217 
00218 /* Copy a string. */
00219 extern struct str * str_copy(struct str * old) {
00220 
00221     struct str * newstr = str_new();
00222     str_append(newstr, old);
00223     return newstr;
00224 }
00225 
00226 /* Get the data stored in this str. */
00227 extern symbol * str_data(struct str * str) {
00228 
00229     return str->data;
00230 }
00231 
00232 /* Get the length of the str. */
00233 extern int str_len(struct str * str) {
00234 
00235     return SIZE(str->data);
00236 }
00237 
00238 extern int get_utf8(const symbol * p, int * slot) {
00239     int b0, b1;
00240     b0 = *p++;
00241     if (b0 < 0xC0) {   /* 1100 0000 */
00242         * slot = b0; return 1;
00243     }
00244     b1 = *p++;
00245     if (b0 < 0xE0) {   /* 1110 0000 */
00246         * slot = (b0 & 0x1F) << 6 | (b1 & 0x3F); return 2;
00247     }
00248     * slot = (b0 & 0xF) << 12 | (b1 & 0x3F) << 6 | (*p & 0x3F); return 3;
00249 }
00250 
00251 extern int put_utf8(int ch, symbol * p) {
00252     if (ch < 0x80) {
00253         p[0] = ch; return 1;
00254     }
00255     if (ch < 0x800) {
00256         p[0] = (ch >> 6) | 0xC0;
00257         p[1] = (ch & 0x3F) | 0x80; return 2;
00258     }
00259     p[0] = (ch >> 12) | 0xE0;
00260     p[1] = ((ch >> 6) & 0x3F) | 0x80;
00261     p[2] = (ch & 0x3F) | 0x80; return 3;
00262 }
00263 

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.