Fleshed out upb_string further. Now upb_def's only

unresolved references are upb_src.
pull/13171/head
Joshua Haberman 15 years ago
parent e29bf964d1
commit 2ef013126c
  1. 3
      Makefile
  2. 11
      core/upb_def.c
  3. 30
      core/upb_string.c
  4. 46
      core/upb_string.h
  5. 17
      tests/test_string.c

@ -87,7 +87,8 @@ tests/test.proto.pb: tests/test.proto
protoc tests/test.proto -otests/test.proto.pb protoc tests/test.proto -otests/test.proto.pb
TESTS=tests/test_string \ TESTS=tests/test_string \
tests/test_table tests/test_table \
tests/test_def
tests: $(TESTS) tests: $(TESTS)
OTHER_TESTS=tests/tests \ OTHER_TESTS=tests/tests \

@ -44,13 +44,12 @@ static void upb_deflist_push(upb_deflist *l, upb_def *d) {
* join("", "Baz") -> "Baz" * join("", "Baz") -> "Baz"
* Caller owns a ref on the returned string. */ * Caller owns a ref on the returned string. */
static upb_string *upb_join(upb_string *base, upb_string *name) { static upb_string *upb_join(upb_string *base, upb_string *name) {
upb_string *joined = upb_strdup(base); if (upb_string_len(base) == 0) {
upb_strlen_t len = upb_string_len(joined); return upb_string_getref(name);
if(len > 0) { } else {
upb_string_getrwbuf(joined, len + 1)[len] = UPB_SYMBOL_SEPARATOR; return upb_string_asprintf(UPB_STRFMT "." UPB_STRFMT,
UPB_STRARG(base), UPB_STRARG(name));
} }
upb_strcat(joined, name);
return joined;
} }
// Qualify the defname for all defs starting with offset "start" with "str". // Qualify the defname for all defs starting with offset "start" with "str".

@ -82,7 +82,7 @@ char *upb_string_getrwbuf(upb_string *str, upb_strlen_t len) {
} }
str->len = len; str->len = len;
str->ptr = str->cached_mem; str->ptr = str->cached_mem;
return str->ptr; return str->cached_mem;
} }
void upb_string_substr(upb_string *str, upb_string *target_str, void upb_string_substr(upb_string *str, upb_string *target_str,
@ -92,3 +92,31 @@ void upb_string_substr(upb_string *str, upb_string *target_str,
str->ptr = upb_string_getrobuf(target_str) + start; str->ptr = upb_string_getrobuf(target_str) + start;
str->len = len; str->len = len;
} }
void upb_string_vprintf(upb_string *str, const char *format, va_list args) {
// Try once without reallocating. We have to va_copy because we might have
// to call vsnprintf again.
uint32_t size = UPB_MAX(upb_string_size(str), 16);
char *buf = upb_string_getrwbuf(str, size);
va_list args_copy;
va_copy(args_copy, args);
uint32_t true_size = vsnprintf(buf, size, format, args_copy);
va_end(args_copy);
if (true_size > size) {
// Need to reallocate.
str = upb_string_tryrecycle(str);
buf = upb_string_getrwbuf(str, true_size);
vsnprintf(buf, true_size, format, args);
}
str->len = true_size;
}
upb_string *upb_string_asprintf(const char *format, ...) {
upb_string *str = upb_string_new();
va_list args;
va_start(args, format);
upb_string_vprintf(str, format, args);
va_end(args);
return str;
}

@ -25,6 +25,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include "upb_atomic.h" #include "upb_atomic.h"
#include "upb.h" #include "upb.h"
@ -37,7 +38,7 @@ extern "C" {
struct _upb_string { struct _upb_string {
// The pointer to our currently active data. This may be memory we own // The pointer to our currently active data. This may be memory we own
// or a pointer into memory we don't own. // or a pointer into memory we don't own.
char *ptr; const char *ptr;
// If non-NULL, this is a block of memory we own. We keep this cached even // If non-NULL, this is a block of memory we own. We keep this cached even
// if "ptr" is currently aliasing memory we don't own. // if "ptr" is currently aliasing memory we don't own.
@ -111,16 +112,25 @@ INLINE void upb_string_endread(upb_string *str) { (void)str; }
// } // }
upb_string *upb_string_tryrecycle(upb_string *str); upb_string *upb_string_tryrecycle(upb_string *str);
// The three options for setting the contents of a string. These may only be // The options for setting the contents of a string. These may only be called
// called when a string is first created or recycled; once other functions have // when a string is first created or recycled; once other functions have been
// been called on the string, these functions are not allowed until the string // called on the string, these functions are not allowed until the string is
// is recycled. // recycled.
// Gets a pointer suitable for writing to the string, which is guaranteed to // Gets a pointer suitable for writing to the string, which is guaranteed to
// have at least "len" bytes of data available. The size of the string will // have at least "len" bytes of data available. The size of the string will
// become "len". // become "len".
char *upb_string_getrwbuf(upb_string *str, upb_strlen_t len); char *upb_string_getrwbuf(upb_string *str, upb_strlen_t len);
// Replaces the contents of str with the contents of the given printf.
void upb_string_vprintf(upb_string *str, const char *format, va_list args);
INLINE void upb_string_printf(upb_string *str, const char *format, ...) {
va_list args;
va_start(args, format);
upb_string_vprintf(str, format, args);
va_end(args);
}
// Sets the contents of "str" to be the given substring of "target_str", to // Sets the contents of "str" to be the given substring of "target_str", to
// which the caller must own a ref. // which the caller must own a ref.
void upb_string_substr(upb_string *str, upb_string *target_str, void upb_string_substr(upb_string *str, upb_string *target_str,
@ -144,7 +154,7 @@ void upb_string_substr(upb_string *str, upb_string *target_str,
/* upb_string library functions ***********************************************/ /* upb_string library functions ***********************************************/
// Named like their <string.h> counterparts, these are all safe against buffer // Named like their <string.h> counterparts, these are all safe against buffer
// overflow. These only use the public upb_string interface. // overflow. For the most part these only use the public upb_string interface.
// More efficient than upb_strcmp if all you need is to test equality. // More efficient than upb_strcmp if all you need is to test equality.
INLINE bool upb_streql(upb_string *s1, upb_string *s2) { INLINE bool upb_streql(upb_string *s1, upb_string *s2) {
@ -163,6 +173,17 @@ INLINE bool upb_streql(upb_string *s1, upb_string *s2) {
// Like strcmp(). // Like strcmp().
int upb_strcmp(upb_string *s1, upb_string *s2); int upb_strcmp(upb_string *s1, upb_string *s2);
// Compare a upb_string with memory or a NULL-terminated C string.
INLINE bool upb_streqllen(upb_string *str, const void *buf, upb_strlen_t len) {
return len == upb_string_len(str) &&
memcmp(upb_string_getrobuf(str), buf, len) == 0;
}
INLINE bool upb_streqlc(upb_string *str, const void *buf) {
// Could be made one-pass.
return upb_streqllen(str, buf, strlen((const char*)buf));
}
// Like upb_strcpy, but copies from a buffer and length. // Like upb_strcpy, but copies from a buffer and length.
INLINE void upb_strcpylen(upb_string *dest, const void *src, upb_strlen_t len) { INLINE void upb_strcpylen(upb_string *dest, const void *src, upb_strlen_t len) {
memcpy(upb_string_getrwbuf(dest, len), src, len); memcpy(upb_string_getrwbuf(dest, len), src, len);
@ -175,10 +196,10 @@ INLINE void upb_strcpy(upb_string *dest, upb_string *src) {
} }
// Like upb_strcpy, but copies from a NULL-terminated string. // Like upb_strcpy, but copies from a NULL-terminated string.
INLINE void upb_strcpyc(upb_string *dest, const char *src) { INLINE void upb_strcpyc(upb_string *dest, const void *src) {
// This does two passes over src, but that is necessary unless we want to // This does two passes over src, but that is necessary unless we want to
// repeatedly re-allocate dst, which seems worse. // repeatedly re-allocate dst, which seems worse.
upb_strcpylen(dest, src, strlen(src)); upb_strcpylen(dest, src, strlen((const char*)src));
} }
// Returns a new string whose contents are a copy of s. // Returns a new string whose contents are a copy of s.
@ -200,11 +221,18 @@ INLINE upb_string *upb_strdupc(const char *src) {
void upb_strcat(upb_string *s, upb_string *append); void upb_strcat(upb_string *s, upb_string *append);
// Returns a new string that is a substring of the given string. // Returns a new string that is a substring of the given string.
upb_string *upb_strslice(upb_string *s, int offset, int len); INLINE upb_string *upb_strslice(upb_string *s, int offset, int len) {
upb_string *str = upb_string_new();
upb_string_substr(str, s, offset, len);
return str;
}
// Reads an entire file into a newly-allocated string. // Reads an entire file into a newly-allocated string.
upb_string *upb_strreadfile(const char *filename); upb_string *upb_strreadfile(const char *filename);
// Returns a new string with the contents of the given printf.
upb_string *upb_string_asprintf(const char *format, ...);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif

@ -17,7 +17,7 @@ int main() {
assert(upb_string_len(str) == (sizeof(static_str) - 1)); assert(upb_string_len(str) == (sizeof(static_str) - 1));
const char *robuf = upb_string_getrobuf(str); const char *robuf = upb_string_getrobuf(str);
assert(robuf != NULL); assert(robuf != NULL);
assert(memcmp(robuf, static_str, upb_string_len(str)) == 0); assert(upb_streqlc(str, static_str));
upb_string_endread(str); upb_string_endread(str);
upb_string *str2 = upb_string_tryrecycle(str); upb_string *str2 = upb_string_tryrecycle(str);
@ -28,7 +28,7 @@ int main() {
upb_strcpyc(str, "XX"); upb_strcpyc(str, "XX");
const char *robuf2 = upb_string_getrobuf(str); const char *robuf2 = upb_string_getrobuf(str);
assert(robuf2 == robuf); assert(robuf2 == robuf);
assert(memcmp(robuf2, "XX", 2) == 0); assert(upb_streqlc(str, "XX"));
// Make string alias part of another string. // Make string alias part of another string.
str2 = upb_strdupc("WXYZ"); str2 = upb_strdupc("WXYZ");
@ -51,6 +51,19 @@ int main() {
const char *robuf5 = upb_string_getrobuf(str); const char *robuf5 = upb_string_getrobuf(str);
assert(robuf5 == robuf); assert(robuf5 == robuf);
// Resetting str to something very long should require new data to be
// allocated.
str = upb_string_tryrecycle(str);
const char longstring[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
upb_strcpyc(str, longstring);
const char *robuf6 = upb_string_getrobuf(str);
assert(robuf6 != robuf);
assert(upb_streqlc(str, longstring));
// Test printf.
str = upb_string_tryrecycle(str);
upb_string_printf(str, "Number: %d, String: %s", 5, "YO!");
upb_string_unref(str); upb_string_unref(str);
upb_string_unref(str2); upb_string_unref(str2);
} }

Loading…
Cancel
Save