1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +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) \
(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 */

64
misc.c
View File

@ -466,44 +466,66 @@ char *dupprintf(const char *fmt, ...)
return ret;
}
struct strbuf {
char *s;
int len, size;
struct strbuf_impl {
int 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 *buf = snew(strbuf);
buf->len = 0;
struct strbuf_impl *buf = snew(struct strbuf_impl);
buf->visible.len = 0;
buf->size = 512;
buf->s = snewn(buf->size, char);
*buf->s = '\0';
return buf;
STRBUF_SET_PTR(buf, snewn(buf->size, char));
*buf->visible.s = '\0';
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);
}
char *strbuf_str(strbuf *buf)
char *strbuf_to_str(strbuf *buf_o)
{
return buf->s;
}
char *strbuf_to_str(strbuf *buf)
{
char *ret = buf->s;
struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
char *ret = buf->visible.s;
sfree(buf);
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);
buf->len += strlen(buf->s + buf->len);
struct strbuf_impl *buf = FROMFIELD(buf_o, struct strbuf_impl, visible);
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_start(ap, fmt);
strbuf_catfv(buf, fmt, ap);
strbuf_catfv(buf_o, fmt, 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);
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);
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 */
void strbuf_catf(strbuf *buf, const char *fmt, ...);
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap);