1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Make strbuf a less opaque type.

Now, instead of being a black box that you shovel strings into and
eventually extract a final answer, it exposes enough structure fields
to the world that you can append things to it _and_ look inside its
current contents. For convenience, it exports its internal pointer as
both a char * and an unsigned char *.
This commit is contained in:
Simon Tatham 2018-05-24 14:55:10 +01:00
parent 12b38ad9e1
commit bff128fea9
3 changed files with 55 additions and 22 deletions

6
defs.h
View File

@ -34,4 +34,10 @@ typedef uint32_t uint32;
#define TYPECHECK(to_check, to_return) \ #define TYPECHECK(to_check, to_return) \
(sizeof(to_check) ? (to_return) : (to_return)) (sizeof(to_check) ? (to_return) : (to_return))
/* Return a pointer to the object of structure type 'type' whose field
* with name 'field' is pointed at by 'object'. */
#define FROMFIELD(object, type, field) \
TYPECHECK(object == &((type *)0)->field, \
((type *)(((char *)(object)) - offsetof(type, field))))
#endif /* PUTTY_DEFS_H */ #endif /* PUTTY_DEFS_H */

64
misc.c
View File

@ -466,44 +466,66 @@ char *dupprintf(const char *fmt, ...)
return ret; return ret;
} }
struct strbuf { struct strbuf_impl {
char *s; int size;
int len, size; struct strbuf visible;
}; };
#define STRBUF_SET_PTR(buf, ptr) \
((buf)->visible.s = (ptr), \
(buf)->visible.u = (unsigned char *)(buf)->visible.s)
char *strbuf_append(strbuf *buf_o, size_t len)
{
struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
char *toret;
if (buf->size < buf->visible.len + len + 1) {
buf->size = (buf->visible.len + len + 1) * 5 / 4 + 512;
STRBUF_SET_PTR(buf, sresize(buf->visible.s, buf->size, char));
}
toret = buf->visible.s + buf->visible.len;
buf->visible.len += len;
buf->visible.s[buf->visible.len] = '\0';
return toret;
}
strbuf *strbuf_new(void) strbuf *strbuf_new(void)
{ {
strbuf *buf = snew(strbuf); struct strbuf_impl *buf = snew(struct strbuf_impl);
buf->len = 0; buf->visible.len = 0;
buf->size = 512; buf->size = 512;
buf->s = snewn(buf->size, char); STRBUF_SET_PTR(buf, snewn(buf->size, char));
*buf->s = '\0'; *buf->visible.s = '\0';
return buf; return &buf->visible;
} }
void strbuf_free(strbuf *buf) void strbuf_free(strbuf *buf_o)
{ {
sfree(buf->s); struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
if (buf->visible.s) {
smemclr(buf->visible.s, buf->size);
sfree(buf->visible.s);
}
sfree(buf); sfree(buf);
} }
char *strbuf_str(strbuf *buf) char *strbuf_to_str(strbuf *buf_o)
{ {
return buf->s; struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
} char *ret = buf->visible.s;
char *strbuf_to_str(strbuf *buf)
{
char *ret = buf->s;
sfree(buf); sfree(buf);
return ret; return ret;
} }
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap) void strbuf_catfv(strbuf *buf_o, const char *fmt, va_list ap)
{ {
buf->s = dupvprintf_inner(buf->s, buf->len, &buf->size, fmt, ap); struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
buf->len += strlen(buf->s + buf->len); STRBUF_SET_PTR(buf, dupvprintf_inner(buf->visible.s, buf->visible.len,
&buf->size, fmt, ap));
buf->visible.len += strlen(buf->visible.s + buf->visible.len);
} }
void strbuf_catf(strbuf *buf, const char *fmt, ...) void strbuf_catf(strbuf *buf_o, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strbuf_catfv(buf, fmt, ap); strbuf_catfv(buf_o, fmt, ap);
va_end(ap); va_end(ap);
} }

7
misc.h
View File

@ -37,9 +37,14 @@ char *dupprintf(const char *fmt, ...)
char *dupvprintf(const char *fmt, va_list ap); char *dupvprintf(const char *fmt, va_list ap);
void burnstr(char *string); void burnstr(char *string);
struct strbuf {
char *s;
unsigned char *u;
int len;
/* (also there's a surrounding implementation struct in misc.c) */
};
strbuf *strbuf_new(void); strbuf *strbuf_new(void);
void strbuf_free(strbuf *buf); void strbuf_free(strbuf *buf);
char *strbuf_str(strbuf *buf); /* does not free buf */
char *strbuf_to_str(strbuf *buf); /* does free buf, but you must free result */ char *strbuf_to_str(strbuf *buf); /* does free buf, but you must free result */
void strbuf_catf(strbuf *buf, const char *fmt, ...); void strbuf_catf(strbuf *buf, const char *fmt, ...);
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap); void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap);