aboutsummaryrefslogtreecommitdiff
path: root/src/libString
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-12-11 18:15:57 +0000
committerrsc <devnull@localhost>2003-12-11 18:15:57 +0000
commit7f11104a5737adf261d10bc1a7b85e740f2eb491 (patch)
tree2473f5fbdd42b74b189e2fcc2a46896a50ede030 /src/libString
parent57ccfb9e8f51138c33ad5f58e14c0e54246cf5c4 (diff)
downloadplan9port-7f11104a5737adf261d10bc1a7b85e740f2eb491.tar.gz
plan9port-7f11104a5737adf261d10bc1a7b85e740f2eb491.tar.bz2
plan9port-7f11104a5737adf261d10bc1a7b85e740f2eb491.zip
Add libString.
Diffstat (limited to 'src/libString')
-rw-r--r--src/libString/mkfile27
-rw-r--r--src/libString/s_alloc.c86
-rw-r--r--src/libString/s_append.c17
-rw-r--r--src/libString/s_array.c17
-rw-r--r--src/libString/s_copy.c19
-rw-r--r--src/libString/s_getline.c72
-rw-r--r--src/libString/s_grow.c34
-rw-r--r--src/libString/s_memappend.c20
-rw-r--r--src/libString/s_nappend.c18
-rw-r--r--src/libString/s_parse.c40
-rw-r--r--src/libString/s_putc.c13
-rw-r--r--src/libString/s_rdinstack.c141
-rw-r--r--src/libString/s_read.c38
-rw-r--r--src/libString/s_read_line.c31
-rw-r--r--src/libString/s_reset.c23
-rw-r--r--src/libString/s_terminate.c13
-rw-r--r--src/libString/s_tolower.c15
-rw-r--r--src/libString/s_unique.c16
18 files changed, 640 insertions, 0 deletions
diff --git a/src/libString/mkfile b/src/libString/mkfile
new file mode 100644
index 00000000..49803b45
--- /dev/null
+++ b/src/libString/mkfile
@@ -0,0 +1,27 @@
+PLAN9=../..
+<$PLAN9/src/mkhdr
+
+LIB=libString.a
+
+OFILES=\
+ s_alloc.$O\
+ s_append.$O\
+ s_array.$O\
+ s_copy.$O\
+ s_getline.$O\
+ s_grow.$O\
+ s_memappend.$O\
+ s_nappend.$O\
+ s_parse.$O\
+ s_putc.$O\
+ s_rdinstack.$O\
+ s_read.$O\
+ s_read_line.$O\
+ s_reset.$O\
+ s_terminate.$O\
+ s_tolower.$O\
+ s_unique.$O\
+
+HFILES=/sys/include/String.h
+
+<$PLAN9/src/mksyslib
diff --git a/src/libString/s_alloc.c b/src/libString/s_alloc.c
new file mode 100644
index 00000000..34f89164
--- /dev/null
+++ b/src/libString/s_alloc.c
@@ -0,0 +1,86 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+#define STRLEN 128
+
+extern void
+s_free(String *sp)
+{
+ if (sp == nil)
+ return;
+ lock(&sp->lk);
+ if(--(sp->ref) != 0){
+ unlock(&sp->lk);
+ return;
+ }
+ unlock(&sp->lk);
+
+ if(sp->fixed == 0 && sp->base != nil)
+ free(sp->base);
+ free(sp);
+}
+
+/* get another reference to a string */
+extern String *
+s_incref(String *sp)
+{
+ lock(&sp->lk);
+ sp->ref++;
+ unlock(&sp->lk);
+
+ return sp;
+}
+
+/* allocate a String head */
+extern String *
+_s_alloc(void)
+{
+ String *s;
+
+ s = mallocz(sizeof *s, 1);
+ if(s == nil)
+ return s;
+ s->ref = 1;
+ s->fixed = 0;
+ return s;
+}
+
+/* create a new `short' String */
+extern String *
+s_newalloc(int len)
+{
+ String *sp;
+
+ sp = _s_alloc();
+ if(sp == nil)
+ sysfatal("s_newalloc: %r");
+ setmalloctag(sp, getcallerpc(&len));
+ if(len < STRLEN)
+ len = STRLEN;
+ sp->base = sp->ptr = malloc(len);
+ if (sp->base == nil)
+ sysfatal("s_newalloc: %r");
+ setmalloctag(sp->base, getcallerpc(&len));
+
+ sp->end = sp->base + len;
+ s_terminate(sp);
+ return sp;
+}
+
+/* create a new `short' String */
+extern String *
+s_new(void)
+{
+ String *sp;
+
+ sp = _s_alloc();
+ if(sp == nil)
+ sysfatal("s_new: %r");
+ sp->base = sp->ptr = malloc(STRLEN);
+ if (sp->base == nil)
+ sysfatal("s_new: %r");
+ sp->end = sp->base + STRLEN;
+ s_terminate(sp);
+ return sp;
+}
diff --git a/src/libString/s_append.c b/src/libString/s_append.c
new file mode 100644
index 00000000..1b02d20e
--- /dev/null
+++ b/src/libString/s_append.c
@@ -0,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+/* append a char array to a String */
+String *
+s_append(String *to, char *from)
+{
+ if (to == 0)
+ to = s_new();
+ if (from == 0)
+ return to;
+ for(; *from; from++)
+ s_putc(to, *from);
+ s_terminate(to);
+ return to;
+}
diff --git a/src/libString/s_array.c b/src/libString/s_array.c
new file mode 100644
index 00000000..3cf571b1
--- /dev/null
+++ b/src/libString/s_array.c
@@ -0,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+extern String* _s_alloc(void);
+
+/* return a String containing a character array (this had better not grow) */
+extern String *
+s_array(char *cp, int len)
+{
+ String *sp = _s_alloc();
+
+ sp->base = sp->ptr = cp;
+ sp->end = sp->base + len;
+ sp->fixed = 1;
+ return sp;
+}
diff --git a/src/libString/s_copy.c b/src/libString/s_copy.c
new file mode 100644
index 00000000..5a23b3c2
--- /dev/null
+++ b/src/libString/s_copy.c
@@ -0,0 +1,19 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+
+/* return a String containing a copy of the passed char array */
+extern String*
+s_copy(char *cp)
+{
+ String *sp;
+ int len;
+
+ len = strlen(cp)+1;
+ sp = s_newalloc(len);
+ setmalloctag(sp, getcallerpc(&cp));
+ strcpy(sp->base, cp);
+ sp->ptr = sp->base + len - 1; /* point to 0 terminator */
+ return sp;
+}
diff --git a/src/libString/s_getline.c b/src/libString/s_getline.c
new file mode 100644
index 00000000..e46dc125
--- /dev/null
+++ b/src/libString/s_getline.c
@@ -0,0 +1,72 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "libString.h"
+
+/* Append an input line to a String.
+ *
+ * Returns a pointer to the character string (or 0).
+ * Leading whitespace and newlines are removed.
+ *
+ * Empty lines and lines starting with '#' are ignored.
+ */
+extern char *
+s_getline(Biobuf *fp, String *to)
+{
+ int c;
+ int len=0;
+
+ s_terminate(to);
+
+ /* end of input */
+ if ((c = Bgetc(fp)) < 0)
+ return 0;
+
+ /* take care of inconsequentials */
+ for(;;) {
+ /* eat leading white */
+ while(c==' ' || c=='\t' || c=='\n' || c=='\r')
+ c = Bgetc(fp);
+
+ if(c < 0)
+ return 0;
+
+ /* take care of comments */
+ if(c == '#'){
+ do {
+ c = Bgetc(fp);
+ if(c < 0)
+ return 0;
+ } while(c != '\n');
+ continue;
+ }
+
+ /* if we got here, we've gotten something useful */
+ break;
+ }
+
+ /* gather up a line */
+ for(;;) {
+ len++;
+ switch(c) {
+ case -1:
+ s_terminate(to);
+ return len ? to->ptr-len : 0;
+ case '\\':
+ c = Bgetc(fp);
+ if (c != '\n') {
+ s_putc(to, '\\');
+ s_putc(to, c);
+ }
+ break;
+ case '\n':
+ s_terminate(to);
+ return len ? to->ptr-len : 0;
+ default:
+ s_putc(to, c);
+ break;
+ }
+ c = Bgetc(fp);
+ }
+ return 0;
+}
diff --git a/src/libString/s_grow.c b/src/libString/s_grow.c
new file mode 100644
index 00000000..5cf2a141
--- /dev/null
+++ b/src/libString/s_grow.c
@@ -0,0 +1,34 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+/* grow a String's allocation by at least `incr' bytes */
+extern String*
+s_grow(String *s, int incr)
+{
+ char *cp;
+ int size;
+
+ if(s->fixed)
+ sysfatal("s_grow of constant string");
+ s = s_unique(s);
+
+ /*
+ * take a larger increment to avoid mallocing too often
+ */
+ size = s->end-s->base;
+ if(size/2 < incr)
+ size += incr;
+ else
+ size += size/2;
+
+ cp = realloc(s->base, size);
+ if (cp == 0)
+ sysfatal("s_grow: %r");
+ s->ptr = (s->ptr - s->base) + cp;
+ s->end = cp + size;
+ s->base = cp;
+
+ return s;
+}
+
diff --git a/src/libString/s_memappend.c b/src/libString/s_memappend.c
new file mode 100644
index 00000000..27b69850
--- /dev/null
+++ b/src/libString/s_memappend.c
@@ -0,0 +1,20 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+/* append a char array ( of up to n characters) to a String */
+String *
+s_memappend(String *to, char *from, int n)
+{
+ char *e;
+
+ if (to == 0)
+ to = s_new();
+ if (from == 0)
+ return to;
+ for(e = from + n; from < e; from++)
+ s_putc(to, *from);
+ s_terminate(to);
+ return to;
+}
+
diff --git a/src/libString/s_nappend.c b/src/libString/s_nappend.c
new file mode 100644
index 00000000..fb41f932
--- /dev/null
+++ b/src/libString/s_nappend.c
@@ -0,0 +1,18 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+/* append a char array ( of up to n characters) to a String */
+String *
+s_nappend(String *to, char *from, int n)
+{
+ if (to == 0)
+ to = s_new();
+ if (from == 0)
+ return to;
+ for(; n && *from; from++, n--)
+ s_putc(to, *from);
+ s_terminate(to);
+ return to;
+}
+
diff --git a/src/libString/s_parse.c b/src/libString/s_parse.c
new file mode 100644
index 00000000..376a41e2
--- /dev/null
+++ b/src/libString/s_parse.c
@@ -0,0 +1,40 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+#define isspace(c) ((c)==' ' || (c)=='\t' || (c)=='\n')
+
+/* Get the next field from a String. The field is delimited by white space,
+ * single or double quotes.
+ */
+String *
+s_parse(String *from, String *to)
+{
+ if (*from->ptr == '\0')
+ return 0;
+ if (to == 0)
+ to = s_new();
+ if (*from->ptr == '\'') {
+ from->ptr++;
+ for (;*from->ptr != '\'' && *from->ptr != '\0'; from->ptr++)
+ s_putc(to, *from->ptr);
+ if (*from->ptr == '\'')
+ from->ptr++;
+ } else if (*from->ptr == '"') {
+ from->ptr++;
+ for (;*from->ptr != '"' && *from->ptr != '\0'; from->ptr++)
+ s_putc(to, *from->ptr);
+ if (*from->ptr == '"')
+ from->ptr++;
+ } else {
+ for (;!isspace(*from->ptr) && *from->ptr != '\0'; from->ptr++)
+ s_putc(to, *from->ptr);
+ }
+ s_terminate(to);
+
+ /* crunch trailing white */
+ while(isspace(*from->ptr))
+ from->ptr++;
+
+ return to;
+}
diff --git a/src/libString/s_putc.c b/src/libString/s_putc.c
new file mode 100644
index 00000000..29a385d7
--- /dev/null
+++ b/src/libString/s_putc.c
@@ -0,0 +1,13 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+void
+s_putc(String *s, int c)
+{
+ if(s->ref > 1)
+ sysfatal("can't s_putc a shared string");
+ if (s->ptr >= s->end)
+ s_grow(s, 2);
+ *(s->ptr)++ = c;
+}
diff --git a/src/libString/s_rdinstack.c b/src/libString/s_rdinstack.c
new file mode 100644
index 00000000..de12d219
--- /dev/null
+++ b/src/libString/s_rdinstack.c
@@ -0,0 +1,141 @@
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "libString.h"
+
+struct Sinstack{
+ int depth;
+ Biobuf *fp[32]; /* hard limit to avoid infinite recursion */
+};
+
+/* initialize */
+extern Sinstack *
+s_allocinstack(char *file)
+{
+ Sinstack *sp;
+ Biobuf *fp;
+
+ fp = Bopen(file, OREAD);
+ if(fp == nil)
+ return nil;
+
+ sp = malloc(sizeof *sp);
+ sp->depth = 0;
+ sp->fp[0] = fp;
+ return sp;
+}
+
+extern void
+s_freeinstack(Sinstack *sp)
+{
+ while(sp->depth >= 0)
+ Bterm(sp->fp[sp->depth--]);
+ free(sp);
+}
+
+/* Append an input line to a String.
+ *
+ * Empty lines and leading whitespace are removed.
+ */
+static char *
+rdline(Biobuf *fp, String *to)
+{
+ int c;
+ int len = 0;
+
+ c = Bgetc(fp);
+
+ /* eat leading white */
+ while(c==' ' || c=='\t' || c=='\n' || c=='\r')
+ c = Bgetc(fp);
+
+ if(c < 0)
+ return 0;
+
+ for(;;){
+ switch(c) {
+ case -1:
+ goto out;
+ case '\\':
+ c = Bgetc(fp);
+ if (c != '\n') {
+ s_putc(to, '\\');
+ s_putc(to, c);
+ len += 2;
+ }
+ break;
+ case '\r':
+ break;
+ case '\n':
+ if(len != 0)
+ goto out;
+ break;
+ default:
+ s_putc(to, c);
+ len++;
+ break;
+ }
+ c = Bgetc(fp);
+ }
+out:
+ s_terminate(to);
+ return to->ptr - len;
+}
+
+/* Append an input line to a String.
+ *
+ * Returns a pointer to the character string (or 0).
+ * Leading whitespace and newlines are removed.
+ * Lines starting with #include cause us to descend into the new file.
+ * Empty lines and other lines starting with '#' are ignored.
+ */
+extern char *
+s_rdinstack(Sinstack *sp, String *to)
+{
+ char *p;
+ Biobuf *fp, *nfp;
+
+ s_terminate(to);
+ fp = sp->fp[sp->depth];
+
+ for(;;){
+ p = rdline(fp, to);
+ if(p == nil){
+ if(sp->depth == 0)
+ break;
+ Bterm(fp);
+ sp->depth--;
+ return s_rdinstack(sp, to);
+ }
+
+ if(strncmp(p, "#include", 8) == 0 && (p[8] == ' ' || p[8] == '\t')){
+ to->ptr = p;
+ p += 8;
+
+ /* sanity (and looping) */
+ if(sp->depth >= nelem(sp->fp))
+ sysfatal("s_recgetline: includes too deep");
+
+ /* skip white */
+ while(*p == ' ' || *p == '\t')
+ p++;
+
+ nfp = Bopen(p, OREAD);
+ if(nfp == nil)
+ continue;
+ sp->depth++;
+ sp->fp[sp->depth] = nfp;
+ return s_rdinstack(sp, to);
+ }
+
+ /* got milk? */
+ if(*p != '#')
+ break;
+
+ /* take care of comments */
+ to->ptr = p;
+ s_terminate(to);
+ }
+ return p;
+}
diff --git a/src/libString/s_read.c b/src/libString/s_read.c
new file mode 100644
index 00000000..59581eaf
--- /dev/null
+++ b/src/libString/s_read.c
@@ -0,0 +1,38 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "libString.h"
+
+enum
+{
+ Minread= 256,
+};
+
+/* Append up to 'len' input bytes to the string 'to'.
+ *
+ * Returns the number of characters read.
+ */
+extern int
+s_read(Biobuf *fp, String *to, int len)
+{
+ int rv;
+ int n;
+
+ if(to->ref > 1)
+ sysfatal("can't s_read a shared string");
+ for(rv = 0; rv < len; rv += n){
+ n = to->end - to->ptr;
+ if(n < Minread){
+ s_grow(to, Minread);
+ n = to->end - to->ptr;
+ }
+ if(n > len - rv)
+ n = len - rv;
+ n = Bread(fp, to->ptr, n);
+ if(n <= 0)
+ break;
+ to->ptr += n;
+ }
+ s_terminate(to);
+ return rv;
+}
diff --git a/src/libString/s_read_line.c b/src/libString/s_read_line.c
new file mode 100644
index 00000000..b1de5ac4
--- /dev/null
+++ b/src/libString/s_read_line.c
@@ -0,0 +1,31 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "libString.h"
+
+/* Append an input line to a String.
+ *
+ * Returns a pointer to the character string (or 0).
+ * Trailing newline is left on.
+ */
+extern char *
+s_read_line(Biobuf *fp, String *to)
+{
+ char *cp;
+ int llen;
+
+ if(to->ref > 1)
+ sysfatal("can't s_read_line a shared string");
+ s_terminate(to);
+ cp = Brdline(fp, '\n');
+ if(cp == 0)
+ return 0;
+ llen = Blinelen(fp);
+ if(to->end - to->ptr < llen)
+ s_grow(to, llen);
+ memmove(to->ptr, cp, llen);
+ cp = to->ptr;
+ to->ptr += llen;
+ s_terminate(to);
+ return cp;
+}
diff --git a/src/libString/s_reset.c b/src/libString/s_reset.c
new file mode 100644
index 00000000..cd2a7421
--- /dev/null
+++ b/src/libString/s_reset.c
@@ -0,0 +1,23 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+String*
+s_reset(String *s)
+{
+ if(s != nil){
+ s = s_unique(s);
+ s->ptr = s->base;
+ *s->ptr = '\0';
+ } else
+ s = s_new();
+ return s;
+}
+
+String*
+s_restart(String *s)
+{
+ s = s_unique(s);
+ s->ptr = s->base;
+ return s;
+}
diff --git a/src/libString/s_terminate.c b/src/libString/s_terminate.c
new file mode 100644
index 00000000..dc893ab2
--- /dev/null
+++ b/src/libString/s_terminate.c
@@ -0,0 +1,13 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+void
+s_terminate(String *s)
+{
+ if(s->ref > 1)
+ sysfatal("can't s_terminate a shared string");
+ if (s->ptr >= s->end)
+ s_grow(s, 1);
+ *s->ptr = 0;
+}
diff --git a/src/libString/s_tolower.c b/src/libString/s_tolower.c
new file mode 100644
index 00000000..737fff1f
--- /dev/null
+++ b/src/libString/s_tolower.c
@@ -0,0 +1,15 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+#include "libString.h"
+
+
+/* convert String to lower case */
+void
+s_tolower(String *sp)
+{
+ char *cp;
+
+ for(cp=sp->ptr; *cp; cp++)
+ *cp = tolower(*cp);
+}
diff --git a/src/libString/s_unique.c b/src/libString/s_unique.c
new file mode 100644
index 00000000..134411c9
--- /dev/null
+++ b/src/libString/s_unique.c
@@ -0,0 +1,16 @@
+#include <u.h>
+#include <libc.h>
+#include "libString.h"
+
+String*
+s_unique(String *s)
+{
+ String *p;
+
+ if(s->ref > 1){
+ p = s;
+ s = s_clone(p);
+ s_free(p);
+ }
+ return s;
+}