summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-06-15 16:07:08 -0700
committerJoshua Haberman <joshua@reverberate.org>2009-06-15 16:07:08 -0700
commitbc717d84023eadd0fe94668f4034e4a09e4be9c9 (patch)
tree096101da08c88808df5e8431ded8f47fde0a47a3
parentccca4d71360776f5589312525b2397c84ad0096d (diff)
Implement inlining that works with both C99 and all versions of GCC.
-rw-r--r--Makefile3
-rw-r--r--upb.h10
-rw-r--r--upb_parse.c2
-rw-r--r--upb_parse.h2
-rw-r--r--upb_struct.c40
-rw-r--r--upb_struct.h57
-rw-r--r--upb_table.h8
7 files changed, 48 insertions, 74 deletions
diff --git a/Makefile b/Makefile
index da620fe..a95652a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,8 @@
.PHONY: all clean
CC=gcc
-CFLAGS=-std=c99
+CXX=g++
+CFLAGS=-std=c99 -fgnu89-inline
CPPFLAGS=-O3 -Wall -Wextra -pedantic -g
OBJ=upb_parse.o upb_table.o upb_struct.o descriptor.o
all: $(OBJ) test_table
diff --git a/upb.h b/upb.h
index b09a39c..ae1845a 100644
--- a/upb.h
+++ b/upb.h
@@ -15,6 +15,16 @@
extern "C" {
#endif
+/* Portable inlining strategy: use C99 rules except on GCC.
+ * see: http://www.greenend.org.uk/rjk/2003/03/inline.html. */
+#ifndef INLINE
+# if __GNUC__ && !__GNUC_STDC_INLINE__
+# define INLINE extern inline
+# else
+# define INLINE inline
+# endif
+#endif
+
/* The maximum that any submessages can be nested. Matches proto2's limit. */
#define UPB_MAX_NESTING 64
diff --git a/upb_parse.c b/upb_parse.c
index 458876e..3dac5eb 100644
--- a/upb_parse.c
+++ b/upb_parse.c
@@ -4,6 +4,7 @@
* Copyright (c) 2008-2009 Joshua Haberman. See LICENSE for details.
*/
+#define INLINE
#include "upb_parse.h"
#include <assert.h>
@@ -262,4 +263,3 @@ upb_status_t upb_parse_value(uint8_t **b, upb_field_type_t ft,
}
#undef CASE
}
-
diff --git a/upb_parse.h b/upb_parse.h
index 829e97c..068d522 100644
--- a/upb_parse.h
+++ b/upb_parse.h
@@ -27,7 +27,7 @@ upb_status_t parse_tag(uint8_t **buf, struct upb_tag *tag);
extern upb_wire_type_t upb_expected_wire_types[];
/* Returns true if wt is the correct on-the-wire type for ft. */
-inline bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) {
+INLINE bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) {
return upb_expected_wire_types[ft] == wt;
}
diff --git a/upb_struct.c b/upb_struct.c
index 3284796..e312183 100644
--- a/upb_struct.c
+++ b/upb_struct.c
@@ -1,45 +1,7 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
- * Definitions that will emit code for inline functions, per C99 inlining
- * rules (see http://www.greenend.org.uk/rjk/2003/03/inline.html).
*/
+#define INLINE
#include "upb_struct.h"
-
-#define UPB_DECLARE_ACCESSORS(ctype, name) \
- extern ctype *upb_struct_get_ ## name ## _ptr( \
- uint8_t *s, struct upb_struct_field *f); \
- extern ctype upb_struct_get_ ## name( \
- uint8_t *s, struct upb_struct_field *f); \
- extern void upb_struct_set_ ## name( \
- uint8_t *s, struct upb_struct_field *f, ctype val);
-
-#define UPB_DECLARE_ARRAY_ACCESSORS(ctype, name) \
- extern ctype *upb_array_get_ ## name ## _ptr(struct upb_array *a, int n); \
- extern ctype upb_array_get_ ## name(struct upb_array *a, int n); \
- extern void upb_array_set_ ## name(struct upb_array *a, int n, ctype val);
-
-#define UPB_DECLARE_ALL_ACCESSORS(ctype, name) \
- UPB_DECLARE_ACCESSORS(ctype, name) \
- UPB_DECLARE_ARRAY_ACCESSORS(ctype, name)
-
-UPB_DECLARE_ALL_ACCESSORS(double, double)
-UPB_DECLARE_ALL_ACCESSORS(float, float)
-UPB_DECLARE_ALL_ACCESSORS(int32_t, int32)
-UPB_DECLARE_ALL_ACCESSORS(int64_t, int64)
-UPB_DECLARE_ALL_ACCESSORS(uint32_t, uint32)
-UPB_DECLARE_ALL_ACCESSORS(uint64_t, uint64)
-UPB_DECLARE_ALL_ACCESSORS(bool, bool)
-UPB_DECLARE_ALL_ACCESSORS(struct upb_struct_delimited*, bytes)
-UPB_DECLARE_ALL_ACCESSORS(struct upb_struct_delimited*, string)
-UPB_DECLARE_ALL_ACCESSORS(uint8_t*, substruct)
-UPB_DECLARE_ACCESSORS(struct upb_array*, array)
-
-extern void upb_struct_set(uint8_t *s, struct upb_struct_field *f);
-extern void upb_struct_unset(uint8_t *s, struct upb_struct_field *f);
-extern bool upb_struct_is_set(uint8_t *s, struct upb_struct_field *f);
-extern bool upb_struct_all_required_fields_set(
- uint8_t *s, struct upb_struct_definition *d);
-extern void upb_struct_clear(uint8_t *s, struct upb_struct_definition *d);
-
diff --git a/upb_struct.h b/upb_struct.h
index 7d5c219..c43fdca 100644
--- a/upb_struct.h
+++ b/upb_struct.h
@@ -29,6 +29,7 @@
#ifndef PBSTRUCT_H_
#define PBSTRUCT_H_
+#include "upb.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -134,67 +135,67 @@ UPB_DEFINE_PRIMITIVE_ARRAY(bool, bool)
*
* These do no existence checks, bounds checks, or type checks. */
-#define UPB_DEFINE_ACCESSORS(ctype, name) \
- inline ctype *upb_struct_get_ ## name ## _ptr( \
+#define UPB_DEFINE_ACCESSORS(ctype, name, INLINE) \
+ INLINE ctype *upb_struct_get_ ## name ## _ptr( \
uint8_t *s, struct upb_struct_field *f) { \
return (ctype*)(s + f->byte_offset); \
} \
- inline ctype upb_struct_get_ ## name( \
+ INLINE ctype upb_struct_get_ ## name( \
uint8_t *s, struct upb_struct_field *f) { \
return *upb_struct_get_ ## name ## _ptr(s, f); \
} \
- inline void upb_struct_set_ ## name( \
+ INLINE void upb_struct_set_ ## name( \
uint8_t *s, struct upb_struct_field *f, ctype val) { \
*upb_struct_get_ ## name ## _ptr(s, f) = val; \
}
-#define UPB_DEFINE_ARRAY_ACCESSORS(ctype, name) \
- inline ctype *upb_array_get_ ## name ## _ptr(struct upb_array *a, int n) { \
+#define UPB_DEFINE_ARRAY_ACCESSORS(ctype, name, INLINE) \
+ INLINE ctype *upb_array_get_ ## name ## _ptr(struct upb_array *a, int n) { \
return ((ctype*)a->data) + n; \
} \
- inline ctype upb_array_get_ ## name(struct upb_array *a, int n) { \
+ INLINE ctype upb_array_get_ ## name(struct upb_array *a, int n) { \
return *upb_array_get_ ## name ## _ptr(a, n); \
} \
- inline void upb_array_set_ ## name(struct upb_array *a, int n, ctype val) { \
+ INLINE void upb_array_set_ ## name(struct upb_array *a, int n, ctype val) { \
*upb_array_get_ ## name ## _ptr(a, n) = val; \
}
-#define UPB_DEFINE_ALL_ACCESSORS(ctype, name) \
- UPB_DEFINE_ACCESSORS(ctype, name) \
- UPB_DEFINE_ARRAY_ACCESSORS(ctype, name)
-
-UPB_DEFINE_ALL_ACCESSORS(double, double)
-UPB_DEFINE_ALL_ACCESSORS(float, float)
-UPB_DEFINE_ALL_ACCESSORS(int32_t, int32)
-UPB_DEFINE_ALL_ACCESSORS(int64_t, int64)
-UPB_DEFINE_ALL_ACCESSORS(uint32_t, uint32)
-UPB_DEFINE_ALL_ACCESSORS(uint64_t, uint64)
-UPB_DEFINE_ALL_ACCESSORS(bool, bool)
-UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, bytes)
-UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, string)
-UPB_DEFINE_ALL_ACCESSORS(uint8_t*, substruct)
-UPB_DEFINE_ACCESSORS(struct upb_array*, array)
+#define UPB_DEFINE_ALL_ACCESSORS(ctype, name, INLINE) \
+ UPB_DEFINE_ACCESSORS(ctype, name, INLINE) \
+ UPB_DEFINE_ARRAY_ACCESSORS(ctype, name, INLINE)
+
+UPB_DEFINE_ALL_ACCESSORS(double, double, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(float, float, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(int32_t, int32, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(int64_t, int64, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(uint32_t, uint32, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(uint64_t, uint64, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(bool, bool, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, bytes, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(struct upb_struct_delimited*, string, INLINE)
+UPB_DEFINE_ALL_ACCESSORS(uint8_t*, substruct, INLINE)
+UPB_DEFINE_ACCESSORS(struct upb_array*, array, INLINE)
/* Functions for reading and writing the "set" flags in the pbstruct. Note
* that these do not perform any memory management associated with any dynamic
* memory these fields may be referencing; that is the client's responsibility.
* These *only* set and test the flags. */
-inline void upb_struct_set(uint8_t *s, struct upb_struct_field *f)
+INLINE void upb_struct_set(uint8_t *s, struct upb_struct_field *f)
{
s[f->isset_byte_offset] |= f->isset_byte_mask;
}
-inline void upb_struct_unset(uint8_t *s, struct upb_struct_field *f)
+INLINE void upb_struct_unset(uint8_t *s, struct upb_struct_field *f)
{
s[f->isset_byte_offset] &= ~f->isset_byte_mask;
}
-inline bool upb_struct_is_set(uint8_t *s, struct upb_struct_field *f)
+INLINE bool upb_struct_is_set(uint8_t *s, struct upb_struct_field *f)
{
return s[f->isset_byte_offset] & f->isset_byte_mask;
}
-inline bool upb_struct_all_required_fields_set(
+INLINE bool upb_struct_all_required_fields_set(
uint8_t *s, struct upb_struct_definition *d)
{
int num_fields = d->num_required_fields;
@@ -207,7 +208,7 @@ inline bool upb_struct_all_required_fields_set(
return true;
}
-inline void upb_struct_clear(uint8_t *s, struct upb_struct_definition *d)
+INLINE void upb_struct_clear(uint8_t *s, struct upb_struct_definition *d)
{
memset(s, 0, d->set_flags_bytes);
}
diff --git a/upb_table.h b/upb_table.h
index 5a23ae5..93945c7 100644
--- a/upb_table.h
+++ b/upb_table.h
@@ -42,26 +42,26 @@ void upb_inttable_init(struct upb_inttable *table, void *entries,
/* Frees any data that was allocated by upb_inttable_init. */
void upb_inttable_free(struct upb_inttable *table);
-inline struct upb_inttable_entry *upb_inttable_entry_get(
+INLINE struct upb_inttable_entry *upb_inttable_entry_get(
void *entries, int32_t pos, int entry_size) {
return (struct upb_inttable_entry*)(((char*)entries) + pos*entry_size);
}
-inline struct upb_inttable_entry *upb_inttable_mainpos2(
+INLINE struct upb_inttable_entry *upb_inttable_mainpos2(
struct upb_inttable *table, upb_inttable_key_t key, int32_t entry_size) {
/* Identity hash for integers. */
int32_t pos = key & (table->size-1);
return upb_inttable_entry_get(table->entries, pos, entry_size);
}
-inline struct upb_inttable_entry *upb_inttable_mainpos(
+INLINE struct upb_inttable_entry *upb_inttable_mainpos(
struct upb_inttable *table, upb_inttable_key_t key) {
return upb_inttable_mainpos2(table, key, table->entry_size);
}
/* Lookups up key in this table. Inlined because this is in the critical path
* of parsing. */
-inline void *upb_inttable_lookup(struct upb_inttable *table,
+INLINE void *upb_inttable_lookup(struct upb_inttable *table,
int32_t key,
int32_t entry_size) {
/* TODO: experiment with Cuckoo Hashing, which can perform lookups without
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback