blob: 4a9a448e52c3a9add8c2d4874a8070b34a9717e3 [file] [log] [blame]
/* --- protobuf-c.h: public protobuf c runtime api --- */
/*
* Copyright 2008, Dave Benson.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License
* at http://www.apache.org/licenses/LICENSE-2.0 Unless
* required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef __PROTOBUF_C_RUNTIME_H_
#define __PROTOBUF_C_RUNTIME_H_
#include <stddef.h>
#include <assert.h>
#ifdef __cplusplus
# define PROTOBUF_C_BEGIN_DECLS extern "C" {
# define PROTOBUF_C_END_DECLS }
#else
# define PROTOBUF_C_BEGIN_DECLS
# define PROTOBUF_C_END_DECLS
#endif
/* Define int32_t, int64_t, uint32_t, uint64_t, uint8_t.
Usually, just include <inttypes.h> to do the work.
XXX: should we use stdint.h?
*/
#ifndef PROTOBUF_C_SKIP_INTTYPES_H
# if defined(_MSC_VER)
/* On windows, in ms visual studio, define the types ourselves */
# define int32_t signed __int32
# define uint32_t unsigned __int32
# define int64_t signed __int64
# define uint64_t unsigned __int64
# define uint8_t unsigned char
# else
/* Use the system inttypes.h */
# include <inttypes.h>
# endif
#endif
PROTOBUF_C_BEGIN_DECLS
typedef enum
{
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_LABEL_REPEATED
} ProtobufCLabel;
typedef enum
{
PROTOBUF_C_TYPE_INT32,
PROTOBUF_C_TYPE_SINT32,
PROTOBUF_C_TYPE_SFIXED32,
PROTOBUF_C_TYPE_INT64,
PROTOBUF_C_TYPE_SINT64,
PROTOBUF_C_TYPE_SFIXED64,
PROTOBUF_C_TYPE_UINT32,
PROTOBUF_C_TYPE_FIXED32,
PROTOBUF_C_TYPE_UINT64,
PROTOBUF_C_TYPE_FIXED64,
PROTOBUF_C_TYPE_FLOAT,
PROTOBUF_C_TYPE_DOUBLE,
PROTOBUF_C_TYPE_BOOL,
PROTOBUF_C_TYPE_ENUM,
PROTOBUF_C_TYPE_STRING,
PROTOBUF_C_TYPE_BYTES,
//PROTOBUF_C_TYPE_GROUP, // NOT SUPPORTED
PROTOBUF_C_TYPE_MESSAGE,
} ProtobufCType;
typedef int protobuf_c_boolean;
#define PROTOBUF_C_OFFSETOF(struct, member) offsetof(struct, member)
#define PROTOBUF_C_ASSERT(condition) assert(condition)
#define PROTOBUF_C_ASSERT_NOT_REACHED() assert(0)
typedef struct _ProtobufCBinaryData ProtobufCBinaryData;
struct _ProtobufCBinaryData
{
size_t len;
uint8_t *data;
};
typedef struct _ProtobufCIntRange ProtobufCIntRange; /* private */
/* --- memory management --- */
typedef struct _ProtobufCAllocator ProtobufCAllocator;
struct _ProtobufCAllocator
{
void *(*alloc)(void *allocator_data, size_t size);
void (*free)(void *allocator_data, void *pointer);
void *(*tmp_alloc)(void *allocator_data, size_t size);
unsigned max_alloca;
void *allocator_data;
};
/* This is a configurable allocator.
* By default, it uses the system allocator (meaning malloc() and free()).
* This is typically changed to adapt to frameworks that provide
* some nonstandard allocation functions.
*
* NOTE: you may modify this allocator.
*/
extern ProtobufCAllocator protobuf_c_default_allocator; /* settable */
/* This is the system allocator, meaning it uses malloc() and free().
*
* NOTE: please do NOT modify this allocator.
*/
extern ProtobufCAllocator protobuf_c_system_allocator; /* use malloc, free etc */
/* This is the function that our default allocators call when they
run out-of-memory. The default behavior of this function is to
terminate your program. */
extern void (*protobuf_c_out_of_memory) (void);
/* --- append-only data buffer --- */
typedef struct _ProtobufCBuffer ProtobufCBuffer;
struct _ProtobufCBuffer
{
void (*append)(ProtobufCBuffer *buffer,
size_t len,
const uint8_t *data);
};
/* --- enums --- */
typedef struct _ProtobufCEnumValue ProtobufCEnumValue;
typedef struct _ProtobufCEnumValueIndex ProtobufCEnumValueIndex;
typedef struct _ProtobufCEnumDescriptor ProtobufCEnumDescriptor;
/* ProtobufCEnumValue: this represents a single value of
* an enumeration.
* 'name' is the string identifying this value, as given in the .proto file.
* 'c_name' is the full name of the C enumeration value.
* 'value' is the number assigned to this value, as given in the .proto file.
*/
struct _ProtobufCEnumValue
{
const char *name;
const char *c_name;
int value;
};
/* ProtobufCEnumDescriptor: the represents the enum as a whole,
* with all its values.
* 'magic' is a code we check to ensure that the api is used correctly.
* 'name' is the qualified name (e.g. "namespace.Type").
* 'short_name' is the unqualified name ("Type"), as given in the .proto file.
* 'package_name' is the '.'-separated namespace
* 'n_values' is the number of distinct values.
* 'values' is the array of distinct values.
* 'n_value_names' number of named values (including aliases).
* 'value_names' are the named values (including aliases).
*
* The rest of the values are private essentially.
*
* see also: Use protobuf_c_enum_descriptor_get_value_by_name()
* and protobuf_c_enum_descriptor_get_value() to efficiently
* lookup values in the descriptor.
*/
struct _ProtobufCEnumDescriptor
{
uint32_t magic;
const char *name;
const char *short_name;
const char *c_name;
const char *package_name;
/* sorted by value */
unsigned n_values;
const ProtobufCEnumValue *values;
/* sorted by name */
unsigned n_value_names;
const ProtobufCEnumValueIndex *values_by_name;
/* value-ranges, for faster lookups by number */
unsigned n_value_ranges;
const ProtobufCIntRange *value_ranges;
void *reserved1;
void *reserved2;
void *reserved3;
void *reserved4;
};
/* --- messages --- */
typedef struct _ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
typedef struct _ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
typedef struct _ProtobufCMessage ProtobufCMessage;
typedef void (*ProtobufCMessageInit)(ProtobufCMessage *);
/* ProtobufCFieldDescriptor: description of a single field
* in a message.
* 'name' is the name of the field, as given in the .proto file.
* 'id' is the code representing the field, as given in the .proto file.
* 'label' is one of PROTOBUF_C_LABEL_{REQUIRED,OPTIONAL,REPEATED}
* 'type' is the type of field.
* 'quantifier_offset' is the offset in bytes into the message's C structure
* for this member's "has_MEMBER" field (for optional members) or
* "n_MEMBER" field (for repeated members).
* 'offset' is the offset in bytes into the message's C structure
* for the member itself.
* 'descriptor' is a pointer to a ProtobufC{Enum,Message}Descriptor
* if type is PROTOBUF_C_TYPE_{ENUM,MESSAGE} respectively,
* otherwise NULL.
* 'default_value' is a pointer to a default value for this field,
* where allowed.
*/
struct _ProtobufCFieldDescriptor
{
const char *name;
uint32_t id;
ProtobufCLabel label;
ProtobufCType type;
unsigned quantifier_offset;
unsigned offset;
const void *descriptor; /* for MESSAGE and ENUM types */
const void *default_value; /* or NULL if no default-value */
protobuf_c_boolean packed;
unsigned reserved_flags;
void *reserved2;
void *reserved3;
};
/* ProtobufCMessageDescriptor: description of a message.
*
* 'magic' is a code we check to ensure that the api is used correctly.
* 'name' is the qualified name (e.g. "namespace.Type").
* 'short_name' is the unqualified name ("Type"), as given in the .proto file.
* 'c_name' is the c-formatted name of the structure
* 'package_name' is the '.'-separated namespace
* 'sizeof_message' is the size in bytes of the C structure
* representing an instance of this type of message.
* 'n_fields' is the number of known fields in this message.
* 'fields' is the fields sorted by id number.
* 'fields_sorted_by_name', 'n_field_ranges' and 'field_ranges'
* are used for looking up fields by name and id. (private)
*/
struct _ProtobufCMessageDescriptor
{
uint32_t magic;
const char *name;
const char *short_name;
const char *c_name;
const char *package_name;
size_t sizeof_message;
/* sorted by field-id */
unsigned n_fields;
const ProtobufCFieldDescriptor *fields;
const unsigned *fields_sorted_by_name;
/* ranges, optimization for looking up fields */
unsigned n_field_ranges;
const ProtobufCIntRange *field_ranges;
ProtobufCMessageInit message_init;
void *reserved1;
void *reserved2;
void *reserved3;
};
/* ProtobufCMessage: an instance of a message.
*
* ProtobufCMessage is sort-of a lightweight
* base-class for all messages.
*
* In particular, ProtobufCMessage doesn't have
* any allocation policy associated with it.
* That's because it is common to create ProtobufCMessage's
* on the stack. In fact, we that's what we recommend
* for sending messages (because if you just allocate from the
* stack, then you can't really have a memory leak).
*
* This means that functions like protobuf_c_message_unpack()
* which return a ProtobufCMessage must be paired
* with a free function, like protobuf_c_message_free_unpacked().
*
* 'descriptor' gives the locations and types of the members of message
* 'n_unknown_fields' is the number of fields we didn't recognize.
* 'unknown_fields' are fields we didn't recognize.
*/
typedef struct _ProtobufCMessageUnknownField ProtobufCMessageUnknownField;
struct _ProtobufCMessage
{
const ProtobufCMessageDescriptor *descriptor;
unsigned n_unknown_fields;
ProtobufCMessageUnknownField *unknown_fields;
};
#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL }
/* To pack a message: you have two options:
(1) you can compute the size of the message
using protobuf_c_message_get_packed_size()
then pass protobuf_c_message_pack() a buffer of
that length.
(2) Provide a virtual buffer (a ProtobufCBuffer) to
accept data as we scan through it.
*/
size_t protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
size_t protobuf_c_message_pack (const ProtobufCMessage *message,
uint8_t *out);
size_t protobuf_c_message_pack_to_buffer (const ProtobufCMessage *message,
ProtobufCBuffer *buffer);
ProtobufCMessage *
protobuf_c_message_unpack (const ProtobufCMessageDescriptor *,
ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void protobuf_c_message_free_unpacked (ProtobufCMessage *message,
ProtobufCAllocator *allocator);
/* WARNING: 'message' must be a block of memory
of size descriptor->sizeof_message. */
#define protobuf_c_message_init(descriptor, message) ((descriptor)->message_init((ProtobufCMessage*) (message)))
/* --- services --- */
typedef struct _ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
typedef struct _ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
struct _ProtobufCMethodDescriptor
{
const char *name;
const ProtobufCMessageDescriptor *input;
const ProtobufCMessageDescriptor *output;
};
struct _ProtobufCServiceDescriptor
{
uint32_t magic;
const char *name;
const char *short_name;
const char *c_name;
const char *package;
unsigned n_methods;
const ProtobufCMethodDescriptor *methods; /* in order from .proto file */
const unsigned *method_indices_by_name;
};
typedef struct _ProtobufCService ProtobufCService;
typedef void (*ProtobufCClosure)(const ProtobufCMessage *message,
void *closure_data);
struct _ProtobufCService
{
const ProtobufCServiceDescriptor *descriptor;
void (*invoke)(ProtobufCService *service,
unsigned method_index,
const ProtobufCMessage *input,
ProtobufCClosure closure,
void *closure_data);
void (*destroy) (ProtobufCService *service);
};
void protobuf_c_service_destroy (ProtobufCService *);
/* --- querying the descriptors --- */
const ProtobufCEnumValue *
protobuf_c_enum_descriptor_get_value_by_name
(const ProtobufCEnumDescriptor *desc,
const char *name);
const ProtobufCEnumValue *
protobuf_c_enum_descriptor_get_value
(const ProtobufCEnumDescriptor *desc,
int value);
const ProtobufCFieldDescriptor *
protobuf_c_message_descriptor_get_field_by_name
(const ProtobufCMessageDescriptor *desc,
const char *name);
const ProtobufCFieldDescriptor *
protobuf_c_message_descriptor_get_field
(const ProtobufCMessageDescriptor *desc,
unsigned value);
const ProtobufCMethodDescriptor *
protobuf_c_service_descriptor_get_method_by_name
(const ProtobufCServiceDescriptor *desc,
const char *name);
/* --- wire format enums --- */
typedef enum
{
PROTOBUF_C_WIRE_TYPE_VARINT,
PROTOBUF_C_WIRE_TYPE_64BIT,
PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED,
PROTOBUF_C_WIRE_TYPE_START_GROUP, /* unsupported */
PROTOBUF_C_WIRE_TYPE_END_GROUP, /* unsupported */
PROTOBUF_C_WIRE_TYPE_32BIT
} ProtobufCWireType;
/* --- unknown message fields --- */
struct _ProtobufCMessageUnknownField
{
uint32_t tag;
ProtobufCWireType wire_type;
size_t len;
uint8_t *data;
};
/* --- extra (superfluous) api: trivial buffer --- */
typedef struct _ProtobufCBufferSimple ProtobufCBufferSimple;
struct _ProtobufCBufferSimple
{
ProtobufCBuffer base;
size_t alloced;
size_t len;
uint8_t *data;
protobuf_c_boolean must_free_data;
};
#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \
{ { protobuf_c_buffer_simple_append }, \
sizeof(array_of_bytes), 0, (array_of_bytes), 0 }
#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
do { if ((simp_buf)->must_free_data) \
protobuf_c_default_allocator.free (&protobuf_c_default_allocator.allocator_data, (simp_buf)->data); } while (0)
/* ====== private ====== */
#include "protobuf-c-private.h"
PROTOBUF_C_END_DECLS
#endif /* __PROTOBUF_C_RUNTIME_H_ */