2000-08-28 03:27:03 +08:00
|
|
|
/**
|
|
|
|
* \file lib/stringbuf.c
|
|
|
|
*/
|
|
|
|
|
1998-07-26 05:00:26 +08:00
|
|
|
#include "system.h"
|
1997-05-07 23:07:50 +08:00
|
|
|
|
1995-12-14 00:01:36 +08:00
|
|
|
#include "stringbuf.h"
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
1995-12-14 00:01:36 +08:00
|
|
|
|
|
|
|
#define BUF_CHUNK 1024
|
|
|
|
|
2001-05-06 03:28:32 +08:00
|
|
|
struct StringBufRec {
|
|
|
|
/*@owned@*/ char *buf;
|
|
|
|
/*@dependent@*/ char *tail; /* Points to first "free" char */
|
|
|
|
int allocated;
|
|
|
|
int free;
|
|
|
|
};
|
|
|
|
|
2001-04-29 09:05:43 +08:00
|
|
|
/**
|
|
|
|
* Locale insensitive isspace(3).
|
|
|
|
*/
|
|
|
|
/*@unused@*/ static inline int xisspace(int c) {
|
|
|
|
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v');
|
|
|
|
}
|
|
|
|
|
2001-05-06 03:28:32 +08:00
|
|
|
/**
|
|
|
|
* Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
|
2001-06-04 21:55:58 +08:00
|
|
|
* @param p memory to free
|
2001-05-23 22:25:19 +08:00
|
|
|
* @return NULL always
|
2001-05-06 03:28:32 +08:00
|
|
|
*/
|
2001-06-04 21:55:58 +08:00
|
|
|
/*@unused@*/ static inline /*@null@*/ void *
|
2001-09-25 05:53:14 +08:00
|
|
|
_free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies *p @*/
|
2001-06-04 21:55:58 +08:00
|
|
|
{
|
2001-05-23 22:25:19 +08:00
|
|
|
if (p != NULL) free((void *)p);
|
2001-05-06 03:28:32 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1995-12-14 00:01:36 +08:00
|
|
|
|
|
|
|
StringBuf newStringBuf(void)
|
|
|
|
{
|
1999-09-21 11:22:53 +08:00
|
|
|
StringBuf sb = xmalloc(sizeof(struct StringBufRec));
|
1995-12-14 00:01:36 +08:00
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
sb->free = sb->allocated = BUF_CHUNK;
|
|
|
|
sb->buf = xcalloc(sb->allocated, sizeof(*sb->buf));
|
1995-12-14 00:01:36 +08:00
|
|
|
sb->buf[0] = '\0';
|
|
|
|
sb->tail = sb->buf;
|
|
|
|
|
|
|
|
return sb;
|
|
|
|
}
|
|
|
|
|
2001-05-06 03:28:32 +08:00
|
|
|
StringBuf freeStringBuf(StringBuf sb)
|
1995-12-14 00:01:36 +08:00
|
|
|
{
|
2001-05-06 03:28:32 +08:00
|
|
|
if (sb) {
|
|
|
|
sb->buf = _free(sb->buf);
|
|
|
|
sb = _free(sb);
|
1997-10-01 04:23:20 +08:00
|
|
|
}
|
2001-05-06 03:28:32 +08:00
|
|
|
return sb;
|
1995-12-14 00:01:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void truncStringBuf(StringBuf sb)
|
|
|
|
{
|
|
|
|
sb->buf[0] = '\0';
|
|
|
|
sb->tail = sb->buf;
|
|
|
|
sb->free = sb->allocated;
|
|
|
|
}
|
|
|
|
|
1996-07-03 03:16:06 +08:00
|
|
|
void stripTrailingBlanksStringBuf(StringBuf sb)
|
|
|
|
{
|
|
|
|
while (sb->free != sb->allocated) {
|
2001-10-14 03:35:58 +08:00
|
|
|
/*@-moduncon@*/
|
|
|
|
if (! xisspace(*(sb->tail - 1)))
|
1996-07-03 03:16:06 +08:00
|
|
|
break;
|
2001-10-14 03:35:58 +08:00
|
|
|
/*@=moduncon@*/
|
1996-07-03 03:16:06 +08:00
|
|
|
sb->free++;
|
|
|
|
sb->tail--;
|
|
|
|
}
|
|
|
|
sb->tail[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2001-05-06 03:28:32 +08:00
|
|
|
char * getStringBuf(StringBuf sb)
|
1995-12-14 00:01:36 +08:00
|
|
|
{
|
|
|
|
return sb->buf;
|
|
|
|
}
|
|
|
|
|
1999-01-06 07:13:56 +08:00
|
|
|
void appendStringBufAux(StringBuf sb, const char *s, int nl)
|
1995-12-14 00:01:36 +08:00
|
|
|
{
|
|
|
|
int l;
|
|
|
|
|
|
|
|
l = strlen(s);
|
|
|
|
/* If free == l there is no room for NULL terminator! */
|
1996-02-21 06:25:21 +08:00
|
|
|
while ((l + nl + 1) > sb->free) {
|
1995-12-14 00:01:36 +08:00
|
|
|
sb->allocated += BUF_CHUNK;
|
|
|
|
sb->free += BUF_CHUNK;
|
1999-09-21 11:22:53 +08:00
|
|
|
sb->buf = xrealloc(sb->buf, sb->allocated);
|
1995-12-14 00:01:36 +08:00
|
|
|
sb->tail = sb->buf + (sb->allocated - sb->free);
|
|
|
|
}
|
|
|
|
|
2001-09-25 05:53:14 +08:00
|
|
|
/*@-mayaliasunique@*/ /* FIX: shrug */
|
1995-12-14 00:01:36 +08:00
|
|
|
strcpy(sb->tail, s);
|
2001-04-30 06:43:01 +08:00
|
|
|
/*@=mayaliasunique@*/
|
1995-12-14 00:01:36 +08:00
|
|
|
sb->tail += l;
|
|
|
|
sb->free -= l;
|
|
|
|
if (nl) {
|
|
|
|
sb->tail[0] = '\n';
|
|
|
|
sb->tail[1] = '\0';
|
|
|
|
sb->tail++;
|
|
|
|
sb->free--;
|
|
|
|
}
|
|
|
|
}
|