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:
parent
12b38ad9e1
commit
bff128fea9
6
defs.h
6
defs.h
@ -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
64
misc.c
@ -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
7
misc.h
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user