From 462b26c1cc041a8fa26deb62cf12f1f351a5b2f6 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 8 Jul 2009 12:06:47 -0700 Subject: Directory restructuring. --- src/upb_string.h | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/upb_string.h (limited to 'src/upb_string.h') diff --git a/src/upb_string.h b/src/upb_string.h new file mode 100644 index 0000000..7a05811 --- /dev/null +++ b/src/upb_string.h @@ -0,0 +1,82 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. + + * Defines a delimited (as opposed to null-terminated) string type and some + * library functions for manipulating them. + * + * There are two primary reasons upb uses delimited strings. One is that they + * can be more efficient for some operations because they do not have to scan + * the string to find its length. For example, streql can start by just + * comparing the lengths (very efficient) and scan the strings themselves only + * if the lengths are equal. + * + * More importantly, using delimited strings makes it possible for strings to + * reference substrings of other strings. For example, if I am parsing a + * protobuf I can create a string that references the original protobuf's + * string data. With NULL-termination I would be forced to write a NULL + * into the middle of the protobuf's data, which is less than ideal and in + * some cases not practical or possible. + */ + +#ifndef UPB_STRING_H_ +#define UPB_STRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "upb.h" + +struct upb_string { + /* We expect the data to be 8-bit clean (uint8_t), but char* is such an + * ingrained convention that we follow it. */ + char *ptr; + uint32_t byte_len; +}; + +INLINE bool upb_streql(struct upb_string *s1, struct upb_string *s2) { + return s1->byte_len == s2->byte_len && + memcmp(s1->ptr, s2->ptr, s1->byte_len) == 0; +} + +INLINE void upb_strcpy(struct upb_string *dest, struct upb_string *src) { + memcpy(dest->ptr, src->ptr, dest->byte_len); + dest->byte_len = src->byte_len; +} + +INLINE struct upb_string upb_strdup(struct upb_string s) { + struct upb_string copy; + copy.ptr = (char*)malloc(s.byte_len); + copy.byte_len = s.byte_len; + memcpy(copy.ptr, s.ptr, s.byte_len); + return copy; +} + +INLINE void upb_strfree(struct upb_string s) { + free(s.ptr); +} + +/* Reads an entire file into a newly-allocated string. */ +bool upb_strreadfile(const char *filename, struct upb_string *data); + +/* Allows defining upb_strings as literals, ie: + * struct upb_string str = UPB_STRLIT("Hello, World!\n"); + * Doesn't work with C++ due to lack of struct initializer syntax. + */ +#define UPB_STRLIT(strlit) {.ptr=strlit, .byte_len=sizeof(strlit)-1} + +/* Allows using upb_strings in printf, ie: + * struct upb_string str = UPB_STRLIT("Hello, World!\n"); + * printf("String is: " UPB_STRFMT, UPB_STRARG(str)); */ +#define UPB_STRARG(str) (str).byte_len, (str).ptr +#define UPB_STRFMT "%.*s" + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* UPB_H_ */ -- cgit v1.2.3