aboutsummaryrefslogtreecommitdiff
path: root/Source/DOH/Doh/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DOH/Doh/string.c')
-rw-r--r--Source/DOH/Doh/string.c487
1 files changed, 116 insertions, 371 deletions
diff --git a/Source/DOH/Doh/string.c b/Source/DOH/Doh/string.c
index 7bf62ed9e..5be745da5 100644
--- a/Source/DOH/Doh/string.c
+++ b/Source/DOH/Doh/string.c
@@ -30,6 +30,8 @@ typedef struct String {
int sp; /* Current position */
int lsp; /* Last returned position */
char *str; /* String data */
+ char pb[4]; /* Pushback data */
+ int pbi;
} String;
/* Forward references */
@@ -46,30 +48,32 @@ int String_insert(DOH *s, int pos, DOH *DOH);
void *String_data(DOH *s);
int String_cmp(DOH *, DOH *);
int String_hash(DOH *s);
+int String_dump(DOH *s, DOH *out);
int String_read(DOH *s, void *buffer, int length);
int String_write(DOH *s, void *buffer, int length);
+int String_getc(DOH *s);
+int String_putc(DOH *s, int ch);
+int String_ungetc(DOH *s, int ch);
int String_seek(DOH *s, long offset, int whence);
long String_tell(DOH *s);
-int String_printf(DOH *s, char *fmt, va_list ap);
-int String_scanfv(DOH *s, char *fmt, va_list ap);
static DohSequenceMethods StringSeqMethods = {
- 0,
- 0,
- String_delitem,
- String_insert,
- String_insertfv,
- 0,
- 0,
+ 0, /* doh_getitem */
+ 0, /* doh_setitem */
+ String_delitem, /* doh_delitem */
+ String_insert, /* doh_insitem */
+ 0, /* doh_first */
+ 0, /* doh_next */
};
static DohFileMethods StringFileMethods = {
String_read,
String_write,
+ String_putc,
+ String_getc,
+ String_ungetc,
String_seek,
String_tell,
- String_printf,
- String_scanfv,
0,
};
@@ -81,6 +85,7 @@ static DohObjInfo StringType = {
String_clear, /* sm_clear */
String_str, /* sm_str */
String_data, /* doh_data */
+ String_dump, /* doh_dump */
String_len, /* sm_len */
String_hash, /* sm_hash */
String_cmp, /* doh_cmp */
@@ -107,6 +112,27 @@ void *String_data(DOH *so) {
}
/* -----------------------------------------------------------------------------
+ * int String_dump(DOH *so, DOH *out)
+ *
+ * Serialize a string onto out
+ * ----------------------------------------------------------------------------- */
+
+int String_dump(DOH *so, DOH *out) {
+ int nsent;
+ int ret;
+ String *s;
+
+ s = (String *) so;
+ nsent = 0;
+ while (nsent < s->len) {
+ ret = Write(out,s->str+nsent,(s->len-nsent));
+ if (ret < 0) return ret;
+ nsent += ret;
+ }
+ return nsent;
+}
+
+/* -----------------------------------------------------------------------------
* NewString(const char *c) - Create a new string
* ----------------------------------------------------------------------------- */
DOH *
@@ -120,6 +146,7 @@ NewString(char *s)
str->hashkey = -1;
str->sp = 0;
str->lsp = 0;
+ str->pbi = 0;
str->line = 1;
max = INIT_MAXSIZE;
if (s) {
@@ -154,6 +181,7 @@ CopyString(DOH *so) {
str->sp = 0;
str->lsp = 0;
str->line = 1;
+ str->pbi = 0;
max = s->maxsize;
str->str = (char *) malloc(max);
memmove(str->str, s->str, max);
@@ -251,6 +279,7 @@ add(String *s, const char *newstr) {
s->maxsize = newmaxsize;
}
strcpy(s->str+s->len,newstr);
+ if (s->sp >= s->len) s->sp+=l;
s->len += l;
}
@@ -267,6 +296,7 @@ addstr(String *s, String *s1) {
s->maxsize = newmaxsize;
}
memmove(s->str+s->len,s1->str,s1->len);
+ if (s->sp >= s->len) s->sp+=l;
s->len += l;
}
@@ -281,8 +311,9 @@ String_addchar(DOH *so, char c) {
assert(s->str = (char *) realloc(s->str,2*s->maxsize));
s->maxsize *= 2;
}
- s->str[s->len++] = c;
- s->str[s->len] = 0;
+ s->str[s->len] = c;
+ if (s->sp >= s->len) s->sp++;
+ s->len++;
}
/* Expand a string to accomodate a write */
@@ -309,327 +340,8 @@ String_clear(DOH *so)
s->sp = 0;
s->lsp = 0;
s->line = 1;
+ s->pbi = 0;
}
-
-/* -----------------------------------------------------------------------------
- * void String_appendfv(String *s, char *format, va_list ap)
- *
- * Formats a string into s. This is an incredibly gross hack.
- * -----------------------------------------------------------------------------*/
-void
-String_appendfv(DOH *so, char *format, va_list ap)
-{
- static char *fmt_codes = "dioxXucsSfeEgGpnbB";
- int state = 0;
- char *p = format;
- char newformat[256];
- char *fmt;
- char temp[64];
- int widthval = 0;
- int precval = 0;
- int maxwidth;
- char *w, *prec;
- int ivalue;
- int dvalue;
- String *s;
-
- s = (String *) so;
-
- while (*p) {
- switch(state) {
- case 0: /* Ordinary text */
- if (*p != '%') {
- String_addchar(s,*p);
- } else{
- fmt = newformat;
- widthval = 0;
- precval = 0;
- *(fmt++) = *p;
- state = 10;
- }
- break;
- case 10: /* Look for a width and precision */
- if (isdigit(*p) && (*p != '0')) {
- w = temp;
- *(w++) = *p;
- *(fmt++) = *p;
- state = 20;
- } else if (strchr(fmt_codes,*p)) {
- /* Got one of the formatting codes */
- p--;
- state = 100;
- } else if (*p == '*') {
- /* Width field is specified in the format list */
- widthval = va_arg(ap,int);
- sprintf(temp,"%d",widthval);
- for (w = temp; *w; w++) {
- *(fmt++) = *w;
- }
- state = 30;
- } else if (*p == '%') {
- String_addchar(s,*p);
- fmt = newformat;
- state = 0;
- } else {
- *(fmt++) = *p;
- }
- break;
-
- case 20: /* Hmmm. At the start of a width field */
- if (isdigit(*p)) {
- *(w++) = *p;
- *(fmt++) = *p;
- } else if (strchr(fmt_codes,*p)) {
- /* Got one of the formatting codes */
- /* Figure out width */
- *w = 0;
- widthval = atoi(temp);
- p--;
- state = 100;
- } else if (*p == '.') {
- *w = 0;
- widthval = atoi(temp);
- w = temp;
- *(fmt++) = *p;
- state = 40;
- } else {
- /* ??? */
- *w = 0;
- widthval = atoi(temp);
- state = 50;
- }
- break;
-
- case 30: /* Parsed a width from an argument. Look for a . */
- if (*p == '.') {
- w = temp;
- *(fmt++) = *p;
- state = 40;
- } else if (strchr(fmt_codes,*p)) {
- /* Got one of the formatting codes */
- /* Figure out width */
- p--;
- state = 100;
- } else {
- /* hmmm. Something else. */
- state = 50;
- }
- break;
-
- case 40:
- /* Start of precision expected */
- if (isdigit(*p) && (*p != '0')) {
- *(fmt++) = *p;
- *(w++) = *p;
- state = 41;
- } else if (*p == '*') {
- /* Precision field is specified in the format list */
- precval = va_arg(ap,int);
- sprintf(temp,"%d",precval);
- for (w = temp; *w; w++) {
- *(fmt++) = *w;
- }
- state = 50;
- } else if (strchr(fmt_codes,*p)) {
- p--;
- state = 100;
- } else {
- *(fmt++) = *p;
- state = 50;
- }
- break;
- case 41:
- if (isdigit(*p)) {
- *(fmt++) = *p;
- *(w++) = *p;
- } else if (strchr(fmt_codes,*p)) {
- /* Got one of the formatting codes */
- /* Figure out width */
- *w = 0;
- precval = atoi(temp);
- p--;
- state = 100;
- } else {
- *w = 0;
- precval = atoi(temp);
- *(fmt++) = *p;
- state = 50;
- }
- break;
- /* Hang out, wait for format specifier */
- case 50:
- if (strchr(fmt_codes,*p)) {
- p--;
- state = 100;
- } else {
- *(fmt++) = *p;
- }
- break;
- case 100:
- /* Got a formatting code */
- if (widthval < precval) maxwidth = precval;
- else maxwidth = widthval;
- if ((*p == 's') || (*p == 'S')) { /* Null-Terminated string */
- DOH *doh;
- String *Sval;
- doh = va_arg(ap, DOH *);
- if (DohCheck(doh)) {
- /* Is an object at least */
- if (String_check(doh)) {
- Sval = (String *) doh;
- } else {
- Sval = (String *) Str(doh);
- }
- maxwidth = maxwidth+strlen(newformat)+strlen(Sval->str);
- String_expand(s,maxwidth);
- *(fmt++) = 's';
- *fmt = 0;
- sprintf(s->str+s->len,newformat,Sval->str);
- s->len = s->len + strlen(s->str+s->len);
- if ((DOH *) Sval != doh) {
- Delete(Sval);
- }
- if (*p == 'S') {
- Delete(doh);
- }
- } else {
- maxwidth = maxwidth+strlen(newformat)+strlen((char *) doh);
- String_expand(s,maxwidth);
- *(fmt++) = 's';
- *fmt = 0;
- sprintf(s->str+s->len,newformat,doh);
- s->len = s->len + strlen(s->str+s->len);
- }
- } else if ((*p == 'b') || (*p == 'B')) {
- /* Raw binary mode */
- DOH *doh, *Sval;
- doh = va_arg(ap, DOH *);
- if (DohCheck(doh)) {
- void *ptr;
- int len;
- Sval = Str(doh);
- ptr = Data(Sval);
- len = Len(Sval);
- if ((widthval > 0) && (widthval < len)) len = widthval;
- String_expand(s,len);
- if (ptr) {
- memmove(s->str+s->len,ptr,len);
- s->len += len;
- }
- if (*p == 'B') {
- Delete(doh);
- }
- Delete(Sval);
- } else {
- String_expand(s,widthval);
- memmove(s->str+s->len,doh,widthval);
- s->len+=widthval;
- }
- } else {
- int ivalue;
- double dvalue;
- void *pvalue;
- *(fmt++) = *p;
- *fmt = 0;
- maxwidth = maxwidth+strlen(newformat)+64;
- String_expand(s,maxwidth);
- switch(*p) {
- case 'd':
- case 'i':
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- case 'c':
- ivalue = va_arg(ap,int);
- sprintf(s->str+s->len,newformat,ivalue);
- break;
- case 'f':
- case 'g':
- case 'e':
- case 'E':
- case 'G':
- dvalue = va_arg(ap,double);
- sprintf(s->str+s->len,newformat,dvalue);
- break;
- case 'p':
- pvalue = va_arg(ap,void *);
- sprintf(s->str+s->len,newformat,pvalue);
- break;
- default:
- break;
- }
- s->len = s->len + strlen(s->str+s->len);
- }
- state = 0;
- break;
- }
- p++;
- }
- if (state) {
- *fmt = 0;
- add(s,fmt);
- }
-}
-
-/* ----------------------------------------------------------------------
- * int String_scanfv(DOH *doh, char *format, va_list ap)
- *
- * Do a string scanf. Somewhat broken compared to C scanf.
- * ---------------------------------------------------------------------- */
-
-int String_scanfv(DOH *doh, char *format, va_list ap) {
- static char *fmt_chars = "diouxcsefgp";
- String *s;
- char newformat[256];
- char *fmt;
- char *p;
- int state;
- void *ptr;
- int total = 0;
- int i;
-
- s = (String *) doh;
- state = 0;
- p = format;
- while (*p) {
- switch(state) {
- case 0:
- if (*p == '%') {
- fmt = newformat;
- *(fmt++) = *p;
- state = 10;
- }
- break;
- case 10:
- if (strchr(fmt_chars,*p)) {
- int len;
- *(fmt++) = *p;
- *fmt = 0;
- ptr = va_arg(ap, void *);
- len = sscanf(s->str+s->sp,newformat,ptr);
- for (i = 0; i < len; i++) {
- while (s->sp < s->len) {
- if (!isspace(s->str[s->sp])) break;
- s->sp++;
- }
- while (s->sp < s->len) {
- if (isspace(s->str[s->sp])) break;
- s->sp++;
- }
- }
- total += len;
- state = 0;
- fmt = newformat;
- } else {
- *(fmt++) = *p;
- }
- break;
- }
- p++;
- }
- return total;
-}
void
raw_insert(String *s, int pos, char *data, int len)
@@ -675,27 +387,6 @@ String_insert(DOH *so, int pos, DOH *str)
}
/* -----------------------------------------------------------------------------
- * void String_insertf(DOH *so, char *format, ...) - Insert a string
- * -----------------------------------------------------------------------------*/
-
-int
-String_insertfv(DOH *so, int pos, char *format, va_list ap)
-{
- String *s;
- String *temp;
- s = (String *) so;
- if (pos == DOH_END) {
- String_appendfv(so,format,ap);
- return 0;
- }
- temp = NewString("");
- String_appendfv(temp,format,ap);
- raw_insert(s,pos, temp->str,temp->len);
- Delete(temp);
- return 0;
-}
-
-/* -----------------------------------------------------------------------------
* int String_delitem(DOH *so, int pos)
*
* Delete an individual item
@@ -734,12 +425,26 @@ String_str(DOH *so) {
* ----------------------------------------------------------------------------- */
int
String_read(DOH *so, void *buffer, int len) {
- int reallen;
+ int reallen, retlen;
+ int i;
+ char *cb;
String *s = (String *) so;
- if ((s->sp + len) > s->len) reallen = (s->len - s->sp);
- memmove(buffer, s->str+s->sp, reallen);
- s->sp += reallen;
- return reallen;
+ if (((s->sp-s->pbi) + len) > s->len) reallen = (s->len - (s->sp-s->pbi));
+
+ cb = (char *) buffer;
+ retlen = reallen;
+
+ /* Read the push-back buffer contents first */
+ while (reallen > 0) {
+ if (s->pbi <= 0) break;
+ *(cb++) = (char) s->pb[--s->pbi];
+ reallen--;
+ }
+ if (reallen > 0) {
+ memmove(cb, s->str+s->sp, reallen);
+ s->sp += reallen;
+ }
+ return retlen;
}
/* -----------------------------------------------------------------------------
@@ -757,8 +462,10 @@ String_write(DOH *so, void *buffer, int len) {
s->maxsize = newlen;
s->len = s->sp + len;
}
+ if (newlen > s->len) s->len = newlen;
memmove(s->str+s->sp,buffer,len);
s->sp += len;
+ s->pbi = 0;
return len;
}
@@ -780,6 +487,7 @@ String_seek(DOH *so, long offset, int whence) {
s->sp = pos + offset;
if (s->sp < 0) s->sp = 0;
if (s->sp > s->len) s->sp = s->len;
+ s->pbi = 0;
return 0;
}
@@ -791,26 +499,63 @@ String_seek(DOH *so, long offset, int whence) {
long
String_tell(DOH *so) {
String *s = (String *) so;
- return (long) s->sp;
+ return (long) (s->sp - s->pbi);
}
/* -----------------------------------------------------------------------------
- * int String_printf(DOH *so, char *format, ...)
+ * int String_putc(DOH *so, int ch)
*
+ * Put a character into the string.
* ----------------------------------------------------------------------------- */
int
-String_printf(DOH *so, char *format, va_list ap)
-{
- int len;
- DOH *nso;
+String_putc(DOH *so, int ch) {
String *s = (String *) so;
- nso = NewString("");
- String_appendfv(nso,format,ap);
- len = ((String *) nso)->len;
- String_write(so,Data(nso),len);
- Delete(nso);
- return len;
+ if (s->sp >= s->len) {
+ String_addchar(s,(char) ch);
+ } else {
+ s->str[s->sp] = (char) ch;
+ s->sp++;
+ }
+ s->pbi = 0;
+ return ch;
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_getc(DOH *so)
+ *
+ * Get a character from the string
+ * ----------------------------------------------------------------------------- */
+
+int String_getc(DOH *so) {
+ String *s = (String *) so;
+ if (s->pbi) {
+ return (int) s->pb[--s->pbi];
+ }
+ if (s->sp >= s->len) return EOF;
+ else return (int) s->str[s->sp++];
+}
+
+/* -----------------------------------------------------------------------------
+ * int String_ungetc(DOH *so, int ch)
+ *
+ * Put a character back on to the input stream.
+ * ----------------------------------------------------------------------------- */
+
+int String_ungetc(DOH *so, int ch) {
+ String *s = (String *) so;
+ int i;
+ if (ch == EOF) return ch;
+ if ((s->sp - s->pbi) <= 0) return EOF;
+ if (s->pbi == 4) {
+ s->pb[0] = s->pb[1];
+ s->pb[1] = s->pb[2];
+ s->pb[2] = s->pb[3];
+ s->pb[3] = (char) ch;
+ } else {
+ s->pb[s->pbi++] = (char) ch;
+ }
+ return ch;
}
/* -----------------------------------------------------------------------------