Import a (modernized) version of djb's stralloc
library.
Lots of code in Magicka is involved in dynamic string manipulation. `stralloc` isn't a bad library for this sort of thing. Note that this is complements, but doesn't replace, existing string utilities. Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
This commit is contained in:
parent
82b6ec3a3b
commit
9a7ceeee3d
@ -47,13 +47,13 @@ HDRS:= bbs.h
|
||||
OBJS:= inih/ini.o bbs.o main.o users.o main_menu.o mail_menu.o \
|
||||
doors.o bbs_list.o chat_system.o email.o files.o settings.o \
|
||||
lua_glue.o strings.o bluewave.o hashmap/hashmap.o menus.o \
|
||||
nodelist.o blog.o util.o
|
||||
nodelist.o blog.o util.o stralloc/stralloc.o
|
||||
|
||||
WWWOBJS:= ../deps/aha/aha.o ../deps/hashids/hashids.o www.o www_email.o \
|
||||
www_msgs.o www_last10.o www_blog.o www_files.o ${OBJS}
|
||||
|
||||
ifeq ($(MAKECMDGOALS), www)
|
||||
CFLAGS+= ${CFLAGS} -I${DEPSDIR}/libb64-1.2/include -DENABLE_WWW=1
|
||||
CFLAGS+= ${CFLAGS} -Istralloc -I${DEPSDIR}/libb64-1.2/include -DENABLE_WWW=1
|
||||
endif
|
||||
|
||||
%.o: %.c ${HDRS}
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "lua/lauxlib.h"
|
||||
#include "jamlib/jam.h"
|
||||
|
||||
#include "stralloc/stralloc.h"
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 12
|
||||
#define VERSION_STR "alpha"
|
||||
|
4
src/stralloc/README
Normal file
4
src/stralloc/README
Normal file
@ -0,0 +1,4 @@
|
||||
This is a cleanup and modernization of the stralloc
|
||||
library from qmail, by Daniel J. Bernstein. Qmail was
|
||||
placed into the public domain by its author; presumably
|
||||
this library, as part of qmail, was as well.
|
162
src/stralloc/stralloc.3
Normal file
162
src/stralloc/stralloc.3
Normal file
@ -0,0 +1,162 @@
|
||||
.TH stralloc 3
|
||||
.SH NAME
|
||||
stralloc \- dynamically allocated strings
|
||||
.SH SYNTAX
|
||||
.B #include <stralloc.h>
|
||||
|
||||
int \fBstralloc_ready\fP(&\fIsa\fR,\fIlen\fR);
|
||||
.br
|
||||
int \fBstralloc_readyplus\fP(&\fIsa\fR,\fIlen\fR);
|
||||
|
||||
int \fBstralloc_copy\fP(&\fIsa\fR,&\fIsa2\fR);
|
||||
.br
|
||||
int \fBstralloc_copys\fP(&\fIsa\fR,\fIbuf\fR);
|
||||
.br
|
||||
int \fBstralloc_copyb\fP(&\fIsa\fR,\fIbuf\fR,\fIlen\fR);
|
||||
|
||||
int \fBstralloc_cat\fP(&\fIsa\fR,&\fIsa2\fR);
|
||||
.br
|
||||
int \fBstralloc_cats\fP(&\fIsa\fR,\fIbuf\fR);
|
||||
.br
|
||||
int \fBstralloc_catb\fP(&\fIsa\fR,\fIbuf\fR,\fIlen\fR);
|
||||
|
||||
int \fBstralloc_append1\fP(&\fIsa\fR,\fIb\fR);
|
||||
.br
|
||||
int \fBstralloc_0\fP(&\fIsa\fR);
|
||||
|
||||
int \fBstralloc_starts\fP(&\fIsa\fR,\fIbuf\fR);
|
||||
|
||||
stralloc \fIsa\fR = {0};
|
||||
.br
|
||||
stralloc \fIsa2\fR = {0};
|
||||
.br
|
||||
size_t \fIlen\fR;
|
||||
.br
|
||||
const char *\fIbuf\fR;
|
||||
.br
|
||||
char \fIb\fR;
|
||||
.SH DESCRIPTION
|
||||
A
|
||||
.B stralloc
|
||||
variable holds a string in dynamically allocated space.
|
||||
String length is limited only by memory.
|
||||
String contents are unrestricted.
|
||||
|
||||
The
|
||||
.B stralloc
|
||||
structure has three components:
|
||||
.I sa\fB.s
|
||||
is a pointer to the string, or 0 if it is not allocated;
|
||||
.I sa\fB.len
|
||||
is the number of bytes in the string, if it is allocated;
|
||||
.I sa\fB.a
|
||||
is the number of bytes allocated for the string, if it is allocated.
|
||||
A
|
||||
.B stralloc
|
||||
variable should be initialized to {0},
|
||||
meaning unallocated.
|
||||
|
||||
.B stralloc_ready
|
||||
makes sure that
|
||||
.I sa
|
||||
has enough space allocated for
|
||||
.I len
|
||||
characters.
|
||||
It allocates extra space if necessary.
|
||||
|
||||
.B stralloc_readyplus
|
||||
makes sure that
|
||||
.I sa
|
||||
has enough space allocated for
|
||||
.I len
|
||||
characters more than its current length.
|
||||
If
|
||||
.I sa
|
||||
is unallocated,
|
||||
.B stralloc_readyplus
|
||||
is the same as
|
||||
.BR stralloc_ready .
|
||||
|
||||
.B stralloc_copy
|
||||
copies
|
||||
.I sa2
|
||||
to
|
||||
.IR sa ,
|
||||
allocating space if necessary.
|
||||
Here
|
||||
.I sa2
|
||||
is an allocated
|
||||
.B stralloc
|
||||
variable.
|
||||
|
||||
.B stralloc_copys
|
||||
copies a 0-terminated string,
|
||||
.IR buf ,
|
||||
to
|
||||
.IR sa ,
|
||||
without the 0.
|
||||
|
||||
.B stralloc_copyb
|
||||
copies
|
||||
.I len
|
||||
characters from
|
||||
.I buf
|
||||
to
|
||||
.IR sa .
|
||||
|
||||
.B stralloc_cat
|
||||
appends
|
||||
.I sa2
|
||||
to
|
||||
.IR sa ,
|
||||
allocating space if necessary.
|
||||
If
|
||||
.I sa
|
||||
is unallocated,
|
||||
.B stralloc_cat
|
||||
is the same as
|
||||
.BR stralloc_copy .
|
||||
|
||||
.B stralloc_cats
|
||||
and
|
||||
.B stralloc_catb
|
||||
are analogous to
|
||||
.B stralloc_copys
|
||||
and
|
||||
.BR stralloc_copyb .
|
||||
|
||||
.B stralloc_append1
|
||||
adds a single character,
|
||||
.IR b ,
|
||||
to
|
||||
.IR sa ,
|
||||
allocating space if necessary.
|
||||
|
||||
.B stralloc_0
|
||||
adds a single 0 character
|
||||
to
|
||||
.IR sa .
|
||||
|
||||
.B stralloc_starts
|
||||
returns 1 if the 0-terminated string
|
||||
.IR buf ,
|
||||
without the 0,
|
||||
is a prefix of
|
||||
.IR sa .
|
||||
.SH "ERROR HANDLING"
|
||||
If a
|
||||
.B stralloc
|
||||
routine runs out of memory,
|
||||
it leaves
|
||||
.I sa
|
||||
alone and returns 0,
|
||||
setting
|
||||
.B errno
|
||||
appropriately.
|
||||
On success it returns 1;
|
||||
this guarantees that
|
||||
.I sa
|
||||
is allocated.
|
||||
.SH "SEE ALSO"
|
||||
alloc(3),
|
||||
error(3)
|
65
src/stralloc/stralloc.c
Normal file
65
src/stralloc/stralloc.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stralloc.h"
|
||||
|
||||
int stralloc_ready(stralloc *sa, size_t n) {
|
||||
size_t na;
|
||||
char *ns;
|
||||
|
||||
assert(sa != NULL);
|
||||
if (sa->s == NULL) {
|
||||
sa->len = 0;
|
||||
sa->a = n;
|
||||
sa->s = malloc(n);
|
||||
return sa != NULL;
|
||||
}
|
||||
if (sa->a <= n)
|
||||
return 1;
|
||||
na = 30 + n + (n >> 3);
|
||||
ns = realloc(sa->s, na);
|
||||
if (ns == NULL)
|
||||
return 0;
|
||||
memset(ns + sa->len, 0, na - sa->len);
|
||||
sa->a = na;
|
||||
sa->s = ns;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int stralloc_starts(stralloc *sa, const char *s) {
|
||||
size_t len;
|
||||
assert(sa != NULL);
|
||||
assert(s != NULL);
|
||||
len = strlen(s);
|
||||
return (sa->len >= len) && memcmp(sa->s, s, len);
|
||||
}
|
||||
|
||||
int stralloc_copyb(stralloc *sa, const char *s, size_t n) {
|
||||
assert(sa != NULL);
|
||||
assert(s != NULL);
|
||||
if (!stralloc_ready(sa, n + 1)) return 0;
|
||||
memmove(sa->s, s, n);
|
||||
sa->len = n;
|
||||
sa->s[n] = 'Z'; /* ``offensive programming'' */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int stralloc_catb(stralloc *sa, const char *s, size_t n) {
|
||||
assert(sa != NULL);
|
||||
assert(s != NULL);
|
||||
if (sa->s == NULL) return stralloc_copyb(sa,s,n);
|
||||
if (!stralloc_readyplus(sa, n + 1)) return 0;
|
||||
memmove(sa->s + sa->len, s, n);
|
||||
sa->len += n;
|
||||
sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int stralloc_append1(stralloc *sa, char b) {
|
||||
assert(sa != NULL);
|
||||
if (!stralloc_readyplus(sa, 1)) return 0;
|
||||
sa->s[sa->len++] = b;
|
||||
return 1;
|
||||
}
|
49
src/stralloc/stralloc.h
Normal file
49
src/stralloc/stralloc.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef STRALLOC_H
|
||||
#define STRALLOC_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct stralloc stralloc;
|
||||
struct stralloc {
|
||||
char *s;
|
||||
size_t len;
|
||||
size_t a;
|
||||
};
|
||||
|
||||
extern int stralloc_ready(stralloc *sa, size_t n);
|
||||
extern int stralloc_starts(stralloc *sa, const char *s);
|
||||
extern int stralloc_copyb(stralloc *sa, const char *s, size_t n);
|
||||
extern int stralloc_catb(stralloc *sa, const char *s, size_t n);
|
||||
extern int stralloc_append1(stralloc *sa, char b);
|
||||
|
||||
static inline int stralloc_readyplus(stralloc *sa, size_t n) {
|
||||
assert(sa != NULL);
|
||||
return stralloc_ready(sa, sa->len + n);
|
||||
}
|
||||
|
||||
static inline int stralloc_copy(stralloc *to, const stralloc *from) {
|
||||
assert(from != NULL);
|
||||
return stralloc_copyb(to, from->s, from->len);
|
||||
}
|
||||
|
||||
static inline int stralloc_cat(stralloc *to, const stralloc *from) {
|
||||
assert(from != NULL);
|
||||
return stralloc_catb(to, from->s, from->len);
|
||||
}
|
||||
|
||||
static inline int stralloc_copys(stralloc *sa, const char *s) {
|
||||
assert(s != NULL);
|
||||
return stralloc_copyb(sa, s, strlen(s));
|
||||
}
|
||||
|
||||
static inline int stralloc_cats(stralloc *sa, const char *s) {
|
||||
return stralloc_catb(sa, s, strlen(s));
|
||||
}
|
||||
|
||||
static inline int stralloc_0(stralloc *sa) {
|
||||
return stralloc_append1(sa, '\0');
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user