summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2010-07-10 13:28:47 -0700
committerJoshua Haberman <joshua@reverberate.org>2010-07-10 13:28:47 -0700
commit2ef013126c682a44d15554ea7a04144fc9a10fed (patch)
treec7657b6749518d5374069755fc2f44380b2d3a2e
parente29bf964d1716398e8354a50f506906a307298e5 (diff)
Fleshed out upb_string further. Now upb_def's only
unresolved references are upb_src.
-rw-r--r--Makefile3
-rw-r--r--core/upb_def.c11
-rw-r--r--core/upb_string.c30
-rw-r--r--core/upb_string.h46
-rw-r--r--tests/test_string.c17
5 files changed, 88 insertions, 19 deletions
diff --git a/Makefile b/Makefile
index 1f977b4..2abe0c7 100644
--- a/Makefile
+++ b/Makefile
@@ -87,7 +87,8 @@ tests/test.proto.pb: tests/test.proto
protoc tests/test.proto -otests/test.proto.pb
TESTS=tests/test_string \
- tests/test_table
+ tests/test_table \
+ tests/test_def
tests: $(TESTS)
OTHER_TESTS=tests/tests \
diff --git a/core/upb_def.c b/core/upb_def.c
index bfab738..1f57c70 100644
--- a/core/upb_def.c
+++ b/core/upb_def.c
@@ -44,13 +44,12 @@ static void upb_deflist_push(upb_deflist *l, upb_def *d) {
* join("", "Baz") -> "Baz"
* Caller owns a ref on the returned string. */
static upb_string *upb_join(upb_string *base, upb_string *name) {
- upb_string *joined = upb_strdup(base);
- upb_strlen_t len = upb_string_len(joined);
- if(len > 0) {
- upb_string_getrwbuf(joined, len + 1)[len] = UPB_SYMBOL_SEPARATOR;
+ if (upb_string_len(base) == 0) {
+ return upb_string_getref(name);
+ } else {
+ 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".
diff --git a/core/upb_string.c b/core/upb_string.c
index f9af9e9..2f487aa 100644
--- a/core/upb_string.c
+++ b/core/upb_string.c
@@ -82,7 +82,7 @@ char *upb_string_getrwbuf(upb_string *str, upb_strlen_t len) {
}
str->len = len;
str->ptr = str->cached_mem;
- return str->ptr;
+ return str->cached_mem;
}
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->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;
+}
diff --git a/core/upb_string.h b/core/upb_string.h
index 7ec3d48..5cc0eaf 100644
--- a/core/upb_string.h
+++ b/core/upb_string.h
@@ -25,6 +25,7 @@
#include <assert.h>
#include <string.h>
+#include <stdarg.h>
#include "upb_atomic.h"
#include "upb.h"
@@ -37,7 +38,7 @@ extern "C" {
struct _upb_string {
// The pointer to our currently active data. This may be memory we 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 "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);
-// The three options for setting the contents of a string. These may only be
-// called when a string is first created or recycled; once other functions have
-// been called on the string, these functions are not allowed until the string
-// is recycled.
+// The options for setting the contents of a string. These may only be called
+// when a string is first created or recycled; once other functions have been
+// called on the string, these functions are not allowed until the string is
+// recycled.
// 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
// become "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
// which the caller must own a ref.
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 ***********************************************/
// 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.
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().
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.
INLINE void upb_strcpylen(upb_string *dest, const void *src, upb_strlen_t 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.
-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
// 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.
@@ -200,11 +221,18 @@ INLINE upb_string *upb_strdupc(const char *src) {
void upb_strcat(upb_string *s, upb_string *append);
// 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.
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
} /* extern "C" */
#endif
diff --git a/tests/test_string.c b/tests/test_string.c
index 4fdab6c..5e6e2a9 100644
--- a/tests/test_string.c
+++ b/tests/test_string.c
@@ -17,7 +17,7 @@ int main() {
assert(upb_string_len(str) == (sizeof(static_str) - 1));
const char *robuf = upb_string_getrobuf(str);
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 *str2 = upb_string_tryrecycle(str);
@@ -28,7 +28,7 @@ int main() {
upb_strcpyc(str, "XX");
const char *robuf2 = upb_string_getrobuf(str);
assert(robuf2 == robuf);
- assert(memcmp(robuf2, "XX", 2) == 0);
+ assert(upb_streqlc(str, "XX"));
// Make string alias part of another string.
str2 = upb_strdupc("WXYZ");
@@ -51,6 +51,19 @@ int main() {
const char *robuf5 = upb_string_getrobuf(str);
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(str2);
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback