summaryrefslogtreecommitdiff
path: root/bindings
diff options
context:
space:
mode:
authorJosh Haberman <haberman@google.com>2013-02-15 16:27:18 -0800
committerJosh Haberman <haberman@google.com>2013-02-15 16:27:18 -0800
commit7d3e2bd2c4cfd1296d1d6f996d7548de26540d41 (patch)
treeb4b35967b3322c65cfb1a32220e8718de09d85fc /bindings
parentea198bdcf947ba4bd51474bdd4f7b82b5e4cf41d (diff)
Sync with 8 months of Google-internal development.
Many things have changed and been simplified. The memory-management story for upb_def and upb_handlers is much more robust; upb_def and upb_handlers should be fairly stable interfaces now. There is still much work to do for the runtime component (upb_sink).
Diffstat (limited to 'bindings')
-rw-r--r--bindings/cpp/upb/bytestream.cc39
-rw-r--r--bindings/cpp/upb/bytestream.hpp276
-rw-r--r--bindings/cpp/upb/def.hpp462
-rw-r--r--bindings/cpp/upb/handlers.cc39
-rw-r--r--bindings/cpp/upb/handlers.hpp176
-rw-r--r--bindings/cpp/upb/msg.hpp62
-rw-r--r--bindings/cpp/upb/pb/decoder.hpp12
-rw-r--r--bindings/cpp/upb/pb/glue.hpp35
-rw-r--r--bindings/cpp/upb/proto2_bridge.cc892
-rw-r--r--bindings/cpp/upb/proto2_bridge.hpp170
-rw-r--r--bindings/cpp/upb/upb.hpp81
-rw-r--r--bindings/linux/Makefile4
-rw-r--r--bindings/linux/ctype.h8
-rw-r--r--bindings/linux/inttypes.h22
-rw-r--r--bindings/linux/setjmp.S60
-rw-r--r--bindings/linux/setjmp.h13
-rw-r--r--bindings/linux/string.h13
-rw-r--r--bindings/lua/LICENSE32
-rw-r--r--bindings/lua/lunitx/atexit.lua32
-rw-r--r--bindings/lua/lunitx/lunit.lua725
-rw-r--r--bindings/lua/lunitx/lunit/console.lua156
-rw-r--r--bindings/lua/lunitx/lunitx.lua21
-rw-r--r--bindings/lua/table.c167
-rw-r--r--bindings/lua/test.lua345
-rw-r--r--bindings/lua/upb.c1412
-rw-r--r--bindings/lua/upb.h45
26 files changed, 2170 insertions, 3129 deletions
diff --git a/bindings/cpp/upb/bytestream.cc b/bindings/cpp/upb/bytestream.cc
deleted file mode 100644
index df0797e..0000000
--- a/bindings/cpp/upb/bytestream.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-
-#include "bytestream.hpp"
-
-namespace upb {
-
-upb_bytesrc_vtbl* ByteSourceBase::vtable() {
- static upb_bytesrc_vtbl vtbl = {
- &ByteSourceBase::VFetch,
- &ByteSourceBase::VDiscard,
- &ByteSourceBase::VCopy,
- &ByteSourceBase::VGetPtr,
- };
- return &vtbl;
-}
-
-upb_bytesuccess_t ByteSourceBase::VFetch(void *src, uint64_t ofs, size_t *len) {
- return static_cast<ByteSourceBase*>(src)->Fetch(ofs, len);
-}
-
-void ByteSourceBase::VCopy(
- const void *src, uint64_t ofs, size_t len, char* dest) {
- static_cast<const ByteSourceBase*>(src)->Copy(ofs, len, dest);
-}
-
-void ByteSourceBase::VDiscard(void *src, uint64_t ofs) {
- static_cast<ByteSourceBase*>(src)->Discard(ofs);
-}
-
-const char * ByteSourceBase::VGetPtr(
- const void *src, uint64_t ofs, size_t* len) {
- return static_cast<const ByteSourceBase*>(src)->GetPtr(ofs, len);
-}
-
-} // namespace upb
diff --git a/bindings/cpp/upb/bytestream.hpp b/bindings/cpp/upb/bytestream.hpp
deleted file mode 100644
index 37d8157..0000000
--- a/bindings/cpp/upb/bytestream.hpp
+++ /dev/null
@@ -1,276 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-//
-// This file defines three core interfaces:
-// - upb::ByteSink: for writing streams of data.
-// - upb::ByteSource: for reading streams of data.
-// - upb::ByteRegion: for reading from a specific region of a ByteSource;
-// should be used by decoders instead of using a ByteSource directly.
-//
-// These interfaces are used by streaming encoders and decoders: for example, a
-// protobuf parser gets its input from a upb::ByteRegion. They are virtual
-// base classes so concrete implementations can get the data from a fd, a
-// FILE*, a string, etc.
-//
-// A ByteRegion represents a region of data from a ByteSource.
-//
-// Parsers get data from this interface instead of a bytesrc because we often
-// want to parse only a specific region of the input. For example, if we parse
-// a string from our input but know that the string represents a protobuf, we
-// can pass its ByteRegion to an appropriate protobuf parser.
-//
-// Since the bytes may be coming from a file or network socket, bytes must be
-// fetched before they can be read (though in some cases this fetch may be a
-// no-op). "fetch" is the only operation on a byteregion that could fail or
-// block, because it is the only operation that actually performs I/O.
-//
-// Bytes can be discarded when they are no longer needed. Parsers should
-// always discard bytes they no longer need, both so the buffers can be freed
-// when possible and to give better visibility into what bytes the parser is
-// still using.
-//
-// start discard read fetch end
-// ofs ofs ofs ofs ofs
-// | |--->Discard() | |--->Fetch() |
-// V V V V V
-// +-------------+-------------------------+-----------------+-----------------+
-// | discarded | | | fetchable |
-// +-------------+-------------------------+-----------------+-----------------+
-// | <------------- loaded ------------------> |
-// | <- available -> |
-// | <---------- remaining ----------> |
-//
-// Note that the start offset may be something other than zero! A byteregion
-// is a view into an underlying bytesrc stream, and the region may start
-// somewhere other than the beginning of that stream.
-//
-// The region can be either delimited or nondelimited. A non-delimited region
-// will keep returning data until the underlying data source returns EOF. A
-// delimited region will return EOF at a predetermined offset.
-//
-// end
-// ofs
-// |
-// V
-// +-----------------------+
-// | delimited region | <-- hard EOF, even if data source has more data.
-// +-----------------------+
-//
-// +------------------------
-// | nondelimited region Z <-- won't return EOF until data source hits EOF.
-// +------------------------
-
-#ifndef UPB_BYTESTREAM_HPP
-#define UPB_BYTESTREAM_HPP
-
-#include "upb/bytestream.h"
-#include "upb/upb.hpp"
-#include <string>
-
-namespace upb {
-
-typedef upb_bytesuccess_t ByteSuccess;
-
-// Implement this interface to vend bytes to ByteRegions which will be used by
-// a decoder.
-class ByteSourceBase : public upb_bytesrc {
- public:
- ByteSourceBase() { upb_bytesrc_init(this, vtable()); }
- virtual ~ByteSourceBase() { upb_bytesrc_uninit(this); }
-
- // Fetches at least one byte starting at ofs, setting *len to the actual
- // number of bytes fetched (or 0 on EOF or error: see return value for
- // details). It is valid for bytes to be fetched multiple times, as long as
- // the bytes have not been previously discarded.
- virtual ByteSuccess Fetch(uint64_t ofs, size_t* len) = 0;
-
- // Discards all data prior to ofs (except data that is pinned, if pinning
- // support is added -- see TODO below).
- virtual void Discard(uint64_t ofs) = 0;
-
- // Copies "len" bytes of data from ofs to "dst", which must be at least "len"
- // bytes long. The given region must not be discarded.
- virtual void Copy(uint64_t ofs, size_t len, char *dst) const = 0;
-
- // Returns a pointer to the bytesrc's internal buffer, storing in *len how
- // much data is available. The given offset must not be discarded. The
- // returned buffer is valid for as long as its bytes are not discarded (in
- // the case that part of the returned buffer is discarded, only the
- // non-discarded bytes remain valid).
- virtual const char *GetPtr(uint64_t ofs, size_t *len) const = 0;
-
- // TODO: Add if/when there is a demonstrated need:
- //
- // // When the caller pins a region (which must not be already discarded), it
- // // is guaranteed that the region will not be discarded (nor will the
- // // bytesrc be destroyed) until the region is unpinned. However, not all
- // // bytesrc's support pinning; a false return indicates that a pin was not
- // // possible.
- // virtual bool Pin(uint64_t ofs, size_t len);
- //
- // // Releases some number of pinned bytes from the beginning of a pinned
- // // region (which may be fewer than the total number of bytes pinned).
- // virtual void Unpin(uint64_t ofs, size_t len, size_t bytes_to_release);
- //
- // Adding pinning support would also involve adding a "pin_ofs" parameter to
- // upb_bytesrc_fetch, so that the fetch can extend an already-pinned region.
- private:
- static upb_bytesrc_vtbl* vtable();
- static upb_bytesuccess_t VFetch(void*, uint64_t, size_t*);
- static void VDiscard(void*, uint64_t);
- static void VCopy(const void*, uint64_t, size_t, char*);
- static const char *VGetPtr(const void*, uint64_t, size_t*);
-};
-
-class ByteRegion : public upb_byteregion {
- public:
- static const uint64_t kNondelimited = UPB_NONDELIMITED;
-
- ByteRegion() { upb_byteregion_init(this); }
- ~ByteRegion() { upb_byteregion_uninit(this); }
-
- // Accessors for the regions bounds -- the meaning of these is described in
- // the diagram above.
- uint64_t start_ofs() const { return upb_byteregion_startofs(this); }
- uint64_t discard_ofs() const { return upb_byteregion_discardofs(this); }
- uint64_t fetch_ofs() const { return upb_byteregion_fetchofs(this); }
- uint64_t end_ofs() const { return upb_byteregion_endofs(this); }
-
- // Returns how many bytes are fetched and available for reading starting from
- // offset "offset".
- uint64_t BytesAvailable(uint64_t offset) const {
- return upb_byteregion_available(this, offset);
- }
-
- // Returns the total number of bytes remaining after offset "offset", or
- // kNondelimited if the byteregion is non-delimited.
- uint64_t BytesRemaining(uint64_t offset) const {
- return upb_byteregion_remaining(this, offset);
- }
-
- uint64_t Length() const { return upb_byteregion_len(this); }
-
- // Sets the value of this byteregion to be a subset of the given byteregion's
- // data. The caller is responsible for releasing this region before the src
- // region is released (unless the region is first pinned, if pinning support
- // is added. see below).
- void Reset(const upb_byteregion *src, uint64_t ofs, uint64_t len) {
- upb_byteregion_reset(this, src, ofs, len);
- }
- void Release() { upb_byteregion_release(this); }
-
- // Attempts to fetch more data, extending the fetched range of this
- // byteregion. Returns true if the fetched region was extended by at least
- // one byte, false on EOF or error (see *s for details).
- ByteSuccess Fetch() { return upb_byteregion_fetch(this); }
-
- // Fetches all remaining data, returning false if the operation failed (see
- // *s for details). May only be used on delimited byteregions.
- ByteSuccess FetchAll() { return upb_byteregion_fetchall(this); }
-
- // Discards bytes from the byteregion up until ofs (which must be greater or
- // equal to discard_ofs()). It is valid to discard bytes that have not been
- // fetched (such bytes will never be fetched) but it is an error to discard
- // past the end of a delimited byteregion.
- void Discard(uint64_t ofs) { return upb_byteregion_discard(this, ofs); }
-
- // Copies "len" bytes of data into "dst", starting at ofs. The specified
- // region must be available.
- void Copy(uint64_t ofs, size_t len, char *dst) const {
- upb_byteregion_copy(this, ofs, len, dst);
- }
-
- // Copies all bytes from the byteregion into dst. Requires that the entire
- // byteregion is fetched and that none has been discarded.
- void CopyAll(char *dst) const {
- upb_byteregion_copyall(this, dst);
- }
-
- // Returns a pointer to the internal buffer for the byteregion starting at
- // offset "ofs." Stores the number of bytes available in this buffer in *len.
- // The returned buffer is invalidated when the byteregion is reset or
- // released, or when the bytes are discarded. If the byteregion is not
- // currently pinned, the pointer is only valid for the lifetime of the parent
- // byteregion.
- const char *GetPtr(uint64_t ofs, size_t *len) const {
- return upb_byteregion_getptr(this, ofs, len);
- }
-
- // Copies the contents of the byteregion into a newly-allocated,
- // NULL-terminated string. Requires that the byteregion is fully fetched.
- char *StrDup() const {
- return upb_byteregion_strdup(this);
- }
-
- template <typename T> void AssignToString(T* str) {
- uint64_t ofs = start_ofs();
- size_t len;
- const char *ptr = GetPtr(ofs, &len);
- // Emperically calling reserve() here is counterproductive and slows down
- // benchmarks. If the parsing is happening in a tight loop that is reusing
- // the string object, there is probably enough data reserved already and
- // the reserve() call is extra overhead.
- str->assign(ptr, len);
- ofs += len;
- while (ofs < end_ofs()) {
- ptr = GetPtr(ofs, &len);
- str->append(ptr, len);
- ofs += len;
- }
- }
-
- // TODO: add if/when there is a demonstrated need.
- //
- // // Pins this byteregion's bytes in memory, allowing it to outlive its
- // // parent byteregion. Normally a byteregion may only be used while its
- // // parent is still valid, but a pinned byteregion may continue to be used
- // // until it is reset or released. A byteregion must be fully fetched to
- // // be pinned (this implies that the byteregion must be delimited).
- // //
- // // In some cases this operation may cause the input data to be copied.
- // //
- // // void Pin();
-};
-
-class StringSource : public upb_stringsrc {
- public:
- StringSource() : upb_stringsrc() { upb_stringsrc_init(this); }
- template <typename T> explicit StringSource(const T& str) {
- upb_stringsrc_init(this);
- Reset(str);
- }
- StringSource(const char *data, size_t len) {
- upb_stringsrc_init(this);
- Reset(data, len);
- }
- ~StringSource() { upb_stringsrc_uninit(this); }
-
- void Reset(const char* data, size_t len) {
- upb_stringsrc_reset(this, data, len);
- }
-
- template <typename T> void Reset(const T& str) {
- Reset(str.c_str(), str.size());
- }
-
- ByteRegion* AllBytes() {
- return static_cast<ByteRegion*>(upb_stringsrc_allbytes(this));
- }
-
- upb_bytesrc* ByteSource() { return upb_stringsrc_bytesrc(this); }
-};
-
-template <> inline ByteRegion* GetValue<ByteRegion*>(Value v) {
- return static_cast<ByteRegion*>(upb_value_getbyteregion(v));
-}
-
-template <> inline Value MakeValue<ByteRegion*>(ByteRegion* v) {
- return upb_value_byteregion(v);
-}
-
-} // namespace upb
-
-#endif
diff --git a/bindings/cpp/upb/def.hpp b/bindings/cpp/upb/def.hpp
deleted file mode 100644
index 6547255..0000000
--- a/bindings/cpp/upb/def.hpp
+++ /dev/null
@@ -1,462 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-//
-// The set of upb::*Def classes and upb::SymbolTable allow for defining and
-// manipulating schema information (as defined in .proto files).
-//
-// Defs go through two distinct phases of life:
-//
-// 1. MUTABLE: when first created, the properties of the def can be set freely
-// (for example a message's name, its list of fields, the name/number of
-// fields, etc). During this phase the def is *not* thread-safe, and may
-// not be used for any purpose except to set its properties (it can't be
-// used to parse anything, create any messages in memory, etc).
-//
-// 2. FINALIZED: the Def::Finzlie() operation finalizes a set of defs,
-// which makes them thread-safe and immutable. Finalized defs may only be
-// accessed through a CONST POINTER. If you want to modify an existing
-// immutable def, copy it with Dup() and modify and finalize the copy.
-//
-// The refcounting of defs works properly no matter what state the def is in.
-// Once the def is finalized it is guaranteed that any def reachable from a
-// live def is also live (so a ref on the base of a message tree keeps the
-// whole tree alive).
-//
-// You can test for which stage of life a def is in by calling IsMutable().
-// This is particularly useful for dynamic language bindings, which must
-// properly guarantee that the dynamic language cannot break the rules laid out
-// above.
-//
-// It would be possible to make the defs thread-safe during stage 1 by using
-// mutexes internally and changing any methods returning pointers to return
-// copies instead. This could be important if we are integrating with a VM or
-// interpreter that does not naturally serialize access to wrapped objects (for
-// example, in the case of Python this is not necessary because of the GIL).
-
-#ifndef UPB_DEF_HPP
-#define UPB_DEF_HPP
-
-#include <algorithm>
-#include <string>
-#include <vector>
-#include "upb/def.h"
-#include "upb/upb.hpp"
-
-namespace upb {
-
-class Def;
-class MessageDef;
-
-typedef upb_fieldtype_t FieldType;
-typedef upb_label_t Label;
-
-class FieldDef : public upb_fielddef {
- public:
- static FieldDef* Cast(upb_fielddef *f) { return static_cast<FieldDef*>(f); }
- static const FieldDef* Cast(const upb_fielddef *f) {
- return static_cast<const FieldDef*>(f);
- }
-
- static FieldDef* New(const void *owner) {
- return Cast(upb_fielddef_new(owner));
- }
- FieldDef* Dup(const void *owner) const {
- return Cast(upb_fielddef_dup(this, owner));
- }
- void Ref(const void *owner) { upb_fielddef_ref(this, owner); }
- void Unref(const void *owner) { upb_fielddef_unref(this, owner); }
-
- bool IsMutable() const { return upb_fielddef_ismutable(this); }
- bool IsFinalized() const { return upb_fielddef_isfinalized(this); }
- bool IsString() const { return upb_isstring(this); }
- bool IsSequence() const { return upb_isseq(this); }
- bool IsSubmessage() const { return upb_issubmsg(this); }
-
- // Simple accessors. /////////////////////////////////////////////////////////
-
- FieldType type() const { return upb_fielddef_type(this); }
- Label label() const { return upb_fielddef_label(this); }
- int32_t number() const { return upb_fielddef_number(this); }
- std::string name() const { return std::string(upb_fielddef_name(this)); }
- Value default_() const { return upb_fielddef_default(this); }
- Value bound_value() const { return upb_fielddef_fval(this); }
- uint16_t offset() const { return upb_fielddef_offset(this); }
- int16_t hasbit() const { return upb_fielddef_hasbit(this); }
-
- bool set_type(FieldType type) { return upb_fielddef_settype(this, type); }
- bool set_label(Label label) { return upb_fielddef_setlabel(this, label); }
- void set_offset(uint16_t offset) { upb_fielddef_setoffset(this, offset); }
- void set_hasbit(int16_t hasbit) { upb_fielddef_sethasbit(this, hasbit); }
- void set_fval(Value fval) { upb_fielddef_setfval(this, fval); }
- void set_accessor(struct _upb_accessor_vtbl* vtbl) {
- upb_fielddef_setaccessor(this, vtbl);
- }
- MessageDef* message();
- const MessageDef* message() const;
-
- struct _upb_accessor_vtbl *accessor() const {
- return upb_fielddef_accessor(this);
- }
-
- // "Number" and "name" must be set before the fielddef is added to a msgdef.
- // For the moment we do not allow these to be set once the fielddef is added
- // to a msgdef -- this could be relaxed in the future.
- bool set_number(int32_t number) {
- return upb_fielddef_setnumber(this, number);
- }
- bool set_name(const char *name) { return upb_fielddef_setname(this, name); }
- bool set_name(const std::string& name) { return set_name(name.c_str()); }
-
- // Default value. ////////////////////////////////////////////////////////////
-
- // Returns the default value for this fielddef, which may either be something
- // the client set explicitly or the "default default" (0 for numbers, empty
- // for strings). The field's type indicates the type of the returned value,
- // except for enum fields that are still mutable.
- //
- // For enums the default can be set either numerically or symbolically -- the
- // upb_fielddef_default_is_symbolic() function below will indicate which it
- // is. For string defaults, the value will be a upb_byteregion which is
- // invalidated by any other non-const call on this object. Once the fielddef
- // is finalized, symbolic enum defaults are resolved, so finalized enum
- // fielddefs always have a default of type int32.
- Value defaultval() { return upb_fielddef_default(this); }
-
- // Sets default value for the field. For numeric types, use
- // upb_fielddef_setdefault(), and "value" must match the type of the field.
- // For string/bytes types, use upb_fielddef_setdefaultstr(). Enum types may
- // use either, since the default may be set either numerically or
- // symbolically.
- //
- // NOTE: May only be called for fields whose type has already been set.
- // Also, will be reset to default if the field's type is set again.
- void set_default(Value value) { upb_fielddef_setdefault(this, value); }
- void set_default(const char *str) { upb_fielddef_setdefaultcstr(this, str); }
- void set_default(const char *str, size_t len) {
- upb_fielddef_setdefaultstr(this, str, len);
- }
- void set_default(const std::string& str) {
- upb_fielddef_setdefaultstr(this, str.c_str(), str.size());
- }
-
- // The results of this function are only meaningful for mutable enum fields,
- // which can have a default specified either as an integer or as a string.
- // If this returns true, the default returned from upb_fielddef_default() is
- // a string, otherwise it is an integer.
- bool DefaultIsSymbolic() { return upb_fielddef_default_is_symbolic(this); }
-
- // Subdef. ///////////////////////////////////////////////////////////////////
-
- // Submessage and enum fields must reference a "subdef", which is the
- // MessageDef or EnumDef that defines their type. Note that when the
- // FieldDef is mutable it may not have a subdef *yet*, but this still returns
- // true to indicate that the field's type requires a subdef.
- bool HasSubDef() { return upb_hassubdef(this); }
-
- // Before a FieldDef is finalized, its subdef may be set either directly
- // (with a Def*) or symbolically. Symbolic refs must be resolved by the
- // client before the containing msgdef can be finalized.
- //
- // Both methods require that HasSubDef() (so the type must be set prior to
- // calling these methods). Returns false if this is not the case, or if the
- // given subdef is not of the correct type. The subtype is reset if the
- // field's type is changed.
- bool set_subdef(Def* def);
- bool set_subtype_name(const char *name) {
- return upb_fielddef_setsubtypename(this, name);
- }
- bool set_subtype_name(const std::string& str) {
- return set_subtype_name(str.c_str());
- }
-
- // Returns the enum or submessage def or symbolic name for this field, if
- // any. May only be called for fields where HasSubDef() is true. Returns
- // NULL if the subdef has not been set or if you ask for a subtype name when
- // the subtype is currently set symbolically (or vice-versa).
- //
- // Caller does *not* own a ref on the returned def or string.
- // subtypename_name() is non-const because only mutable defs can have the
- // subtype name set symbolically (symbolic references must be resolved before
- // the MessageDef can be finalized).
- const Def* subdef() const;
- const char *subtype_name() { return upb_fielddef_subtypename(this); }
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(FieldDef);
-};
-
-class Def : public upb_def {
- public:
- // Converting from C types to C++ wrapper types.
- static Def* Cast(upb_def *def) { return static_cast<Def*>(def); }
- static const Def* Cast(const upb_def *def) {
- return static_cast<const Def*>(def);
- }
-
- void Ref(const void *owner) const { upb_def_ref(this, owner); }
- void Unref(const void *owner) const { upb_def_unref(this, owner); }
-
- void set_full_name(const char *name) { upb_def_setfullname(this, name); }
- void set_full_name(const std::string& name) {
- upb_def_setfullname(this, name.c_str());
- }
-
- const char *full_name() const { return upb_def_fullname(this); }
-
- // Finalizes the given list of defs (as well as the fielddefs for the given
- // msgdefs). All defs reachable from any def in this list must either be
- // already finalized or elsewhere in the list. Any symbolic references to
- // enums or submessages must already have been resolved. Returns true on
- // success, otherwise false is returned and status contains details. In the
- // error case the input defs are unmodified. See the comment at the top of
- // this file for the semantics of finalized defs.
- //
- // n is currently limited to 64k defs, if more are required break them into
- // batches of 64k (or we could raise this limit, at the cost of a bigger
- // upb_def structure or complexity in upb_def_finalize()).
- static bool Finalize(Def*const* defs, int n, Status* status) {
- return upb_finalize(reinterpret_cast<upb_def*const*>(defs), n, status);
- }
- static bool Finalize(const std::vector<Def*>& defs, Status* status) {
- return Finalize(&defs[0], defs.size(), status);
- }
-};
-
-class MessageDef : public upb_msgdef {
- public:
- // Converting from C types to C++ wrapper types.
- static MessageDef* Cast(upb_msgdef *md) {
- return static_cast<MessageDef*>(md);
- }
- static const MessageDef* Cast(const upb_msgdef *md) {
- return static_cast<const MessageDef*>(md);
- }
- static MessageDef* DynamicCast(Def* def) {
- return Cast(upb_dyncast_msgdef(def));
- }
- static const MessageDef* DynamicCast(const Def* def) {
- return Cast(upb_dyncast_msgdef_const(def));
- }
-
- Def* AsDef() { return Def::Cast(UPB_UPCAST(this)); }
- const Def* AsDef() const { return Def::Cast(UPB_UPCAST(this)); }
-
- static MessageDef* New(void *owner) { return Cast(upb_msgdef_new(owner)); }
- MessageDef* Dup(void *owner) const {
- return Cast(upb_msgdef_dup(this, owner));
- }
-
- void Ref(const void *owner) const { upb_msgdef_ref(this, owner); }
- void Unref(const void *owner) const { upb_msgdef_unref(this, owner); }
-
- // Read accessors -- may be called at any time.
-
- const char *full_name() const { return AsDef()->full_name(); }
-
- // The total size of in-memory messages created with this MessageDef.
- uint16_t instance_size() const { return upb_msgdef_size(this); }
-
- // The number of "hasbit" bytes in a message instance.
- uint8_t hasbit_bytes() const { return upb_msgdef_hasbit_bytes(this); }
-
- uint32_t extension_start() const { return upb_msgdef_extstart(this); }
- uint32_t extension_end() const { return upb_msgdef_extend(this); }
-
- // Write accessors. May only be called before the msgdef is in a symtab.
-
- void set_full_name(const char *name) { AsDef()->set_full_name(name); }
- void set_full_name(const std::string& name) { AsDef()->set_full_name(name); }
-
- void set_instance_size(uint16_t size) { upb_msgdef_setsize(this, size); }
- void set_hasbit_bytes(uint16_t size) { upb_msgdef_setsize(this, size); }
- bool SetExtensionRange(uint32_t start, uint32_t end) {
- return upb_msgdef_setextrange(this, start, end);
- }
-
- // Adds a set of fields (FieldDef objects) to a MessageDef. Caller passes a
- // ref on the FieldDef to the MessageDef in both success and failure cases.
- // May only be done before the MessageDef is in a SymbolTable (requires
- // m->IsMutable() for the MessageDef). The FieldDef's name and number must
- // be set, and the message may not already contain any field with this name
- // or number, and this FieldDef may not be part of another message, otherwise
- // false is returned and the MessageDef is unchanged.
- bool AddField(FieldDef* f, const void *owner) {
- return AddFields(&f, 1, owner);
- }
- bool AddFields(FieldDef*const * f, int n, const void *owner) {
- return upb_msgdef_addfields(this, (upb_fielddef*const*)f, n, owner);
- }
- bool AddFields(const std::vector<FieldDef*>& fields, const void *owner) {
- return AddFields(&fields[0], fields.size(), owner);
- }
-
- int field_count() const { return upb_msgdef_numfields(this); }
-
- // Lookup fields by name or number, returning NULL if no such field exists.
- FieldDef* FindFieldByName(const char *name) {
- return FieldDef::Cast(upb_msgdef_ntof(this, name));
- }
- FieldDef* FindFieldByName(const std::string& name) {
- return FieldDef::Cast(upb_msgdef_ntof(this, name.c_str()));
- }
- FieldDef* FindFieldByNumber(uint32_t num) {
- return FieldDef::Cast(upb_msgdef_itof(this, num));
- }
-
- const FieldDef* FindFieldByName(const char *name) const {
- return FindFieldByName(name);
- }
- const FieldDef* FindFieldByName(const std::string& name) const {
- return FindFieldByName(name);
- }
- const FieldDef* FindFieldByNumber(uint32_t num) const {
- return FindFieldByNumber(num);
- }
-
- class Iterator : public upb_msg_iter {
- public:
- explicit Iterator(MessageDef* md) { upb_msg_begin(this, md); }
- Iterator() {}
-
- FieldDef* field() { return FieldDef::Cast(upb_msg_iter_field(this)); }
- bool Done() { return upb_msg_done(this); }
- void Next() { return upb_msg_next(this); }
- };
-
- class ConstIterator : public upb_msg_iter {
- public:
- explicit ConstIterator(const MessageDef* md) { upb_msg_begin(this, md); }
- ConstIterator() {}
-
- const FieldDef* field() { return FieldDef::Cast(upb_msg_iter_field(this)); }
- bool Done() { return upb_msg_done(this); }
- void Next() { return upb_msg_next(this); }
- };
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(MessageDef);
-};
-
-class EnumDef : public upb_enumdef {
- public:
- // Converting from C types to C++ wrapper types.
- static EnumDef* Cast(upb_enumdef *e) { return static_cast<EnumDef*>(e); }
- static const EnumDef* Cast(const upb_enumdef *e) {
- return static_cast<const EnumDef*>(e);
- }
-
- static EnumDef* New(const void *owner) { return Cast(upb_enumdef_new(owner)); }
-
- void Ref(const void *owner) { upb_enumdef_ref(this, owner); }
- void Unref(const void *owner) { upb_enumdef_unref(this, owner); }
- EnumDef* Dup(const void *owner) const {
- return Cast(upb_enumdef_dup(this, owner));
- }
-
- Def* AsDef() { return Def::Cast(UPB_UPCAST(this)); }
- const Def* AsDef() const { return Def::Cast(UPB_UPCAST(this)); }
-
- int32_t default_value() const { return upb_enumdef_default(this); }
-
- // May only be set if IsMutable().
- void set_full_name(const char *name) { AsDef()->set_full_name(name); }
- void set_full_name(const std::string& name) { AsDef()->set_full_name(name); }
- void set_default_value(int32_t val) {
- return upb_enumdef_setdefault(this, val);
- }
-
- // Adds a value to the enumdef. Requires that no existing val has this
- // name or number (returns false and does not add if there is). May only
- // be called if IsMutable().
- bool AddValue(char *name, int32_t num) {
- return upb_enumdef_addval(this, name, num);
- }
- bool AddValue(const std::string& name, int32_t num) {
- return upb_enumdef_addval(this, name.c_str(), num);
- }
-
- // Lookups from name to integer and vice-versa.
- bool LookupName(const char *name, int32_t* num) const {
- return upb_enumdef_ntoi(this, name, num);
- }
-
- // Lookup from integer to name, returns a NULL-terminated string which
- // the caller does not own, or NULL if not found.
- const char *LookupNumber(int32_t num) const {
- return upb_enumdef_iton(this, num);
- }
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(EnumDef);
-};
-
-class SymbolTable : public upb_symtab {
- public:
- // Converting from C types to C++ wrapper types.
- static SymbolTable* Cast(upb_symtab *s) {
- return static_cast<SymbolTable*>(s);
- }
- static const SymbolTable* Cast(const upb_symtab *s) {
- return static_cast<const SymbolTable*>(s);
- }
-
- static SymbolTable* New(const void *owner) {
- return Cast(upb_symtab_new(owner));
- }
-
- void Ref(const void *owner) const { upb_symtab_unref(this, owner); }
- void Unref(const void *owner) const { upb_symtab_unref(this, owner); }
- void DonateRef(const void *from, const void *to) const {
- upb_symtab_donateref(this, from, to);
- }
-
- // Adds the given defs to the symtab, resolving all symbols. Only one def
- // per name may be in the list, but defs can replace existing defs in the
- // symtab. The entire operation either succeeds or fails. If the operation
- // fails, the symtab is unchanged, false is returned, and status indicates
- // the error. The caller passes a ref on the defs in all cases.
- bool Add(Def *const *defs, int n, void *owner, Status* status) {
- return upb_symtab_add(this, (upb_def*const*)defs, n, owner, status);
- }
- bool Add(const std::vector<Def*>& defs, void *owner, Status* status) {
- return Add(&defs[0], defs.size(), owner, status);
- }
-
- // If the given name refers to a message in this symbol table, returns a new
- // ref to that MessageDef object, otherwise returns NULL.
- const MessageDef* LookupMessage(const char *name, void *owner) const {
- return MessageDef::Cast(upb_symtab_lookupmsg(this, name, owner));
- }
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(SymbolTable);
-};
-
-template <> inline const FieldDef* GetValue<const FieldDef*>(Value v) {
- return static_cast<const FieldDef*>(upb_value_getfielddef(v));
-}
-
-template <> inline Value MakeValue<FieldDef*>(FieldDef* v) {
- return upb_value_fielddef(v);
-}
-
-inline MessageDef* FieldDef::message() {
- return MessageDef::Cast(upb_fielddef_msgdef(this));
-}
-inline const MessageDef* FieldDef::message() const {
- return MessageDef::Cast(upb_fielddef_msgdef(this));
-}
-
-inline const Def* FieldDef::subdef() const {
- return Def::Cast(upb_fielddef_subdef(this));
-}
-inline bool FieldDef::set_subdef(Def* def) {
- return upb_fielddef_setsubdef(this, def);
-}
-
-} // namespace upb
-
-#endif
diff --git a/bindings/cpp/upb/handlers.cc b/bindings/cpp/upb/handlers.cc
deleted file mode 100644
index c96a74e..0000000
--- a/bindings/cpp/upb/handlers.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-
-#include "handlers.hpp"
-
-#include "def.hpp"
-
-namespace upb {
-
-namespace {
-
-void MessageCallbackWrapper(
- void* closure, upb_mhandlers* mh, const upb_msgdef* m) {
- Handlers::MessageRegistrationVisitor* visitor =
- static_cast<Handlers::MessageRegistrationVisitor*>(closure);
- visitor->OnMessage(static_cast<MessageHandlers*>(mh),
- static_cast<const MessageDef*>(m));
-}
-
-void FieldCallbackWrapper(
- void* closure, upb_fhandlers* fh, const upb_fielddef* f) {
- Handlers::MessageRegistrationVisitor* visitor =
- static_cast<Handlers::MessageRegistrationVisitor*>(closure);
- visitor->OnField(static_cast<FieldHandlers*>(fh),
- static_cast<const FieldDef*>(f));
-}
-} // namepace
-
-MessageHandlers* Handlers::RegisterMessageDef(
- const MessageDef& m, Handlers::MessageRegistrationVisitor* visitor) {
- upb_mhandlers* mh = upb_handlers_regmsgdef(
- this, &m, &MessageCallbackWrapper, &FieldCallbackWrapper, &visitor);
- return static_cast<MessageHandlers*>(mh);
-}
-
-} // namespace upb
diff --git a/bindings/cpp/upb/handlers.hpp b/bindings/cpp/upb/handlers.hpp
deleted file mode 100644
index a366c3d..0000000
--- a/bindings/cpp/upb/handlers.hpp
+++ /dev/null
@@ -1,176 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-//
-// upb::Handlers is a generic visitor-like interface for iterating over a
-// stream of protobuf data. You can register function pointers that will be
-// called for each message and/or field as the data is being parsed or iterated
-// over, without having to know the source format that we are parsing from.
-// This decouples the parsing logic from the processing logic.
-
-#ifndef UPB_HANDLERS_HPP
-#define UPB_HANDLERS_HPP
-
-#include "upb/handlers.h"
-
-#include "upb/upb.hpp"
-
-namespace upb {
-
-typedef upb_fieldtype_t FieldType;
-typedef upb_flow_t Flow;
-typedef upb_sflow_t SubFlow;
-class MessageHandlers;
-class MessageDef;
-class FieldDef;
-
-class FieldHandlers : public upb_fhandlers {
- public:
- typedef upb_value_handler ValueHandler;
- typedef upb_startfield_handler StartFieldHandler;
- typedef upb_endfield_handler EndFieldHandler;
-
- // The FieldHandlers will live at least as long as the upb::Handlers to
- // which it belongs, but can be Ref'd/Unref'd to make it live longer (which
- // will prolong the life of the underlying upb::Handlers also).
- void Ref() { upb_fhandlers_ref(this); }
- void Unref() { upb_fhandlers_unref(this); }
-
- // Functions to set this field's handlers.
- // These return "this" so they can be conveniently chained, eg.
- // message_handlers->NewField(...)
- // ->SetStartSequenceHandler(&StartSequence),
- // ->SetEndSequenceHandler(&EndSequence),
- // ->SetValueHandler(&Value);
- FieldHandlers* SetValueHandler(ValueHandler* h) {
- upb_fhandlers_setvalue(this, h); return this;
- }
- FieldHandlers* SetStartSequenceHandler(StartFieldHandler* h) {
- upb_fhandlers_setstartseq(this, h); return this;
- }
- FieldHandlers* SetEndSequenceHandler(EndFieldHandler* h) {
- upb_fhandlers_setendseq(this, h); return this;
- }
- FieldHandlers* SetStartSubmessageHandler(StartFieldHandler* h) {
- upb_fhandlers_setstartsubmsg(this, h); return this;
- }
- FieldHandlers* SetEndSubmessageHandler(EndFieldHandler* h) {
- upb_fhandlers_setendsubmsg(this, h); return this;
- }
-
- // Get/Set the field's bound value, which will be passed to its handlers.
- Value GetBoundValue() const { return upb_fhandlers_getfval(this); }
- FieldHandlers* SetBoundValue(Value val) {
- upb_fhandlers_setfval(this, val); return this;
- }
-
- // Returns the MessageHandlers to which we belong.
- MessageHandlers* GetMessageHandlers() const;
- // Returns the MessageHandlers for this field's submessage (invalid to call
- // unless this field's type UPB_TYPE(MESSAGE) or UPB_TYPE(GROUP).
- MessageHandlers* GetSubMessageHandlers() const;
- // If set to >=0, the given hasbit will be set after the value callback is
- // called (offset relative to the current closure).
- int32_t GetHasbit() const { return upb_fhandlers_gethasbit(this); }
- void SetHasbit(int32_t bit) { upb_fhandlers_sethasbit(this, bit); }
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(FieldHandlers);
-};
-
-class MessageHandlers : public upb_mhandlers {
- public:
- typedef upb_startmsg_handler StartMessageHandler;
- typedef upb_endmsg_handler EndMessageHandler;
-
- static MessageHandlers* Cast(upb_mhandlers* mh) {
- return static_cast<MessageHandlers*>(mh);
- }
- static const MessageHandlers* Cast(const upb_mhandlers* mh) {
- return static_cast<const MessageHandlers*>(mh);
- }
-
- // The MessageHandlers will live at least as long as the upb::Handlers to
- // which it belongs, but can be Ref'd/Unref'd to make it live longer (which
- // will prolong the life of the underlying upb::Handlers also).
- void Ref() { upb_mhandlers_ref(this); }
- void Unref() { upb_mhandlers_unref(this); }
-
- // Functions to set this message's handlers.
- // These return "this" so they can be conveniently chained, eg.
- // handlers->NewMessageHandlers()
- // ->SetStartMessageHandler(&StartMessage)
- // ->SetEndMessageHandler(&EndMessage);
- MessageHandlers* SetStartMessageHandler(StartMessageHandler* h) {
- upb_mhandlers_setstartmsg(this, h); return this;
- }
- MessageHandlers* SetEndMessageHandler(EndMessageHandler* h) {
- upb_mhandlers_setendmsg(this, h); return this;
- }
-
- // Functions to create new FieldHandlers for this message.
- FieldHandlers* NewFieldHandlers(uint32_t fieldnum, FieldType type,
- bool repeated) {
- return static_cast<FieldHandlers*>(
- upb_mhandlers_newfhandlers(this, fieldnum, type, repeated));
- }
-
- // Like the previous but for MESSAGE or GROUP fields. For GROUP fields, the
- // given submessage must not have any fields with this field number.
- FieldHandlers* NewFieldHandlersForSubmessage(uint32_t n, const char *name,
- FieldType type, bool repeated,
- MessageHandlers* subm) {
- (void)name;
- return static_cast<FieldHandlers*>(
- upb_mhandlers_newfhandlers_subm(this, n, type, repeated, subm));
- }
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(MessageHandlers);
-};
-
-class Handlers : public upb_handlers {
- public:
- // Creates a new Handlers instance.
- static Handlers* New() { return static_cast<Handlers*>(upb_handlers_new()); }
-
- void Ref() { upb_handlers_ref(this); }
- void Unref() { upb_handlers_unref(this); }
-
- // Returns a new MessageHandlers object. The first such message that is
- // obtained will be the top-level message for this Handlers object.
- MessageHandlers* NewMessageHandlers() {
- return static_cast<MessageHandlers*>(upb_handlers_newmhandlers(this));
- }
-
- // Convenience function for registering handlers for all messages and fields
- // in a MessageDef and all its children. For every registered message,
- // OnMessage will be called on the visitor with newly-created MessageHandlers
- // and MessageDef. Likewise with OnField will be called with newly-created
- // FieldHandlers and FieldDef for each field.
- class MessageRegistrationVisitor {
- public:
- virtual ~MessageRegistrationVisitor() {}
- virtual void OnMessage(MessageHandlers* mh, const MessageDef* m) = 0;
- virtual void OnField(FieldHandlers* fh, const FieldDef* f) = 0;
- };
- MessageHandlers* RegisterMessageDef(const MessageDef& m,
- MessageRegistrationVisitor* visitor);
-
- private:
- UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(Handlers);
-};
-
-inline MessageHandlers* FieldHandlers::GetMessageHandlers() const {
- return static_cast<MessageHandlers*>(upb_fhandlers_getmsg(this));
-}
-
-inline MessageHandlers* FieldHandlers::GetSubMessageHandlers() const {
- return static_cast<MessageHandlers*>(upb_fhandlers_getsubmsg(this));
-}
-
-} // namespace upb
-
-#endif
diff --git a/bindings/cpp/upb/msg.hpp b/bindings/cpp/upb/msg.hpp
deleted file mode 100644
index cde1743..0000000
--- a/bindings/cpp/upb/msg.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-// Routines for reading and writing message data to an in-memory structure,
-// similar to a C struct.
-//
-// upb does not define one single message object that everyone must use.
-// Rather it defines an abstract interface for reading and writing members
-// of a message object, and all of the parsers and serializers use this
-// abstract interface. This allows upb's parsers and serializers to be used
-// regardless of what memory management scheme or synchronization model the
-// application is using.
-//
-// A standard set of accessors is provided for doing simple reads and writes at
-// a known offset into the message. These accessors should be used when
-// possible, because they are specially optimized -- for example, the JIT can
-// recognize them and emit specialized code instead of having to call the
-// function at all. The application can substitute its own accessors when the
-// standard accessors are not suitable.
-
-#ifndef UPB_MSG_HPP
-#define UPB_MSG_HPP
-
-#include "upb/msg.h"
-#include "upb/handlers.hpp"
-
-namespace upb {
-
-typedef upb_accessor_vtbl AccessorVTable;
-
-// Registers handlers for writing into a message of the given type using
-// whatever accessors it has defined.
-inline MessageHandlers* RegisterWriteHandlers(upb::Handlers* handlers,
- const upb::MessageDef* md) {
- return MessageHandlers::Cast(
- upb_accessors_reghandlers(handlers, md));
-}
-
-template <typename T> static FieldHandlers::ValueHandler* GetValueHandler();
-
-// A handy templated function that will retrieve a value handler for a given
-// C++ type.
-#define GET_VALUE_HANDLER(type, ctype) \
- template <> \
- inline FieldHandlers::ValueHandler* GetValueHandler<ctype>() { \
- return &upb_stdmsg_set ## type; \
- }
-
-GET_VALUE_HANDLER(double, double);
-GET_VALUE_HANDLER(float, float);
-GET_VALUE_HANDLER(uint64, uint64_t);
-GET_VALUE_HANDLER(uint32, uint32_t);
-GET_VALUE_HANDLER(int64, int64_t);
-GET_VALUE_HANDLER(int32, int32_t);
-GET_VALUE_HANDLER(bool, bool);
-#undef GET_VALUE_HANDLER
-
-} // namespace
-
-#endif
diff --git a/bindings/cpp/upb/pb/decoder.hpp b/bindings/cpp/upb/pb/decoder.hpp
index 05bcb8a..950e9e2 100644
--- a/bindings/cpp/upb/pb/decoder.hpp
+++ b/bindings/cpp/upb/pb/decoder.hpp
@@ -22,14 +22,14 @@
#include "upb/pb/decoder.h"
-#include "upb/bytestream.hpp"
-#include "upb/upb.hpp"
+#include "upb/bytestream.h"
+#include "upb/upb.h"
namespace upb {
class DecoderPlan : public upb_decoderplan {
public:
- static DecoderPlan* New(Handlers* h, bool allow_jit) {
+ static DecoderPlan* New(const Handlers* h, bool allow_jit) {
return static_cast<DecoderPlan*>(upb_decoderplan_new(h, allow_jit));
}
void Unref() { upb_decoderplan_unref(this); }
@@ -54,9 +54,7 @@ class Decoder : public upb_decoder {
// reset to a different plan.
//
// Must be called before ResetInput() or Decode().
- void ResetPlan(DecoderPlan* plan, int32_t msg_offset) {
- upb_decoder_resetplan(this, plan, msg_offset);
- }
+ void ResetPlan(DecoderPlan* plan) { upb_decoder_resetplan(this, plan); }
// Resets the input of the decoder. This puts it in a state where it has not
// seen any data, and expects the next data to be from the beginning of a new
@@ -71,7 +69,7 @@ class Decoder : public upb_decoder {
// Decodes serialized data (calling Handlers as the data is parsed) until
// error or EOF (see status() for details).
- Success Decode() { return upb_decoder_decode(this); }
+ Status::Success Decode() { return upb_decoder_decode(this); }
const upb::Status& status() {
return static_cast<const upb::Status&>(*upb_decoder_status(this));
diff --git a/bindings/cpp/upb/pb/glue.hpp b/bindings/cpp/upb/pb/glue.hpp
deleted file mode 100644
index d43baeb..0000000
--- a/bindings/cpp/upb/pb/glue.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * upb - a minimalist implementation of protocol buffers.
- *
- * Copyright (c) 2011 Google Inc. See LICENSE for details.
- * Author: Josh Haberman <jhaberman@gmail.com>
- */
-
-#ifndef UPB_PB_GLUE_HPP
-#define UPB_PB_GLUE_HPP
-
-#include "upb/upb.hpp"
-#include "upb/pb/glue.h"
-
-namespace upb {
-
-// All routines that load descriptors expect the descriptor to be a
-// FileDescriptorSet.
-bool LoadDescriptorFileIntoSymtab(SymbolTable* s, const char *fname,
- Status* status) {
- return upb_load_descriptor_file_into_symtab(s, fname, status);
-}
-
-bool LoadDescriptorIntoSymtab(SymbolTable* s, const char* str,
- size_t len, Status* status) {
- return upb_load_descriptor_into_symtab(s, str, len, status);
-}
-
-template <typename T>
-bool LoadDescriptorIntoSymtab(SymbolTable* s, const T& desc, Status* status) {
- return upb_load_descriptor_into_symtab(s, desc.c_str(), desc.size(), status);
-}
-
-} // namespace upb
-
-#endif
diff --git a/bindings/cpp/upb/proto2_bridge.cc b/bindings/cpp/upb/proto2_bridge.cc
deleted file mode 100644
index 6119295..0000000
--- a/bindings/cpp/upb/proto2_bridge.cc
+++ /dev/null
@@ -1,892 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-
-#include <string>
-#include <typeinfo>
-#include "upb/bytestream.hpp"
-#include "upb/def.hpp"
-#include "upb/handlers.hpp"
-#include "upb/msg.hpp"
-#include "upb/proto2_bridge.hpp"
-
-namespace {
-
-static void* GetFieldPointer(void *message, const upb::FieldDef* f) {
- return static_cast<char*>(message) + f->offset();
-}
-
-} // namespace
-
-#ifdef UPB_GOOGLE3
-
-// TODO(haberman): friend upb so that this isn't required.
-#define protected public
-#include "net/proto2/public/repeated_field.h"
-#undef private
-
-#define private public
-#include "net/proto/proto2_reflection.h"
-#undef private
-
-#include "net/proto2/proto/descriptor.pb.h"
-#include "net/proto2/public/descriptor.h"
-#include "net/proto2/public/generated_message_reflection.h"
-#include "net/proto2/public/lazy_field.h"
-#include "net/proto2/public/message.h"
-#include "net/proto2/public/string_piece_field_support.h"
-#include "net/proto/internal_layout.h"
-#include "strings/cord.h"
-using ::proto2::Descriptor;
-using ::proto2::EnumDescriptor;
-using ::proto2::EnumValueDescriptor;
-using ::proto2::FieldDescriptor;
-using ::proto2::FieldOptions;
-using ::proto2::FileDescriptor;
-using ::proto2::internal::GeneratedMessageReflection;
-using ::proto2::internal::RepeatedPtrFieldBase;
-using ::proto2::internal::StringPieceField;
-using ::proto2::Message;
-using ::proto2::MessageFactory;
-using ::proto2::Reflection;
-using ::proto2::RepeatedField;
-using ::proto2::RepeatedPtrField;
-
-namespace upb {
-
-static const Message* GetPrototypeForField(const Message& m,
- const FieldDescriptor* f);
-
-namespace proto2_bridge_google3 { class FieldAccessor; }
-
-using ::upb::proto2_bridge_google3::FieldAccessor;
-
-namespace proto2_bridge_google3 {
-
-static void AssignToCord(const ByteRegion* r, Cord* cord) {
- // TODO(haberman): ref source data if source is a cord.
- cord->Clear();
- uint64_t ofs = r->start_ofs();
- while (ofs < r->end_ofs()) {
- size_t len;
- const char *buf = r->GetPtr(ofs, &len);
- cord->Append(StringPiece(buf, len));
- ofs += len;
- }
-}
-
-#else
-
-// TODO(haberman): friend upb so that this isn't required.
-#define protected public
-#include "google/protobuf/repeated_field.h"
-#undef protected
-
-#define private public
-#include "google/protobuf/generated_message_reflection.h"
-#undef private
-
-#include "google/protobuf/descriptor.h"
-#include "google/protobuf/descriptor.pb.h"
-#include "google/protobuf/message.h"
-using ::google::protobuf::Descriptor;
-using ::google::protobuf::EnumDescriptor;
-using ::google::protobuf::EnumValueDescriptor;
-using ::google::protobuf::FieldDescriptor;
-using ::google::protobuf::FieldOptions;
-using ::google::protobuf::FileDescriptor;
-using ::google::protobuf::internal::GeneratedMessageReflection;
-using ::google::protobuf::internal::RepeatedPtrFieldBase;
-using ::google::protobuf::Message;
-using ::google::protobuf::MessageFactory;
-using ::google::protobuf::Reflection;
-using ::google::protobuf::RepeatedField;
-using ::google::protobuf::RepeatedPtrField;
-
-namespace upb {
-static const Message* GetPrototypeForField(const Message& m,
- const FieldDescriptor* f);
-
-namespace proto2_bridge_opensource { class FieldAccessor; }
-
-using ::upb::proto2_bridge_opensource::FieldAccessor;
-
-namespace proto2_bridge_opensource {
-
-#endif // ifdef UPB_GOOGLE3
-
-// Have to define this manually since older versions of proto2 didn't define
-// an enum value for STRING.
-#define UPB_CTYPE_STRING 0
-
-// The code in this class depends on the internal representation of the proto2
-// generated classes, which is an internal implementation detail of proto2 and
-// is not a public interface. As a result, this class's implementation may
-// need to be changed if/when proto2 changes its internal representation. It
-// is intended that this class is the only code that depends on these internal,
-// non-public interfaces.
-//
-// This class only works with messages that use GeneratedMessageReflection.
-// Other reflection classes will need other accessor implementations.
-class FieldAccessor {
- public:
- // Returns true if we were able to set an accessor and any other properties
- // of the FieldDef that are necessary to read/write this field to a
- // proto2::Message.
- static bool TrySet(const FieldDescriptor* proto2_f,
- const upb::MessageDef* md,
- upb::FieldDef* upb_f) {
- const Message* prototype = static_cast<const Message*>(md->prototype);
- const Reflection* base_r = prototype->GetReflection();
- const GeneratedMessageReflection* r =
- dynamic_cast<const GeneratedMessageReflection*>(base_r);
- // Old versions of the open-source protobuf release erroneously default to
- // Cord even though that has never been supported in the open-source
- // release.
- int32_t ctype = proto2_f->options().has_ctype() ?
- proto2_f->options().ctype() : UPB_CTYPE_STRING;
- if (!r) return false;
- // Extensions not supported yet.
- if (proto2_f->is_extension()) return false;
-
- upb_f->set_accessor(GetForFieldDescriptor(proto2_f, ctype));
- upb_f->set_hasbit(GetHasbit(proto2_f, r));
- upb_f->set_offset(GetOffset(proto2_f, r));
- if (upb_f->IsSubmessage()) {
- upb_f->set_subtype_name(proto2_f->message_type()->full_name());
- upb_f->prototype = GetPrototypeForField(*prototype, proto2_f);
- }
-
- if (upb_f->IsString() && !upb_f->IsSequence() &&
- ctype == UPB_CTYPE_STRING) {
- upb_f->prototype = &r->GetStringReference(*prototype, proto2_f, NULL);
- }
- return true;
- }
-
- static MessageFactory* GetMessageFactory(const Message& m) {
- const GeneratedMessageReflection* r =
- dynamic_cast<const GeneratedMessageReflection*>(m.GetReflection());
- return r ? r->message_factory_ : NULL;
- }
-
- private:
- static int64_t GetHasbit(const FieldDescriptor* f,
- const GeneratedMessageReflection* r) {
- if (f->is_repeated()) {
- // proto2 does not store hasbits for repeated fields.
- return -1;
- } else {
- return (r->has_bits_offset_ * 8) + f->index();
- }
- }
-
- static uint16_t GetOffset(const FieldDescriptor* f,
- const GeneratedMessageReflection* r) {
- return r->offsets_[f->index()];
- }
-
- static AccessorVTable *GetForFieldDescriptor(const FieldDescriptor* f,
- int32_t ctype) {
- switch (f->cpp_type()) {
- case FieldDescriptor::CPPTYPE_ENUM:
- // Should handlers validate enum membership to match proto2?
- case FieldDescriptor::CPPTYPE_INT32: return Get<int32_t>();
- case FieldDescriptor::CPPTYPE_INT64: return Get<int64_t>();
- case FieldDescriptor::CPPTYPE_UINT32: return Get<uint32_t>();
- case FieldDescriptor::CPPTYPE_UINT64: return Get<uint64_t>();
- case FieldDescriptor::CPPTYPE_DOUBLE: return Get<double>();
- case FieldDescriptor::CPPTYPE_FLOAT: return Get<float>();
- case FieldDescriptor::CPPTYPE_BOOL: return Get<bool>();
- case FieldDescriptor::CPPTYPE_STRING:
- switch (ctype) {
-#ifdef UPB_GOOGLE3
- case FieldOptions::STRING:
- return GetForString<string>();
- case FieldOptions::CORD:
- return GetForCord();
- case FieldOptions::STRING_PIECE:
- return GetForStringPiece();
-#else
- case UPB_CTYPE_STRING:
- return GetForString<std::string>();
-#endif
- default: return NULL;
- }
- case FieldDescriptor::CPPTYPE_MESSAGE:
-#ifdef UPB_GOOGLE3
- if (f->options().lazy()) {
- return NULL; // Not yet implemented.
- } else {
- return GetForMessage();
- }
-#else
- return GetForMessage();
-#endif
- default: return NULL;
- }
- }
-
- // PushOffset handler (used for StartSequence and others) ///////////////////
-
- static SubFlow PushOffset(void *m, Value fval) {
- const FieldDef *f = GetValue<const FieldDef*>(fval);
- return UPB_CONTINUE_WITH(GetFieldPointer(m, f));
- }
-
- // Primitive Value (numeric, enum, bool) /////////////////////////////////////
-
- template <typename T> static AccessorVTable *Get() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- GetValueHandler<T>(),
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &Append<T>,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- template <typename T>
- static Flow Append(void *_r, Value fval, Value val) {
- (void)fval;
- RepeatedField<T>* r = static_cast<RepeatedField<T>*>(_r);
- r->Add(GetValue<T>(val));
- return UPB_CONTINUE;
- }
-
- // String ////////////////////////////////////////////////////////////////////
-
- template <typename T> static AccessorVTable *GetForString() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- &SetString<T>,
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &AppendString<T>,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- // This needs to be templated because google3 string is not std::string.
- template <typename T> static Flow SetString(void *m, Value fval, Value val) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- T **str = static_cast<T**>(GetFieldPointer(m, f));
- // If it points to the default instance, we must create a new instance.
- if (*str == f->prototype) *str = new T();
- GetValue<ByteRegion*>(val)->AssignToString(*str);
- return UPB_CONTINUE;
- }
-
- template <typename T>
- static Flow AppendString(void *_r, Value fval, Value val) {
- (void)fval;
- RepeatedPtrField<T>* r = static_cast<RepeatedPtrField<T>*>(_r);
- GetValue<ByteRegion*>(val)->AssignToString(r->Add());
- return UPB_CONTINUE;
- }
-
- // SubMessage ////////////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForMessage() {
- static upb_accessor_vtbl vtbl = {
- &StartSubMessage,
- NULL, // Value handler
- &PushOffset, // StartSequence handler
- &StartRepeatedSubMessage,
- NULL, // Repeated value handler
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static SubFlow StartSubMessage(void *m, Value fval) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- void **subm = static_cast<void**>(GetFieldPointer(m, f));
- if (*subm == NULL || *subm == f->prototype) {
- const Message* prototype = static_cast<const Message*>(f->prototype);
- *subm = prototype->New();
- }
- return UPB_CONTINUE_WITH(*subm);
- }
-
- class RepeatedMessageTypeHandler {
- public:
- typedef void Type;
- // AddAllocated() calls this, but only if other objects are sitting
- // around waiting for reuse, which we will not do.
- static void Delete(Type* t) {
- (void)t;
- assert(false);
- }
- };
-
- // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
- // its base class RepeatedPtrFieldBase*.
- static SubFlow StartRepeatedSubMessage(void* _r, Value fval) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- RepeatedPtrFieldBase *r = static_cast<RepeatedPtrFieldBase*>(_r);
- void *submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
- if (!submsg) {
- const Message* prototype = static_cast<const Message*>(f->prototype);
- submsg = prototype->New();
- r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
- }
- return UPB_CONTINUE_WITH(submsg);
- }
-
- // TODO(haberman): handle Extensions, Unknown Fields.
-
-#ifdef UPB_GOOGLE3
- // Handlers for types/features only included in internal proto2 release:
- // Cord, StringPiece, LazyField, and MessageSet.
- // TODO(haberman): LazyField, MessageSet.
-
- // Cord //////////////////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForCord() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- &SetCord,
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &AppendCord,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static Flow SetCord(void *m, Value fval, Value val) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- Cord* field = static_cast<Cord*>(GetFieldPointer(m, f));
- AssignToCord(GetValue<ByteRegion*>(val), field);
- return UPB_CONTINUE;
- }
-
- static Flow AppendCord(void *_r, Value fval, Value val) {
- RepeatedField<Cord>* r = static_cast<RepeatedField<Cord>*>(_r);
- AssignToCord(GetValue<ByteRegion*>(val), r->Add());
- return UPB_CONTINUE;
- }
-
- // StringPiece ///////////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForStringPiece() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- &SetStringPiece,
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &AppendStringPiece,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static void AssignToStringPieceField(const ByteRegion* r,
- proto2::internal::StringPieceField* f) {
- // TODO(haberman): alias if possible and enabled on the input stream.
- // TODO(haberman): add a method to StringPieceField that lets us avoid
- // this copy/malloc/free.
- char *data = new char[r->Length()];
- r->Copy(r->start_ofs(), r->Length(), data);
- f->CopyFrom(StringPiece(data, r->Length()));
- delete[] data;
- }
-
- static Flow SetStringPiece(void *m, Value fval, Value val) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- StringPieceField* field =
- static_cast<StringPieceField*>(GetFieldPointer(m, f));
- AssignToStringPieceField(GetValue<ByteRegion*>(val), field);
- return UPB_CONTINUE;
- }
-
- static Flow AppendStringPiece(void* _r, Value fval, Value val) {
- RepeatedPtrField<StringPieceField>* r =
- static_cast<RepeatedPtrField<StringPieceField>*>(_r);
- AssignToStringPieceField(GetValue<ByteRegion*>(val), r->Add());
- return UPB_CONTINUE;
- }
-
-#endif // UPB_GOOGLE3
-};
-
-#ifdef UPB_GOOGLE3
-
-// Proto1 accessor -- only needed inside Google.
-class Proto1FieldAccessor {
- public:
- // Returns true if we were able to set an accessor and any other properties
- // of the FieldDef that are necessary to read/write this field to a
- // proto2::Message.
- static bool TrySet(const FieldDescriptor* proto2_f,
- const upb::MessageDef* md,
- upb::FieldDef* upb_f) {
- const Message* m = static_cast<const Message*>(md->prototype);
- const proto2::Reflection* base_r = m->GetReflection();
- const _pi::Proto2Reflection* r =
- dynamic_cast<const _pi::Proto2Reflection*>(base_r);
- if (!r) return false;
- // Extensions not supported yet.
- if (proto2_f->is_extension()) return false;
-
- const _pi::Field* f = r->GetFieldLayout(proto2_f);
-
- if (f->crep == _pi::CREP_OPTIONAL_FOREIGN_WEAK) {
- // Override the BYTES type that proto2 descriptors have for weak fields.
- upb_f->set_type(UPB_TYPE(MESSAGE));
- }
-
- if (upb_f->IsSubmessage()) {
- const Message* prototype = upb::GetPrototypeForField(*m, proto2_f);
- upb_f->set_subtype_name(prototype->GetDescriptor()->full_name());
- upb_f->prototype = prototype;
- }
-
- upb_f->set_accessor(GetForCrep(f->crep));
- upb_f->set_hasbit(GetHasbit(proto2_f, r));
- upb_f->set_offset(GetOffset(proto2_f, r));
- return true;
- }
-
- private:
- static int16_t GetHasbit(const FieldDescriptor* f,
- const _pi::Proto2Reflection* r) {
- if (f->is_repeated()) {
- // proto1 does not store hasbits for repeated fields.
- return -1;
- } else {
- return (r->layout_->has_bit_offset * 8) + r->GetFieldLayout(f)->has_index;
- }
- }
-
- static uint16_t GetOffset(const FieldDescriptor* f,
- const _pi::Proto2Reflection* r) {
- return r->GetFieldLayout(f)->offset;
- }
-
- static AccessorVTable *GetForCrep(int crep) {
-#define PRIMITIVE(name, type_name) \
- case _pi::CREP_REQUIRED_ ## name: \
- case _pi::CREP_OPTIONAL_ ## name: \
- case _pi::CREP_REPEATED_ ## name: return Get<type_name>();
-
- switch (crep) {
- PRIMITIVE(DOUBLE, double);
- PRIMITIVE(FLOAT, float);
- PRIMITIVE(INT64, int64_t);
- PRIMITIVE(UINT64, uint64_t);
- PRIMITIVE(INT32, int32_t);
- PRIMITIVE(FIXED64, uint64_t);
- PRIMITIVE(FIXED32, uint32_t);
- PRIMITIVE(BOOL, bool);
- case _pi::CREP_REQUIRED_STRING:
- case _pi::CREP_OPTIONAL_STRING:
- case _pi::CREP_REPEATED_STRING: return GetForString();
- case _pi::CREP_OPTIONAL_OUTOFLINE_STRING: return GetForOutOfLineString();
- case _pi::CREP_REQUIRED_CORD:
- case _pi::CREP_OPTIONAL_CORD:
- case _pi::CREP_REPEATED_CORD: return GetForCord();
- case _pi::CREP_REQUIRED_GROUP:
- case _pi::CREP_REQUIRED_FOREIGN:
- case _pi::CREP_REQUIRED_FOREIGN_PROTO2: return GetForRequiredMessage();
- case _pi::CREP_OPTIONAL_GROUP:
- case _pi::CREP_REPEATED_GROUP:
- case _pi::CREP_OPTIONAL_FOREIGN:
- case _pi::CREP_REPEATED_FOREIGN:
- case _pi::CREP_OPTIONAL_FOREIGN_PROTO2:
- case _pi::CREP_REPEATED_FOREIGN_PROTO2: return GetForMessage();
- case _pi::CREP_OPTIONAL_FOREIGN_WEAK: return GetForWeakMessage();
- default: assert(false); return NULL;
- }
-#undef PRIMITIVE
- }
-
- // PushOffset handler (used for StartSequence and others) ///////////////////
-
- // We can find a RepeatedField* or a RepeatedPtrField* at f->offset().
- static SubFlow PushOffset(void *m, Value fval) {
- const FieldDef *f = GetValue<const FieldDef*>(fval);
- return UPB_CONTINUE_WITH(GetFieldPointer(m, f));
- }
-
- // Primitive Value (numeric, enum, bool) /////////////////////////////////////
-
- template <typename T> static AccessorVTable *Get() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- GetValueHandler<T>(),
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &Append<T>,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- template <typename T>
- static Flow Append(void *_r, Value fval, Value val) {
- (void)fval;
- // Proto1's ProtoArray class derives from RepeatedField.
- RepeatedField<T>* r = static_cast<RepeatedField<T>*>(_r);
- r->Add(GetValue<T>(val));
- return UPB_CONTINUE;
- }
-
- // String ////////////////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForString() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- &SetString,
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &AppendString,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static Flow SetString(void *m, Value fval, Value val) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- string *str = static_cast<string*>(GetFieldPointer(m, f));
- GetValue<ByteRegion*>(val)->AssignToString(str);
- return UPB_CONTINUE;
- }
-
- static Flow AppendString(void *_r, Value fval, Value val) {
- (void)fval;
- RepeatedPtrField<string>* r = static_cast<RepeatedPtrField<string>*>(_r);
- GetValue<ByteRegion*>(val)->AssignToString(r->Add());
- return UPB_CONTINUE;
- }
-
- // Out-of-line string ////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForOutOfLineString() {
- static upb_accessor_vtbl vtbl = {
- NULL, &SetOutOfLineString,
- // This type is only used for non-repeated string fields.
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static Flow SetOutOfLineString(void *m, Value fval, Value val) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- string **str = static_cast<string**>(GetFieldPointer(m, f));
- if (*str == &::ProtocolMessage::___empty_internal_proto_string_)
- *str = new string();
- GetValue<ByteRegion*>(val)->AssignToString(*str);
- return UPB_CONTINUE;
- }
-
- // Cord //////////////////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForCord() {
- static upb_accessor_vtbl vtbl = {
- NULL, // StartSubMessage handler
- &SetCord,
- &PushOffset, // StartSequence handler
- NULL, // StartRepeatedSubMessage handler
- &AppendCord,
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static Flow SetCord(void *m, Value fval, Value val) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- Cord* field = static_cast<Cord*>(GetFieldPointer(m, f));
- AssignToCord(GetValue<ByteRegion*>(val), field);
- return UPB_CONTINUE;
- }
-
- static Flow AppendCord(void *_r, Value fval, Value val) {
- RepeatedField<Cord>* r = static_cast<RepeatedField<Cord>*>(_r);
- AssignToCord(GetValue<ByteRegion*>(val), r->Add());
- return UPB_CONTINUE;
- }
-
- // SubMessage ////////////////////////////////////////////////////////////////
-
- static AccessorVTable *GetForRequiredMessage() {
- static upb_accessor_vtbl vtbl = {
- &PushOffset, // StartSubMessage handler
- NULL, // Value handler
- &PushOffset, // StartSequence handler
- &StartRepeatedSubMessage,
- NULL, // Repeated value handler
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static AccessorVTable *GetForWeakMessage() {
- static upb_accessor_vtbl vtbl = {
- &StartWeakSubMessage, // StartSubMessage handler
- NULL, // Value handler
- &PushOffset, // StartSequence handler
- &StartRepeatedSubMessage,
- NULL, // Repeated value handler
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static AccessorVTable *GetForMessage() {
- static upb_accessor_vtbl vtbl = {
- &StartSubMessage,
- NULL, // Value handler
- &PushOffset, // StartSequence handler
- &StartRepeatedSubMessage,
- NULL, // Repeated value handler
- NULL, NULL, NULL, NULL, NULL, NULL};
- return &vtbl;
- }
-
- static SubFlow StartSubMessage(void *m, Value fval) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- Message **subm = static_cast<Message**>(GetFieldPointer(m, f));
- if (*subm == f->prototype) *subm = (*subm)->New();
- return UPB_CONTINUE_WITH(*subm);
- }
-
- static SubFlow StartWeakSubMessage(void *m, Value fval) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- Message **subm = static_cast<Message**>(GetFieldPointer(m, f));
- if (*subm == NULL) {
- const Message* prototype = static_cast<const Message*>(f->prototype);
- *subm = prototype->New();
- }
- return UPB_CONTINUE_WITH(*subm);
- }
-
- class RepeatedMessageTypeHandler {
- public:
- typedef void Type;
- // AddAllocated() calls this, but only if other objects are sitting
- // around waiting for reuse, which we will not do.
- static void Delete(Type* t) {
- (void)t;
- assert(false);
- }
- };
-
- // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
- // its base class RepeatedPtrFieldBase*.
- static SubFlow StartRepeatedSubMessage(void* _r, Value fval) {
- const FieldDef* f = GetValue<const FieldDef*>(fval);
- RepeatedPtrFieldBase *r = static_cast<RepeatedPtrFieldBase*>(_r);
- void *submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
- if (!submsg) {
- const Message* prototype = static_cast<const Message*>(f->prototype);
- submsg = prototype->New();
- r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
- }
- return UPB_CONTINUE_WITH(submsg);
- }
-};
-
-#endif
-
-} // namespace proto2_bridge_{google3,opensource}
-
-static const Message* GetPrototypeForMessage(const Message& m) {
- const Message* ret = NULL;
- MessageFactory* factory = FieldAccessor::GetMessageFactory(m);
- if (factory) {
- // proto2 generated message or DynamicMessage.
- ret = factory->GetPrototype(m.GetDescriptor());
- assert(ret);
- } else {
- // Proto1 message; since proto1 has no dynamic message, it must be
- // from the generated factory.
- ret = MessageFactory::generated_factory()->GetPrototype(m.GetDescriptor());
- assert(ret); // If NULL, then wasn't a proto1 message, can't handle it.
- }
- assert(ret->GetReflection() == m.GetReflection());
- return ret;
-}
-
-static const Message* GetPrototypeForField(const Message& m,
- const FieldDescriptor* f) {
-#ifdef UPB_GOOGLE3
- if (f->type() == FieldDescriptor::TYPE_BYTES) {
- // Proto1 weak field: the proto2 descriptor says their type is BYTES.
- const _pi::Proto2Reflection* r =
- dynamic_cast<const _pi::Proto2Reflection*>(m.GetReflection());
- assert(r);
- const _pi::Field* field = r->GetFieldLayout(f);
- assert(field->crep == _pi::CREP_OPTIONAL_FOREIGN_WEAK);
- return GetPrototypeForMessage(
- *static_cast<const Message*>(field->weak_layout()->default_instance));
- } else if (dynamic_cast<const _pi::Proto2Reflection*>(m.GetReflection())) {
- // Proto1 message; since proto1 has no dynamic message, it must be from
- // the generated factory.
- const Message* ret =
- MessageFactory::generated_factory()->GetPrototype(f->message_type());
- assert(ret);
- return ret;
- }
-#endif
- assert(f->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
- // We assume that all submessages (and extensions) will be constructed using
- // the same MessageFactory as this message. This doesn't cover the case of
- // CodedInputStream::SetExtensionRegistry().
- MessageFactory* factory = FieldAccessor::GetMessageFactory(m);
- assert(factory); // If neither proto1 nor proto2 we can't handle it.
- const Message* ret = factory->GetPrototype(f->message_type());
- assert(ret);
- return ret;
-}
-
-namespace proto2_bridge {
-
-upb::FieldDef* AddFieldDef(const FieldDescriptor* f, upb::MessageDef* md) {
- upb::FieldDef* upb_f = upb::FieldDef::New(&upb_f);
- upb_f->set_number(f->number());
- upb_f->set_name(f->name());
- upb_f->set_label(static_cast<upb::Label>(f->label()));
- upb_f->set_type(static_cast<upb::FieldType>(f->type()));
-
- if (!FieldAccessor::TrySet(f, md, upb_f)
-#ifdef UPB_GOOGLE3
- && !proto2_bridge_google3::Proto1FieldAccessor::TrySet(f, md, upb_f)
-#endif
- ) {
- // Unsupported reflection class.
- assert(false);
- }
-
- if (upb_f->type() == UPB_TYPE(ENUM)) {
- // We set the enum default symbolically.
- upb_f->set_default(f->default_value_enum()->name());
- upb_f->set_subtype_name(f->enum_type()->full_name());
- } else {
- // Set field default for primitive types. Need to switch on the upb type
- // rather than the proto2 type, because upb_f->type() may have been changed
- // from BYTES to MESSAGE for a weak field.
- switch (upb_types[upb_f->type()].inmemory_type) {
- case UPB_CTYPE_INT32:
- upb_f->set_default(MakeValue(f->default_value_int32()));
- break;
- case UPB_CTYPE_INT64:
- upb_f->set_default(
- MakeValue(static_cast<int64_t>(f->default_value_int64())));
- break;
- case UPB_CTYPE_UINT32:
- upb_f->set_default(MakeValue(f->default_value_uint32()));
- break;
- case UPB_CTYPE_UINT64:
- upb_f->set_default(
- MakeValue(static_cast<uint64_t>(f->default_value_uint64())));
- break;
- case UPB_CTYPE_DOUBLE:
- upb_f->set_default(MakeValue(f->default_value_double()));
- break;
- case UPB_CTYPE_FLOAT:
- upb_f->set_default(MakeValue(f->default_value_float()));
- break;
- case UPB_CTYPE_BOOL:
- upb_f->set_default(MakeValue(f->default_value_bool()));
- break;
- case UPB_CTYPE_BYTEREGION:
- upb_f->set_default(f->default_value_string());
- break;
- }
- }
- return md->AddField(upb_f, &upb_f) ? upb_f : NULL;
-}
-
-upb::MessageDef *NewEmptyMessageDef(const Message& m, void *owner) {
- upb::MessageDef *md = upb::MessageDef::New(owner);
- md->set_full_name(m.GetDescriptor()->full_name());
- md->prototype = GetPrototypeForMessage(m);
- return md;
-}
-
-upb::EnumDef* NewEnumDef(const EnumDescriptor* desc, void *owner) {
- upb::EnumDef* e = upb::EnumDef::New(owner);
- e->set_full_name(desc->full_name());
- for (int i = 0; i < desc->value_count(); i++) {
- const EnumValueDescriptor* val = desc->value(i);
- bool success = e->AddValue(val->name(), val->number());
- assert(success);
- (void)success;
- }
- return e;
-}
-
-void AddAllFields(upb::MessageDef* md) {
- const Descriptor* d =
- static_cast<const Message*>(md->prototype)->GetDescriptor();
- for (int i = 0; i < d->field_count(); i++) {
-#ifdef UPB_GOOGLE3
- // Skip lazy fields for now since we can't properly handle them.
- if (d->field(i)->options().lazy()) continue;
-#endif
- // Extensions not supported yet.
- if (d->field(i)->is_extension()) continue;
- AddFieldDef(d->field(i), md);
- }
-}
-
-upb::MessageDef *NewFullMessageDef(const Message& m, void *owner) {
- upb::MessageDef* md = NewEmptyMessageDef(m, owner);
- AddAllFields(md);
- // TODO(haberman): add unknown field handler and extensions.
- return md;
-}
-
-typedef std::map<std::string, upb::Def*> SymbolMap;
-
-static upb::MessageDef* NewFinalMessageDefHelper(const Message& m, void *owner,
- SymbolMap* symbols) {
- upb::MessageDef* md = NewFullMessageDef(m, owner);
- // Must do this before processing submessages to prevent infinite recursion.
- (*symbols)[std::string(md->full_name())] = md->AsDef();
-
- for (upb::MessageDef::Iterator i(md); !i.Done(); i.Next()) {
- upb::FieldDef* f = i.field();
- if (!f->HasSubDef()) continue;
- SymbolMap::iterator iter = symbols->find(f->subtype_name());
- upb::Def* subdef;
- if (iter != symbols->end()) {
- subdef = iter->second;
- } else {
- const FieldDescriptor* proto2_f =
- m.GetDescriptor()->FindFieldByNumber(f->number());
- if (f->type() == UPB_TYPE(ENUM)) {
- subdef = NewEnumDef(proto2_f->enum_type(), owner)->AsDef();
- (*symbols)[std::string(subdef->full_name())] = subdef;
- } else {
- assert(f->IsSubmessage());
- const Message* prototype = GetPrototypeForField(m, proto2_f);
- subdef = NewFinalMessageDefHelper(*prototype, owner, symbols)->AsDef();
- }
- }
- f->set_subdef(subdef);
- }
- return md;
-}
-
-const upb::MessageDef* NewFinalMessageDef(const Message& m, void *owner) {
- SymbolMap symbols;
- upb::MessageDef* ret = NewFinalMessageDefHelper(m, owner, &symbols);
-
- // Finalize defs.
- std::vector<upb::Def*> defs;
- SymbolMap::iterator iter;
- for (iter = symbols.begin(); iter != symbols.end(); ++iter) {
- defs.push_back(iter->second);
- }
- Status status;
- bool success = Def::Finalize(defs, &status);
- assert(success);
- (void)success;
-
- // Unref all defs except the top-level one that we are returning.
- for (int i = 0; i < static_cast<int>(defs.size()); i++) {
- if (defs[i] != ret->AsDef()) defs[i]->Unref(owner);
- }
-
- return ret;
-}
-
-} // namespace proto2_bridge
-} // namespace upb
diff --git a/bindings/cpp/upb/proto2_bridge.hpp b/bindings/cpp/upb/proto2_bridge.hpp
deleted file mode 100644
index ace08ce..0000000
--- a/bindings/cpp/upb/proto2_bridge.hpp
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011-2012 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-//
-// A bridge between upb and proto2, allows populating proto2 generated
-// classes using upb's parser, translating between descriptors and defs, etc.
-//
-// This is designed to be able to be compiled against either the open-source
-// version of protocol buffers or the Google-internal proto2. The two are
-// the same in most ways, but live in different namespaces (proto2 vs
-// google::protobuf) and have a few other more minor differences.
-//
-// The bridge gives you a lot of control over which fields will be written to
-// the message (fields that are not written will just be skipped), and whether
-// unknown fields are written to the UnknownFieldSet. This can save a lot of
-// work if the client only cares about some subset of the fields.
-//
-// Example usage:
-//
-// // Build a def that will have all fields and parse just like proto2 would.
-// const upb::MessageDef* md = upb::proto2_bridge::NewMessageDef(&MyProto());
-//
-// // JIT the parser; should only be done once ahead-of-time.
-// upb::Handlers* handlers = upb::NewHandlersForMessage(md);
-// upb::DecoderPlan* plan = upb::DecoderPlan::New(handlers);
-// handlers->Unref();
-//
-// // The actual parsing.
-// MyProto proto;
-// upb::Decoder decoder;
-// upb::StringSource source(buf, len);
-// decoder.ResetPlan(plan, 0);
-// decoder.ResetInput(source.AllBytes(), &proto);
-// CHECK(decoder.Decode() == UPB_OK) << decoder.status();
-//
-// To parse only one field and skip all others:
-//
-// const upb::MessageDef* md =
-// upb::proto2_bridge::NewEmptyMessageDef(MyProto().GetPrototype());
-// upb::proto2_bridge::AddFieldDef(
-// MyProto::descriptor()->FindFieldByName("my_field"), md);
-// upb::Finalize(md);
-//
-// // Now continue with "JIT the parser" from above.
-//
-// Note that there is currently no support for
-// CodedInputStream::SetExtensionRegistry(), which allows specifying a separate
-// DescriptorPool and MessageFactory for extensions. Since this is a property
-// of the input in proto2, it's difficult to build a plan ahead-of-time that
-// can properly support this. If it's an important use case, the caller should
-// probably build a upb plan explicitly.
-
-#ifndef UPB_PROTO2_BRIDGE
-#define UPB_PROTO2_BRIDGE
-
-#include <vector>
-
-namespace google {
-namespace protobuf {
-class Descriptor;
-class EnumDescriptor;
-class FieldDescriptor;
-class FileDescriptor;
-class Message;
-} // namespace google
-} // namespace protobuf
-
-namespace proto2 {
-class Descriptor;
-class EnumDescriptor;
-class FieldDescriptor;
-class FileDescriptor;
-class Message;
-} // namespace proto2
-
-
-namespace upb {
-
-class Def;
-class FieldDef;
-class MessageDef;
-
-namespace proto2_bridge {
-
-// Unfinalized defs ////////////////////////////////////////////////////////////
-
-// Creating of UNFINALIZED defs. All of these functions return defs that are
-// still mutable and have not been finalized. They must be finalized before
-// using them to parse anything. This is useful if you want more control over
-// the process of constructing defs, eg. to add the specific set of fields you
-// care about.
-
-// Creates a new upb::MessageDef that corresponds to the type in the given
-// prototype message. The MessageDef will not have any fields added to it.
-upb::MessageDef *NewEmptyMessageDef(const proto2::Message& m, void *owner);
-upb::MessageDef *NewEmptyMessageDef(const google::protobuf::Message& desc,
- void *owner);
-
-// Adds a new upb::FieldDef to the given MessageDef corresponding to the given
-// FieldDescriptor. The FieldDef will be given an accessor and offset so that
-// it can be used to read and write data into the proto2::Message classes.
-// The given MessageDef must have been constructed with NewEmptyDefForMessage()
-// and f->containing_type() must correspond to the message that was used.
-//
-// Any submessage, group, or enum fields will be given symbolic references to
-// the subtype, which must be resolved before the MessageDef can be finalized.
-//
-// On success, returns the FieldDef that was added (caller does not own a ref).
-// If an existing field had the same name or number, returns NULL.
-upb::FieldDef* AddFieldDef(const proto2::FieldDescriptor* f,
- upb::MessageDef* md);
-upb::FieldDef* AddFieldDef(const google::protobuf::FieldDescriptor* f,
- upb::MessageDef* md);
-
-// Given a MessageDef that was constructed with NewEmptyDefForMessage(), adds
-// FieldDefs for all fields defined in the original message, but not for any
-// extensions or unknown fields. The given MessageDef must not have any fields
-// that have the same name or number as any of the fields we are adding (the
-// easiest way to guarantee this is to start with an empty MessageDef).
-//
-// Returns true on success or false if any of the fields could not be added.
-void AddAllFields(upb::MessageDef* md);
-
-// TODO(haberman): Add:
-// // Adds a handler that will store unknown fields in the UnknownFieldSet.
-// void AddUnknownFieldHandler(upb::MessageDef* md);
-
-// Returns a new upb::MessageDef that contains handlers for all fields, unknown
-// fields, and any extensions in the descriptor's pool. The resulting
-// def/handlers should be equivalent to the generated code constructed by the
-// protobuf compiler (or the code in DynamicMessage) for the given type.
-// The subdefs for message/enum fields (if any) will be referenced symbolically,
-// and will need to be resolved before being finalized.
-//
-// TODO(haberman): Add missing support (LazyField, MessageSet, and extensions).
-//
-// TODO(haberman): possibly add a similar function that lets you supply a
-// separate DescriptorPool and MessageFactory for extensions, to support
-// proto2's io::CodedInputStream::SetExtensionRegistry().
-upb::MessageDef* NewFullMessageDef(const proto2::Message& m, void *owner);
-upb::MessageDef* NewFullMessageDef(const google::protobuf::Message& m,
- void *owner);
-
-// Returns a new upb::EnumDef that corresponds to the given EnumDescriptor.
-// Caller owns a ref on the returned EnumDef.
-upb::EnumDef* NewEnumDef(const proto2::EnumDescriptor* desc, void *owner);
-upb::EnumDef* NewEnumDef(const google::protobuf::EnumDescriptor* desc,
- void *owner);
-
-// Finalized defs //////////////////////////////////////////////////////////////
-
-// These functions return FINALIZED defs, meaning that they are immutable and
-// ready for use. Since they are immutable you cannot make any further changes
-// to eg. the set of fields, but these functions are more convenient if you
-// simply want to parse a message exactly how the built-in proto2 parser would.
-
-// Creates a returns a finalized MessageDef for the give message and its entire
-// type tree that will include all fields and unknown handlers (ie. it will
-// parse just like proto2 would).
-const upb::MessageDef* NewFinalMessageDef(const proto2::Message& m,
- void *owner);
-const upb::MessageDef* NewFinalMessageDef(const google::protobuf::Message& m,
- void *owner);
-
-} // namespace proto2_bridge
-} // namespace upb
-
-#endif
diff --git a/bindings/cpp/upb/upb.hpp b/bindings/cpp/upb/upb.hpp
deleted file mode 100644
index 48c2708..0000000
--- a/bindings/cpp/upb/upb.hpp
+++ /dev/null
@@ -1,81 +0,0 @@
-//
-// upb - a minimalist implementation of protocol buffers.
-//
-// Copyright (c) 2011 Google Inc. See LICENSE for details.
-// Author: Josh Haberman <jhaberman@gmail.com>
-
-#ifndef UPB_HPP
-#define UPB_HPP
-
-#include "upb/upb.h"
-#include <iostream>
-
-#if defined(__GXX_EXPERIMENTAL_CXX0X__) && !defined(UPB_NO_CXX11)
-#define UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(class_name) \
- class_name() = delete; \
- ~class_name() = delete;
-#else
-#define UPB_DISALLOW_CONSTRUCT_AND_DESTRUCT(class_name) \
- class_name(); \
- ~class_name();
-#endif
-
-namespace upb {
-
-typedef upb_success_t Success;
-
-class Status : public upb_status {
- public:
- Status() { upb_status_init(this); }
- ~Status() { upb_status_uninit(this); }
-
- bool ok() const { return upb_ok(this); }
- bool eof() const { return upb_eof(this); }
-
- const char *GetString() const { return upb_status_getstr(this); }
- void SetEof() { upb_status_seteof(this); }
- void SetErrorLiteral(const char* msg) {
- upb_status_seterrliteral(this, msg);
- }
-
- void Clear() { upb_status_clear(this); }
-};
-
-typedef upb_value Value;
-
-template <typename T> T GetValue(Value v);
-template <typename T> Value MakeValue(T v);
-
-#define UPB_VALUE_ACCESSORS(type, ctype) \
- template <> inline ctype GetValue<ctype>(Value v) { \
- return upb_value_get ## type(v); \
- } \
- template <> inline Value MakeValue<ctype>(ctype v) { \
- return upb_value_ ## type(v); \
- }
-
-UPB_VALUE_ACCESSORS(double, double);
-UPB_VALUE_ACCESSORS(float, float);
-UPB_VALUE_ACCESSORS(int32, int32_t);
-UPB_VALUE_ACCESSORS(int64, int64_t);
-UPB_VALUE_ACCESSORS(uint32, uint32_t);
-UPB_VALUE_ACCESSORS(uint64, uint64_t);
-UPB_VALUE_ACCESSORS(bool, bool);
-
-#undef UPB_VALUE_ACCESSORS
-
-template <typename T> inline T* GetPtrValue(Value v) {
- return static_cast<T*>(upb_value_getptr(v));
-}
-template <typename T> inline Value MakePtrValue(T* v) {
- return upb_value_ptr(static_cast<void*>(v));
-}
-
-INLINE std::ostream& operator<<(std::ostream& out, const Status& status) {
- out << status.GetString();
- return out;
-}
-
-} // namespace upb
-
-#endif
diff --git a/bindings/linux/Makefile b/bindings/linux/Makefile
index e98aa3c..1736b61 100644
--- a/bindings/linux/Makefile
+++ b/bindings/linux/Makefile
@@ -1,7 +1,6 @@
obj-m = upb.o
upb-objs = \
- setjmp.o \
../../upb/upb.o \
../../upb/bytestream.o \
../../upb/def.o \
@@ -9,9 +8,6 @@ upb-objs = \
../../upb/table.o \
../../upb/refcount.o \
../../upb/msg.o \
- ../../upb/pb/decoder.o \
- ../../upb/pb/textprinter.o \
- ../../upb/pb/varint.o \
KVERSION = $(shell uname -r)
diff --git a/bindings/linux/ctype.h b/bindings/linux/ctype.h
deleted file mode 100644
index b6cbda5..0000000
--- a/bindings/linux/ctype.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * upb - a minimalist implementation of protocol buffers.
- *
- * Copyright (c) 2012 Google Inc. See LICENSE for details.
- * Author: Josh Haberman <jhaberman@gmail.com>
- */
-
-#include <linux/ctype.h>
diff --git a/bindings/linux/inttypes.h b/bindings/linux/inttypes.h
deleted file mode 100644
index e7a6e42..0000000
--- a/bindings/linux/inttypes.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * upb - a minimalist implementation of protocol buffers.
- *
- * Copyright (c) 2012 Google Inc. See LICENSE for details.
- * Author: Josh Haberman <jhaberman@gmail.com>
- */
-
-#ifndef PRId64
-#define PRId64 "ld"
-#endif
-
-#ifndef PRIu64
-#define PRIu64 "lu"
-#endif
-
-#ifndef PRId32
-#define PRId32 "d"
-#endif
-
-#ifndef PRIu32
-#define PRIu32 "u"
-#endif
diff --git a/bindings/linux/setjmp.S b/bindings/linux/setjmp.S
deleted file mode 100644
index 5eea4be..0000000
--- a/bindings/linux/setjmp.S
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003 Peter Wemm.
- * Copyright (c) 1993 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-.globl _setjmp, _longjmp
-
-_setjmp:
- movq %rbx,0(%rdi) /* save rbx */
- movq %rsp,8(%rdi) /* save rsp */
- movq %rbp,16(%rdi) /* save rbp */
- movq %r12,24(%rdi) /* save r12 */
- movq %r13,32(%rdi) /* save r13 */
- movq %r14,40(%rdi) /* save r14 */
- movq %r15,48(%rdi) /* save r15 */
- movq 0(%rsp),%rdx /* get rta */
- movq %rdx,56(%rdi) /* save rip */
- xorl %eax,%eax /* return(0); */
- ret
-
-_longjmp:
- movq 0(%rdi),%rbx /* restore rbx */
- movq 8(%rdi),%rsp /* restore rsp */
- movq 16(%rdi),%rbp /* restore rbp */
- movq 24(%rdi),%r12 /* restore r12 */
- movq 32(%rdi),%r13 /* restore r13 */
- movq 40(%rdi),%r14 /* restore r14 */
- movq 48(%rdi),%r15 /* restore r15 */
- movq 56(%rdi),%rdx /* get rta */
- movq %rdx,0(%rsp) /* put in return frame */
- xorl %eax,%eax /* return(1); */
- incl %eax
- ret
diff --git a/bindings/linux/setjmp.h b/bindings/linux/setjmp.h
deleted file mode 100644
index c4716e6..0000000
--- a/bindings/linux/setjmp.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * upb - a minimalist implementation of protocol buffers.
- *
- * Copyright (c) 2012 Google Inc. See LICENSE for details.
- * Author: Josh Haberman <jhaberman@gmail.com>
- */
-
-// Linux doesn't provide setjmp/longjmp, boo.
-
-typedef void *jmp_buf[8];
-
-extern int _setjmp(jmp_buf env);
-__attribute__((__noreturn__)) extern void _longjmp(jmp_buf env, int val);
diff --git a/bindings/linux/string.h b/bindings/linux/string.h
index 69de3fa..30ebf8a 100644
--- a/bindings/linux/string.h
+++ b/bindings/linux/string.h
@@ -9,18 +9,5 @@
#define UPB_LINUX_STRING_H_
#include <linux/string.h>
-#include <stdlib.h>
-#include "upb/upb.h" // For INLINE.
-
-INLINE char *strdup(const char *s) {
- size_t len = strlen(s);
- char *ret = malloc(len + 1);
- if (ret == NULL) return NULL;
- // Be particularly defensive and guard against buffer overflow if there
- // is a concurrent mutator.
- strncpy(ret, s, len);
- ret[len] = '\0';
- return ret;
-}
#endif /* UPB_DEF_H_ */
diff --git a/bindings/lua/LICENSE b/bindings/lua/LICENSE
new file mode 100644
index 0000000..fb720fe
--- /dev/null
+++ b/bindings/lua/LICENSE
@@ -0,0 +1,32 @@
+
+Lunit License
+-------------
+
+Lunit is written by Michael Roth <mroth@nessie.de> and is licensed
+under the terms of the MIT license reproduced below.
+
+========================================================================
+
+Copyright (c) 2004-2010 Michael Roth <mroth@nessie.de>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software,
+and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+========================================================================
+
diff --git a/bindings/lua/lunitx/atexit.lua b/bindings/lua/lunitx/atexit.lua
new file mode 100644
index 0000000..c3cdddc
--- /dev/null
+++ b/bindings/lua/lunitx/atexit.lua
@@ -0,0 +1,32 @@
+
+local actions = {}
+
+local atexit
+
+if _VERSION >= 'Lua 5.2' then
+
+ atexit = function (fn)
+ actions[#actions+1] = setmetatable({}, { __gc = fn })
+ end
+
+else
+
+ local newproxy = newproxy
+ local debug = debug
+ local assert = assert
+ local setmetatable = setmetatable
+
+ local function gc(fn)
+ local p = assert(newproxy())
+ assert(debug.setmetatable(p, { __gc = fn }))
+ return p
+ end
+
+ atexit = function (fn)
+ actions[#actions+1] = gc(fn)
+ end
+
+end
+
+return atexit
+
diff --git a/bindings/lua/lunitx/lunit.lua b/bindings/lua/lunitx/lunit.lua
new file mode 100644
index 0000000..8fa87de
--- /dev/null
+++ b/bindings/lua/lunitx/lunit.lua
@@ -0,0 +1,725 @@
+--[[--------------------------------------------------------------------------
+
+ This file is part of lunit 0.5.
+
+ For Details about lunit look at: http://www.mroth.net/lunit/
+
+ Author: Michael Roth <mroth@nessie.de>
+
+ Copyright (c) 2004, 2006-2010 Michael Roth <mroth@nessie.de>
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+--]]--------------------------------------------------------------------------
+
+
+local orig_assert = assert
+
+local pairs = pairs
+local ipairs = ipairs
+local next = next
+local type = type
+local error = error
+local tostring = tostring
+local setmetatable = setmetatable
+local pcall = pcall
+local xpcall = xpcall
+local require = require
+local loadfile = loadfile
+
+local string_sub = string.sub
+local string_gsub = string.gsub
+local string_format = string.format
+local string_lower = string.lower
+local string_find = string.find
+
+local table_concat = table.concat
+
+local debug_getinfo = debug.getinfo
+
+local _G = _G
+
+local lunit
+
+if _VERSION >= 'Lua 5.2' then
+
+ lunit = {}
+ _ENV = lunit
+
+else
+
+ module("lunit")
+ lunit = _M
+
+end
+
+
+local __failure__ = {} -- Type tag for failed assertions
+
+local typenames = { "nil", "boolean", "number", "string", "table", "function", "thread", "userdata" }
+
+
+local traceback_hide -- Traceback function which hides lunit internals
+local mypcall -- Protected call to a function with own traceback
+do
+ local _tb_hide = setmetatable( {}, {__mode="k"} )
+
+ function traceback_hide(func)
+ _tb_hide[func] = true
+ end
+
+ local function my_traceback(errobj)
+ if is_table(errobj) and errobj.type == __failure__ then
+ local info = debug_getinfo(5, "Sl") -- FIXME: Hardcoded integers are bad...
+ errobj.where = string_format( "%s:%d", info.short_src, info.currentline)
+ else
+ errobj = { msg = tostring(errobj) }
+ errobj.tb = {}
+ local i = 2
+ while true do
+ local info = debug_getinfo(i, "Snlf")
+ if not is_table(info) then
+ break
+ end
+ if not _tb_hide[info.func] then
+ local line = {} -- Ripped from ldblib.c...
+ line[#line+1] = string_format("%s:", info.short_src)
+ if info.currentline > 0 then
+ line[#line+1] = string_format("%d:", info.currentline)
+ end
+ if info.namewhat ~= "" then
+ line[#line+1] = string_format(" in function '%s'", info.name)
+ else
+ if info.what == "main" then
+ line[#line+1] = " in main chunk"
+ elseif info.what == "C" or info.what == "tail" then
+ line[#line+1] = " ?"
+ else
+ line[#line+1] = string_format(" in function <%s:%d>", info.short_src, info.linedefined)
+ end
+ end
+ errobj.tb[#errobj.tb+1] = table_concat(line)
+ end
+ i = i + 1
+ end
+ end
+ return errobj
+ end
+
+ function mypcall(func)
+ orig_assert( is_function(func) )
+ local ok, errobj = xpcall(func, my_traceback)
+ if not ok then
+ return errobj
+ end
+ end
+ traceback_hide(mypcall)
+end
+
+
+-- Type check functions
+
+for _, typename in ipairs(typenames) do
+ lunit["is_"..typename] = function(x)
+ return type(x) == typename
+ end
+end
+
+local is_nil = is_nil
+local is_boolean = is_boolean
+local is_number = is_number
+local is_string = is_string
+local is_table = is_table
+local is_function = is_function
+local is_thread = is_thread
+local is_userdata = is_userdata
+
+
+local function failure(name, usermsg, defaultmsg, ...)
+ local errobj = {
+ type = __failure__,
+ name = name,
+ msg = string_format(defaultmsg,...),
+ usermsg = usermsg
+ }
+ error(errobj, 0)
+end
+traceback_hide( failure )
+
+
+local function format_arg(arg)
+ local argtype = type(arg)
+ if argtype == "string" then
+ return "'"..arg.."'"
+ elseif argtype == "number" or argtype == "boolean" or argtype == "nil" then
+ return tostring(arg)
+ else
+ return "["..tostring(arg).."]"
+ end
+end
+
+
+local function selected(map, name)
+ if not map then
+ return true
+ end
+
+ local m = {}
+ for k,v in pairs(map) do
+ m[k] = lunitpat2luapat(v)
+ end
+ return in_patternmap(m, name)
+end
+
+
+function fail(msg)
+ stats.assertions = stats.assertions + 1
+ failure( "fail", msg, "failure" )
+end
+traceback_hide( fail )
+
+
+function assert(assertion, msg)
+ stats.assertions = stats.assertions + 1
+ if not assertion then
+ failure( "assert", msg, "assertion failed" )
+ end
+ return assertion
+end
+traceback_hide( assert )
+
+
+function assert_true(actual, msg)
+ stats.assertions = stats.assertions + 1
+ if actual ~= true then
+ failure( "assert_true", msg, "true expected but was %s", format_arg(actual) )
+ end
+ return actual
+end
+traceback_hide( assert_true )
+
+
+function assert_false(actual, msg)
+ stats.assertions = stats.assertions + 1
+ if actual ~= false then
+ failure( "assert_false", msg, "false expected but was %s", format_arg(actual) )
+ end
+ return actual
+end
+traceback_hide( assert_false )
+
+
+function assert_equal(expected, actual, msg)
+ stats.assertions = stats.assertions + 1
+ if expected ~= actual then
+ failure( "assert_equal", msg, "expected %s but was %s", format_arg(expected), format_arg(actual) )
+ end
+ return actual
+end
+traceback_hide( assert_equal )
+
+
+function assert_not_equal(unexpected, actual, msg)
+ stats.assertions = stats.assertions + 1
+ if unexpected == actual then
+ failure( "assert_not_equal", msg, "%s not expected but was one", format_arg(unexpected) )
+ end
+ return actual
+end
+traceback_hide( assert_not_equal )
+
+
+function assert_match(pattern, actual, msg)
+ stats.assertions = stats.assertions + 1
+ if type(pattern) ~= "string" then
+ failure( "assert_match", msg, "expected a string as pattern but was %s", format_arg(pattern) )
+ end
+ if type(actual) ~= "string" then
+ failure( "assert_match", msg, "expected a string to match pattern '%s' but was a %s", pattern, format_arg(actual) )
+ end
+ if not string_find(actual, pattern) then
+ failure( "assert_match", msg, "expected '%s' to match pattern '%s' but doesn't", actual, pattern )
+ end
+ return actual
+end
+traceback_hide( assert_match )
+
+
+function assert_not_match(pattern, actual, msg)
+ stats.assertions = stats.assertions + 1
+ if type(pattern) ~= "string" then
+ failure( "assert_not_match", msg, "expected a string as pattern but was %s", format_arg(pattern) )
+ end
+ if type(actual) ~= "string" then
+ failure( "assert_not_match", msg, "expected a string to not match pattern '%s' but was %s", pattern, format_arg(actual) )
+ end
+ if string_find(actual, pattern) then
+ failure( "assert_not_match", msg, "expected '%s' to not match pattern '%s' but it does", actual, pattern )
+ end
+ return actual
+end
+traceback_hide( assert_not_match )
+
+
+function assert_error(msg, func)
+ stats.assertions = stats.assertions + 1
+ if func == nil then
+ func, msg = msg, nil
+ end
+ if type(func) ~= "function" then
+ failure( "assert_error", msg, "expected a function as last argument but was %s", format_arg(func) )
+ end
+ local ok, errmsg = pcall(func)
+ if ok then
+ failure( "assert_error", msg, "error expected but no error occurred" )
+ end
+end
+traceback_hide( assert_error )
+
+
+function assert_error_match(msg, pattern, func)
+ stats.assertions = stats.assertions + 1
+ if func == nil then
+ msg, pattern, func = nil, msg, pattern
+ end
+ if type(pattern) ~= "string" then
+ failure( "assert_error_match", msg, "expected the pattern as a string but was %s", format_arg(pattern) )
+ end
+ if type(func) ~= "function" then
+ failure( "assert_error_match", msg, "expected a function as last argument but was %s", format_arg(func) )
+ end
+ local ok, errmsg = pcall(func)
+ if ok then
+ failure( "assert_error_match", msg, "error expected but no error occurred" )
+ end
+ if type(errmsg) ~= "string" then
+ failure( "assert_error_match", msg, "error as string expected but was %s", format_arg(errmsg) )
+ end
+ if not string_find(errmsg, pattern) then
+ failure( "assert_error_match", msg, "expected error '%s' to match pattern '%s' but doesn't", errmsg, pattern )
+ end
+end
+traceback_hide( assert_error_match )
+
+
+function assert_pass(msg, func)
+ stats.assertions = stats.assertions + 1
+ if func == nil then
+ func, msg = msg, nil
+ end
+ if type(func) ~= "function" then
+ failure( "assert_pass", msg, "expected a function as last argument but was %s", format_arg(func) )
+ end
+ local ok, errmsg = pcall(func)
+ if not ok then
+ failure( "assert_pass", msg, "no error expected but error was: '%s'", errmsg )
+ end
+end
+traceback_hide( assert_pass )
+
+
+-- lunit.assert_typename functions
+
+for _, typename in ipairs(typenames) do
+ local assert_typename = "assert_"..typename
+ lunit[assert_typename] = function(actual, msg)
+ stats.assertions = stats.assertions + 1
+ if type(actual) ~= typename then
+ failure( assert_typename, msg, "%s expected but was %s", typename, format_arg(actual) )
+ end
+ return actual
+ end
+ traceback_hide( lunit[assert_typename] )
+end
+
+
+-- lunit.assert_not_typename functions
+
+for _, typename in ipairs(typenames) do
+ local assert_not_typename = "assert_not_"..typename
+ lunit[assert_not_typename] = function(actual, msg)
+ stats.assertions = stats.assertions + 1
+ if type(actual) == typename then
+ failure( assert_not_typename, msg, typename.." not expected but was one" )
+ end
+ end
+ traceback_hide( lunit[assert_not_typename] )
+end
+
+
+function lunit.clearstats()
+ stats = {
+ assertions = 0;
+ passed = 0;
+ failed = 0;
+ errors = 0;
+ }
+end
+
+
+local report, reporterrobj
+do
+ local testrunner
+
+ function lunit.setrunner(newrunner)
+ if not ( is_table(newrunner) or is_nil(newrunner) ) then
+ return error("lunit.setrunner: Invalid argument", 0)
+ end
+ local oldrunner = testrunner
+ testrunner = newrunner
+ return oldrunner
+ end
+
+ function lunit.loadrunner(name)
+ if not is_string(name) then
+ return error("lunit.loadrunner: Invalid argument", 0)
+ end
+ local ok, runner = pcall( require, name )
+ if not ok then
+ return error("lunit.loadrunner: Can't load test runner: "..runner, 0)
+ end
+ return setrunner(runner)
+ end
+
+ function lunit.getrunner()
+ return testrunner
+ end
+
+ function report(event, ...)
+ local f = testrunner and testrunner[event]
+ if is_function(f) then
+ pcall(f, ...)
+ end
+ end
+
+ function reporterrobj(context, tcname, testname, errobj)
+ local fullname = tcname .. "." .. testname
+ if context == "setup" then
+ fullname = fullname .. ":" .. setupname(tcname, testname)
+ elseif context == "teardown" then
+ fullname = fullname .. ":" .. teardownname(tcname, testname)
+ end
+ if errobj.type == __failure__ then
+ stats.failed = stats.failed + 1
+ report("fail", fullname, errobj.where, errobj.msg, errobj.usermsg)
+ else
+ stats.errors = stats.errors + 1
+ report("err", fullname, errobj.msg, errobj.tb)
+ end
+ end
+end
+
+
+
+local function key_iter(t, k)
+ return (next(t,k))
+end
+
+
+local testcase
+do
+ -- Array with all registered testcases
+ local _testcases = {}
+
+ -- Marks a module as a testcase.
+ -- Applied over a module from module("xyz", lunit.testcase).
+ function lunit.testcase(m)
+ orig_assert( is_table(m) )
+ --orig_assert( m._M == m )
+ orig_assert( is_string(m._NAME) )
+ --orig_assert( is_string(m._PACKAGE) )
+
+ -- Register the module as a testcase
+ _testcases[m._NAME] = m
+
+ -- Import lunit, fail, assert* and is_* function to the module/testcase
+ m.lunit = lunit
+ m.fail = lunit.fail
+ for funcname, func in pairs(lunit) do
+ if "assert" == string_sub(funcname, 1, 6) or "is_" == string_sub(funcname, 1, 3) then
+ m[funcname] = func
+ end
+ end
+ end
+
+ function lunit.module(name,seeall)
+ local m = {}
+ if seeall == "seeall" then
+ setmetatable(m, { __index = _G })
+ end
+ m._NAME = name
+ lunit.testcase(m)
+ return m
+ end
+
+ -- Iterator (testcasename) over all Testcases
+ function lunit.testcases()
+ -- Make a copy of testcases to prevent confusing the iterator when
+ -- new testcase are defined
+ local _testcases2 = {}
+ for k,v in pairs(_testcases) do
+ _testcases2[k] = true
+ end
+ return key_iter, _testcases2, nil
+ end
+
+ function testcase(tcname)
+ return _testcases[tcname]
+ end
+end
+
+
+do
+ -- Finds a function in a testcase case insensitive
+ local function findfuncname(tcname, name)
+ for key, value in pairs(testcase(tcname)) do
+ if is_string(key) and is_function(value) and string_lower(key) == name then
+ return key
+ end
+ end
+ end
+
+ function lunit.setupname(tcname)
+ return findfuncname(tcname, "setup")
+ end
+
+ function lunit.teardownname(tcname)
+ return findfuncname(tcname, "teardown")
+ end
+
+ -- Iterator over all test names in a testcase.
+ -- Have to collect the names first in case one of the test
+ -- functions creates a new global and throws off the iteration.
+ function lunit.tests(tcname)
+ local testnames = {}
+ for key, value in pairs(testcase(tcname)) do
+ if is_string(key) and is_function(value) then
+ local lfn = string_lower(key)
+ if string_sub(lfn, 1, 4) == "test" or string_sub(lfn, -4) == "test" then
+ testnames[key] = true
+ end
+ end
+ end
+ return key_iter, testnames, nil
+ end
+end
+
+
+
+
+function lunit.runtest(tcname, testname)
+ orig_assert( is_string(tcname) )
+ orig_assert( is_string(testname) )
+
+ if (not getrunner()) then
+ loadrunner("lunit.console")
+ end
+
+ local function callit(context, func)
+ if func then
+ local err = mypcall(func)
+ if err then
+ reporterrobj(context, tcname, testname, err)
+ return false
+ end
+ end
+ return true
+ end
+ traceback_hide(callit)
+
+ report("run", tcname, testname)
+
+ local tc = testcase(tcname)
+ local setup = tc[setupname(tcname)]
+ local test = tc[testname]
+ local teardown = tc[teardownname(tcname)]
+
+ local setup_ok = callit( "setup", setup )
+ local test_ok = setup_ok and callit( "test", test )
+ local teardown_ok = setup_ok and callit( "teardown", teardown )
+
+ if setup_ok and test_ok and teardown_ok then
+ stats.passed = stats.passed + 1
+ report("pass", tcname, testname)
+ end
+end
+traceback_hide(runtest)
+
+
+
+function lunit.run(testpatterns)
+ clearstats()
+ report("begin")
+ for testcasename in lunit.testcases() do
+ -- Run tests in the testcases
+ for testname in lunit.tests(testcasename) do
+ if selected(testpatterns, testname) then
+ runtest(testcasename, testname)
+ end
+ end
+ end
+ report("done")
+ return stats
+end
+traceback_hide(run)
+
+
+function lunit.loadonly()
+ clearstats()
+ report("begin")
+ report("done")
+ return stats
+end
+
+
+
+
+
+
+
+
+
+local lunitpat2luapat
+do
+ local conv = {
+ ["^"] = "%^",
+ ["$"] = "%$",
+ ["("] = "%(",
+ [")"] = "%)",
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["["] = "%[",
+ ["]"] = "%]",
+ ["+"] = "%+",
+ ["-"] = "%-",
+ ["?"] = ".",
+ ["*"] = ".*"
+ }
+ function lunitpat2luapat(str)
+ --return "^" .. string.gsub(str, "%W", conv) .. "$"
+ -- Above was very annoying, if I want to run all the tests having to do with
+ -- RSS, I want to be able to do "-t rss" not "-t \*rss\*".
+ return string_gsub(str, "%W", conv)
+ end
+end
+
+
+
+local function in_patternmap(map, name)
+ if map[name] == true then
+ return true
+ else
+ for _, pat in ipairs(map) do
+ if string_find(name, pat) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
+
+
+
+
+
+
+
+-- Called from 'lunit' shell script.
+
+function main(argv)
+ argv = argv or {}
+
+ -- FIXME: Error handling and error messages aren't nice.
+
+ local function checkarg(optname, arg)
+ if not is_string(arg) then
+ return error("lunit.main: option "..optname..": argument missing.", 0)
+ end
+ end
+
+ local function loadtestcase(filename)
+ if not is_string(filename) then
+ return error("lunit.main: invalid argument")
+ end
+ local chunk, err = loadfile(filename)
+ if err then
+ return error(err)
+ else
+ chunk()
+ end
+ end
+
+ local testpatterns = nil
+ local doloadonly = false
+
+ local i = 0
+ while i < #argv do
+ i = i + 1
+ local arg = argv[i]
+ if arg == "--loadonly" then
+ doloadonly = true
+ elseif arg == "--runner" or arg == "-r" then
+ local optname = arg; i = i + 1; arg = argv[i]
+ checkarg(optname, arg)
+ loadrunner(arg)
+ elseif arg == "--test" or arg == "-t" then
+ local optname = arg; i = i + 1; arg = argv[i]
+ checkarg(optname, arg)
+ testpatterns = testpatterns or {}
+ testpatterns[#testpatterns+1] = arg
+ elseif arg == "--help" or arg == "-h" then
+ print[[
+lunit 0.5
+Copyright (c) 2004-2009 Michael Roth <mroth@nessie.de>
+This program comes WITHOUT WARRANTY OF ANY KIND.
+
+Usage: lua test [OPTIONS] [--] scripts
+
+Options:
+
+ -r, --runner RUNNER Testrunner to use, defaults to 'lunit-console'.
+ -t, --test PATTERN Which tests to run, may contain * or ? wildcards.
+ --loadonly Only load the tests.
+ -h, --help Print this help screen.
+
+Please report bugs to <mroth@nessie.de>.
+]]
+ return
+ elseif arg == "--" then
+ while i < #argv do
+ i = i + 1; arg = argv[i]
+ loadtestcase(arg)
+ end
+ else
+ loadtestcase(arg)
+ end
+ end
+
+ if doloadonly then
+ return loadonly()
+ else
+ return run(testpatterns)
+ end
+end
+
+clearstats()
+
+return lunit
diff --git a/bindings/lua/lunitx/lunit/console.lua b/bindings/lua/lunitx/lunit/console.lua
new file mode 100644
index 0000000..0ff22a4
--- /dev/null
+++ b/bindings/lua/lunitx/lunit/console.lua
@@ -0,0 +1,156 @@
+
+--[[--------------------------------------------------------------------------
+
+ This file is part of lunit 0.5.
+
+ For Details about lunit look at: http://www.mroth.net/lunit/
+
+ Author: Michael Roth <mroth@nessie.de>
+
+ Copyright (c) 2006-2008 Michael Roth <mroth@nessie.de>
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+--]]--------------------------------------------------------------------------
+
+
+
+--[[
+
+ begin()
+ run(testcasename, testname)
+ err(fullname, message, traceback)
+ fail(fullname, where, message, usermessage)
+ pass(testcasename, testname)
+ done()
+
+ Fullname:
+ testcase.testname
+ testcase.testname:setupname
+ testcase.testname:teardownname
+
+--]]
+
+
+lunit = require "lunit"
+
+local lunit_console
+
+if _VERSION >= 'Lua 5.2' then
+
+ lunit_console = setmetatable({},{__index = _ENV})
+ _ENV = lunit_console
+
+else
+
+ module( "lunit-console", package.seeall )
+ lunit_console = _M
+
+end
+
+
+
+local function printformat(format, ...)
+ io.write( string.format(format, ...) )
+end
+
+
+local columns_printed = 0
+
+local function writestatus(char)
+ if columns_printed == 0 then
+ io.write(" ")
+ end
+ if columns_printed == 60 then
+ io.write("\n ")
+ columns_printed = 0
+ end
+ io.write(char)
+ io.flush()
+ columns_printed = columns_printed + 1
+end
+
+
+local msgs = {}
+
+
+function begin()
+ local total_tc = 0
+ local total_tests = 0
+
+ msgs = {} -- e
+
+ for tcname in lunit.testcases() do
+ total_tc = total_tc + 1
+ for testname, test in lunit.tests(tcname) do
+ total_tests = total_tests + 1
+ end
+ end
+
+ printformat("Loaded testsuite with %d tests in %d testcases.\n\n", total_tests, total_tc)
+end
+
+
+function run(testcasename, testname)
+ -- NOP
+end
+
+
+function err(fullname, message, traceback)
+ writestatus("E")
+ msgs[#msgs+1] = "Error! ("..fullname.."):\n"..message.."\n\t"..table.concat(traceback, "\n\t") .. "\n"
+end
+
+
+function fail(fullname, where, message, usermessage)
+ writestatus("F")
+ local text = "Failure ("..fullname.."):\n"..
+ where..": "..message.."\n"
+
+ if usermessage then
+ text = text .. where..": "..usermessage.."\n"
+ end
+
+ msgs[#msgs+1] = text
+end
+
+
+function pass(testcasename, testname)
+ writestatus(".")
+end
+
+
+
+function done()
+ printformat("\n\n%d Assertions checked.\n", lunit.stats.assertions )
+ print()
+
+ for i, msg in ipairs(msgs) do
+ printformat( "%3d) %s\n", i, msg )
+ end
+
+ printformat("Testsuite finished (%d passed, %d failed, %d errors).\n",
+ lunit.stats.passed, lunit.stats.failed, lunit.stats.errors )
+end
+
+
+return lunit_console
+
+
diff --git a/bindings/lua/lunitx/lunitx.lua b/bindings/lua/lunitx/lunitx.lua
new file mode 100644
index 0000000..7656e6a
--- /dev/null
+++ b/bindings/lua/lunitx/lunitx.lua
@@ -0,0 +1,21 @@
+local atexit = require "atexit"
+local lunit = require "lunit"
+
+--for k,v in pairs(debug.getinfo(1,"S")) do print(k,v) end
+-- autonameing
+-- module("bcrc-test", lunit.testcase, package.seeall)
+
+atexit(function()
+ local _, emsg = xpcall(function()
+ lunit.main(arg)
+ end, debug.traceback)
+ if emsg then
+ print(emsg)
+ os.exit(1)
+ end
+ if lunit.stats.failed > 0 or lunit.stats.errors > 0 then
+ os.exit(1)
+ end
+end)
+
+return lunit
diff --git a/bindings/lua/table.c b/bindings/lua/table.c
new file mode 100644
index 0000000..31b92d2
--- /dev/null
+++ b/bindings/lua/table.c
@@ -0,0 +1,167 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * Lua extension that provides access to upb_table. This is an internal-only
+ * interface and exists for the sole purpose of writing a C code generator in
+ * Lua that can dump a upb_table as static C initializers. This lets us use
+ * Lua for convenient string manipulation while saving us from re-implementing
+ * the upb_table hash function and hash table layout / collision strategy in
+ * Lua.
+ *
+ * Since this is used only as part of the toolchain (and not part of the
+ * runtime) we do not hold this module to the same stringent requirements as
+ * the main Lua modules (for example that misbehaving Lua programs cannot
+ * crash the interpreter).
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lauxlib.h"
+#include "bindings/lua/upb.h"
+#include "upb/def.h"
+
+static void lupbtable_setnum(lua_State *L, int tab, const char *key,
+ lua_Number val) {
+ lua_pushnumber(L, val);
+ lua_setfield(L, tab - 1, key);
+}
+
+static void lupbtable_pushval(lua_State *L, upb_value val, upb_ctype_t type) {
+ switch (type) {
+ case UPB_CTYPE_INT32:
+ lua_pushnumber(L, upb_value_getint32(val));
+ break;
+ case UPB_CTYPE_PTR:
+ lupb_def_pushwrapper(L, upb_value_getptr(val), NULL);
+ break;
+ case UPB_CTYPE_CSTR:
+ lua_pushstring(L, upb_value_getcstr(val));
+ break;
+ default:
+ luaL_error(L, "Unexpected type: %d", type);
+ }
+}
+
+// Sets a few fields common to both hash table entries and arrays.
+static void lupbtable_setmetafields(lua_State *L, int type, const void *ptr) {
+ // We tack this onto every entry so we know it even if the entries
+ // don't stay with the table.
+ lua_pushnumber(L, type);
+ lua_setfield(L, -2, "valtype");
+
+ // Set this to facilitate linking.
+ lua_pushlightuserdata(L, (void*)ptr);
+ lua_setfield(L, -2, "ptr");
+}
+
+static void lupbtable_pushent(lua_State *L, const upb_tabent *e,
+ bool inttab, int type) {
+ lua_newtable(L);
+ if (!upb_tabent_isempty(e)) {
+ if (inttab) {
+ lua_pushnumber(L, e->key.num);
+ } else {
+ lua_pushstring(L, e->key.str);
+ }
+ lua_setfield(L, -2, "key");
+ lupbtable_pushval(L, e->val, type);
+ lua_setfield(L, -2, "value");
+ }
+ lua_pushlightuserdata(L, (void*)e->next);
+ lua_setfield(L, -2, "next");
+ lupbtable_setmetafields(L, type, e);
+}
+
+// Dumps the shared part of upb_table into a Lua table.
+static void lupbtable_pushtable(lua_State *L, const upb_table *t, bool inttab) {
+ lua_newtable(L);
+ lupbtable_setnum(L, -1, "count", t->count);
+ lupbtable_setnum(L, -1, "mask", t->mask);
+ lupbtable_setnum(L, -1, "type", t->type);
+ lupbtable_setnum(L, -1, "size_lg2", t->size_lg2);
+
+ lua_newtable(L);
+ for (int i = 0; i < upb_table_size(t); i++) {
+ lupbtable_pushent(L, &t->entries[i], inttab, t->type);
+ lua_rawseti(L, -2, i + 1);
+ }
+ lua_setfield(L, -2, "entries");
+}
+
+// Dumps a upb_inttable to a Lua table.
+static void lupbtable_pushinttable(lua_State *L, const upb_inttable *t) {
+ lupbtable_pushtable(L, &t->t, true);
+ lupbtable_setnum(L, -1, "array_size", t->array_size);
+ lupbtable_setnum(L, -1, "array_count", t->array_count);
+
+ lua_newtable(L);
+ for (int i = 0; i < t->array_size; i++) {
+ lua_newtable(L);
+ if (upb_arrhas(t->array[i])) {
+ lupbtable_pushval(L, t->array[i], t->t.type);
+ lua_setfield(L, -2, "val");
+ }
+ lupbtable_setmetafields(L, t->t.type, &t->array[i]);
+ lua_rawseti(L, -2, i + 1);
+ }
+ lua_setfield(L, -2, "array");
+}
+
+static void lupbtable_pushstrtable(lua_State *L, const upb_strtable *t) {
+ lupbtable_pushtable(L, &t->t, false);
+}
+
+static int lupbtable_msgdef_itof(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ lupbtable_pushinttable(L, &m->itof);
+ return 1;
+}
+
+static int lupbtable_msgdef_ntof(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ lupbtable_pushstrtable(L, &m->ntof);
+ return 1;
+}
+
+static int lupbtable_enumdef_iton(lua_State *L) {
+ const upb_enumdef *e = lupb_enumdef_check(L, 1);
+ lupbtable_pushinttable(L, &e->iton);
+ return 1;
+}
+
+static int lupbtable_enumdef_ntoi(lua_State *L) {
+ const upb_enumdef *e = lupb_enumdef_check(L, 1);
+ lupbtable_pushstrtable(L, &e->ntoi);
+ return 1;
+}
+
+static void lupbtable_setfieldi(lua_State *L, const char *field, int i) {
+ lua_pushnumber(L, i);
+ lua_setfield(L, -2, field);
+}
+
+static const struct luaL_Reg lupbtable_toplevel_m[] = {
+ {"msgdef_itof", lupbtable_msgdef_itof},
+ {"msgdef_ntof", lupbtable_msgdef_ntof},
+ {"enumdef_iton", lupbtable_enumdef_iton},
+ {"enumdef_ntoi", lupbtable_enumdef_ntoi},
+ {NULL, NULL}
+};
+
+int luaopen_upbtable(lua_State *L) {
+ lupb_newlib(L, "upb.table", lupbtable_toplevel_m);
+
+ // We define these here because they are not public (at least at the moment).
+ lupbtable_setfieldi(L, "CTYPE_PTR", UPB_CTYPE_PTR);
+ lupbtable_setfieldi(L, "CTYPE_INT32", UPB_CTYPE_INT32);
+
+ lua_pushlightuserdata(L, NULL);
+ lua_setfield(L, -2, "NULL");
+
+ return 1; // Return a single Lua value, the package table created above.
+}
diff --git a/bindings/lua/test.lua b/bindings/lua/test.lua
index 42bce25..6b162a9 100644
--- a/bindings/lua/test.lua
+++ b/bindings/lua/test.lua
@@ -1,109 +1,262 @@
-require "upb"
+local upb = require "upb"
+local lunit = require "lunitx"
-symtab = upb.SymbolTable{
- upb.MessageDef{fqname="A", fields={
- upb.FieldDef{name="a", type=upb.TYPE_INT32, number=1},
- upb.FieldDef{name="b", type=upb.TYPE_DOUBLE, number=2}}
+if _VERSION >= 'Lua 5.2' then
+ _ENV = lunit.module("testupb", "seeall")
+else
+ module("testupb", lunit.testcase, package.seeall)
+end
+
+function test_fielddef()
+ local f = upb.FieldDef()
+ assert_false(f:is_frozen())
+ assert_nil(f:number())
+ assert_nil(f:name())
+ assert_equal(upb.LABEL_OPTIONAL, f:label())
+
+ f:set_name("foo_field")
+ f:set_number(3)
+ f:set_label(upb.LABEL_REPEATED)
+ f:set_type(upb.TYPE_FLOAT)
+
+ assert_equal("foo_field", f:name())
+ assert_equal(3, f:number())
+ assert_equal(upb.LABEL_REPEATED, f:label())
+ assert_equal(upb.TYPE_FLOAT, f:type())
+
+ local f2 = upb.FieldDef{
+ name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED
}
-}
-
-symtab = upb.SymbolTable{
- upb.MessageDef{fqname="A", fields={
- upb.FieldDef{name="a", type=upb.TYPE_INT32, number=1},
- upb.FieldDef{name="b", type=upb.TYPE_DOUBLE, number=2}}
- },
- upb.MessageDef{fqname="B"}
-}
-A, B, C = symtab:lookup("A", "B")
-print(A)
-print(B)
-print(C)
-
-a = A()
-a2 = upb.Message(A)
-print("YO! a.a=" .. tostring(a.a) .. ", a2.a=" .. tostring(a2.a))
-a.a = 2
-a2.a = 3
-print("YO! a.a=" .. tostring(a.a) .. ", a2.a=" .. tostring(a2.a))
-
-A = symtab:lookup("A")
-if not A then
- error("Could not find A")
+
+ assert_equal("foo", f2:name())
+ assert_equal(5, f2:number())
+ assert_equal(upb.TYPE_DOUBLE, f2:type())
+ assert_equal(upb.LABEL_REQUIRED, f2:label())
end
-f = io.open("../../upb/descriptor.pb")
-if not f then
- error("Couldn't open descriptor.pb, try running 'make descriptorgen'")
+function test_enumdef()
+ local e = upb.EnumDef()
+ assert_equal(0, #e)
+ assert_nil(e:value(5))
+ assert_nil(e:value("NONEXISTENT_NAME"))
+
+ for name, value in e:values() do
+ fail()
+ end
+
+ e:add("VAL1", 1)
+ e:add("VAL2", 2)
+
+ local values = {}
+ for name, value in e:values() do
+ values[name] = value
+ end
+
+ assert_equal(1, values["VAL1"])
+ assert_equal(2, values["VAL2"])
+
+ local e2 = upb.EnumDef{
+ values = {
+ {"FOO", 1},
+ {"BAR", 77},
+ }
+ }
+
+ assert_equal(1, e2:value("FOO"))
+ assert_equal(77, e2:value("BAR"))
+ assert_equal("FOO", e2:value(1))
+ assert_equal("BAR", e2:value(77))
end
-symtab:parsedesc(f:read("*all"))
-symtab:load_descriptor()
-symtab:load_descriptor_file()
-upb.pb.load_descriptor(f:read("*all"))
+function test_empty_msgdef()
+ local md = upb.MessageDef()
+ assert_nil(md:full_name()) -- Def without name is anonymous.
+ assert_false(md:is_frozen())
+ assert_equal(0, #md)
+ assert_nil(md:field("nonexistent_field"))
+ assert_nil(md:field(3))
+ for field in md:fields() do
+ fail()
+ end
+
+ upb.freeze(md)
+ assert_true(md:is_frozen())
+ assert_equal(0, #md)
+ assert_nil(md:field("nonexistent_field"))
+ assert_nil(md:field(3))
+ for field in md:fields() do
+ fail()
+ end
+end
+
+function test_msgdef_constructor()
+ local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32}
+ local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32}
+ local md = upb.MessageDef{
+ full_name = "TestMessage",
+ fields = {f1, f2}
+ }
+ assert_equal("TestMessage", md:full_name())
+ assert_false(md:is_frozen())
+ assert_equal(2, #md)
+ assert_equal(f1, md:field("field1"))
+ assert_equal(f2, md:field("field2"))
+ assert_equal(f1, md:field(7))
+ assert_equal(f2, md:field(8))
+ local count = 0
+ local found = {}
+ for field in md:fields() do
+ count = count + 1
+ found[field] = true
+ end
+ assert_equal(2, count)
+ assert_true(found[f1])
+ assert_true(found[f2])
-upb.pb.load_descriptor_file("../../src/descriptor.pb", symtab)
+ upb.freeze(md)
+end
+
+function test_msgdef_setters()
+ local md = upb.MessageDef()
+ md:set_full_name("Message1")
+ assert_equal("Message1", md:full_name())
+ local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE}
+ md:add{f}
+ assert_equal(1, #md)
+ assert_equal(f, md:field("field1"))
+end
+
+function test_msgdef_errors()
+ assert_error(function() upb.MessageDef{bad_initializer_key = 5} end)
+ local md = upb.MessageDef()
+ assert_error(function()
+ -- Duplicate field number.
+ upb.MessageDef{
+ fields = {
+ upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32}
+ }
+ }
+ end)
+ assert_error(function()
+ -- Duplicate field name.
+ upb.MessageDef{
+ fields = {
+ upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32}
+ }
+ }
+ end)
+
+ -- attempt to set a name with embedded NULLs.
+ assert_error_match("names cannot have embedded NULLs", function()
+ md:set_full_name("abc\0def")
+ end)
+
+ upb.freeze(md)
+ -- Attempt to mutate frozen MessageDef.
+ -- TODO(haberman): better error message and test for message.
+ assert_error(function()
+ md:add{upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}}
+ end)
+ assert_error(function()
+ md:set_full_name("abc")
+ end)
+
+ -- Attempt to freeze a msgdef without freezing its subdef.
+ assert_error_match("is not frozen or being frozen", function()
+ m1 = upb.MessageDef()
+ upb.freeze(
+ upb.MessageDef{
+ fields = {
+ upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE,
+ subdef = m1}
+ }
+ }
+ )
+ end)
+end
+
+function test_symtab()
+ local empty = upb.SymbolTable()
+ assert_equal(0, #empty:getdefs(upb.DEF_ANY))
+
+ local symtab = upb.SymbolTable{
+ upb.MessageDef{full_name = "TestMessage"},
+ upb.MessageDef{full_name = "ContainingMessage", fields = {
+ upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE,
+ subdef_name = ".TestMessage"}
+ }
+ }
+ }
+
+ local msgdef1 = symtab:lookup("TestMessage")
+ local msgdef2 = symtab:lookup("ContainingMessage")
+ assert_not_nil(msgdef1)
+ assert_not_nil(msgdef2)
+ assert_equal(msgdef1, msgdef2:field("field2"):subdef())
+ assert_true(msgdef1:is_frozen())
+ assert_true(msgdef2:is_frozen())
+
+ symtab:add{
+ upb.MessageDef{full_name = "ContainingMessage2", fields = {
+ upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE,
+ subdef = msgdef2}
+ }
+ }
+ }
+
+ local msgdef3 = symtab:lookup("ContainingMessage2")
+ assert_not_nil(msgdef3)
+ assert_equal(msgdef3:field("field5"):subdef(), msgdef2)
+end
-f = io.open("../../benchmarks/google_messages.proto.pb")
-if not f then
- error("Couldn't open google_messages.proto.pb, try running 'make benchmarks'")
+-- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer
+-- can be defined in Lua.
+if _VERSION >= 'Lua 5.2' then
+ function defer(fn)
+ setmetatable({}, { __gc = fn })
+ end
+else
+ function defer(fn)
+ getmetatable(newproxy(true)).__gc = fn
+ end
end
-symtab:parsedesc(f:read("*all"))
-for _, def in ipairs(symtab:getdefs(-1)) do
- print(def:name())
+function test_finalizer()
+ -- Tests that we correctly handle a call into an already-finalized object.
+ -- Collectible objects are finalized in the opposite order of creation.
+ do
+ local t = {}
+ defer(function()
+ assert_error_match("called into dead def", function()
+ -- Generic def call.
+ t[1]:full_name()
+ end)
+ assert_error_match("called into dead msgdef", function()
+ -- Specific msgdef call.
+ t[1]:add()
+ end)
+ assert_error_match("called into dead enumdef", function()
+ t[2]:values()
+ end)
+ assert_error_match("called into dead fielddef", function()
+ t[3]:number()
+ end)
+ assert_error_match("called into dead symtab",
+ function() t[4]:lookup()
+ end)
+ end)
+ t = {
+ upb.MessageDef(),
+ upb.EnumDef(),
+ upb.FieldDef(),
+ upb.SymbolTable(),
+ }
+ end
+ collectgarbage()
end
-SpeedMessage1 = symtab:lookup("benchmarks.SpeedMessage1")
-SpeedMessage2 = symtab:lookup("benchmarks.SpeedMessage2")
-print(SpeedMessage1:name())
-
-msg = MyType()
-msg:Decode(str)
-
-msg:DecodeJSON(str)
-
-msg = upb.pb.decode(str, MyType)
-str = upb.pb.encode(msg)
-
-msg = upb.pb.decode_text(str, MyType)
-str = upb.pb.encode_text(msg)
-
-upb.clear(msg)
-upb.msgdef(msg)
-upb.has(msg, "foo_bar")
-
-msg = upb.json.decode(str, MyType)
-
-msg = upb.pb.DecodeText(str)
-msg = upb.pb.EncodeText(msg)
-upb.
-
-upb.pb.decode_into(msg, str)
-
-str = upb.json.Encode(msg)
-upb.json.DecodeInto(msg, str)
-f = assert(io.open("../../benchmarks/google_message1.dat"))
-msg:Parse(f:read("*all"))
-print(msg:ToText())
-print(upb.json.encode(msg))
-
-msg = SpeedMessage2()
-f = assert(io.open("../../benchmarks/google_message2.dat"))
-msg:Parse(f:read("*all"))
-print(msg:ToText())
---msg:Serialize()
---msg:FromText(str)
--- print(msg.field129)
--- print(msg.field271)
---print(msg.field15.field15)
---msg.field15.field15 = "my override"
---print(msg.field15.field15)
--- print(msg.field1)
--- print(msg.field1)
--- msg.field1 = "YEAH BABY!"
--- print(msg.field1)
--- print(msg.field129)
--- msg.field129 = 5
--- print(msg.field129)
---]]
+lunit.main()
diff --git a/bindings/lua/upb.c b/bindings/lua/upb.c
index 4cce4b6..1a1d7c0 100644
--- a/bindings/lua/upb.c
+++ b/bindings/lua/upb.c
@@ -4,96 +4,85 @@
* Copyright (c) 2009 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
- * A Lua extension for upb.
+ * A Lua extension for upb. Exposes only the core library
+ * (sub-libraries are exposed in other extensions).
*/
-#include <stdlib.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
#include "lauxlib.h"
-#include "upb/def.h"
-#include "upb/msg.h"
+#include "bindings/lua/upb.h"
+#include "upb/bytestream.h"
#include "upb/pb/glue.h"
-#if LUA_VERSION_NUM == 501
-#define lua_rawlen lua_objlen
-#endif
+// Lua metatable types.
+#define LUPB_MSGDEF "lupb.msgdef"
+#define LUPB_ENUMDEF "lupb.enumdef"
+#define LUPB_FIELDDEF "lupb.fielddef"
+#define LUPB_SYMTAB "lupb.symtab"
-static bool streql(const char *a, const char *b) { return strcmp(a, b) == 0; }
+// Other table constants.
+#define LUPB_OBJCACHE "lupb.objcache"
-static bool lupb_isint(double n) { return (double)(int)n == n; }
+#if LUA_VERSION_NUM == 501
-static uint8_t lupb_touint8(lua_State *L, int narg, const char *name) {
- lua_Number n = lua_tonumber(L, narg);
- if (n > UINT8_MAX || n < 0 || rint(n) != n)
- luaL_error(L, "Invalid %s", name);
- return n;
+// Taken from Lua 5.2's source.
+void *luaL_testudata(lua_State *L, int ud, const char *tname) {
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ luaL_getmetatable(L, tname); /* get correct metatable */
+ if (!lua_rawequal(L, -1, -2)) /* not the same? */
+ p = NULL; /* value is a userdata with wrong metatable */
+ lua_pop(L, 2); /* remove both metatables */
+ return p;
+ }
+ }
+ return NULL; /* value is not a userdata with a metatable */
}
-static uint32_t lupb_touint32(lua_State *L, int narg, const char *name) {
- lua_Number n = lua_tonumber(L, narg);
- if (n > UINT32_MAX || n < 0 || rint(n) != n)
- luaL_error(L, "Invalid %s", name);
- return n;
+#elif LUA_VERSION_NUM == 502
+
+int luaL_typerror(lua_State *L, int narg, const char *tname) {
+ const char *msg = lua_pushfstring(L, "%s expected, got %s",
+ tname, luaL_typename(L, narg));
+ return luaL_argerror(L, narg, msg);
}
-static void lupb_pushstring(lua_State *L, const upb_strref *ref) {
- if (ref->ptr) {
- lua_pushlstring(L, ref->ptr, ref->len);
- } else {
- // Lua requires a continguous string; must copy+allocate.
- char *str = upb_strref_dup(ref);
- lua_pushlstring(L, str, ref->len);
- free(str);
- }
+#else
+#error Only Lua 5.1 and 5.2 are supported
+#endif
+
+const char *lupb_checkname(lua_State *L, int narg) {
+ size_t len;
+ const char *name = luaL_checklstring(L, narg, &len);
+ if (strlen(name) != len)
+ luaL_error(L, "names cannot have embedded NULLs");
+ return name;
}
-static void lupb_pushvalue(lua_State *L, upb_value val, upb_fielddef *f) {
- switch (f->type) {
- case UPB_TYPE(INT32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(SFIXED32):
- case UPB_TYPE(ENUM):
- lua_pushnumber(L, upb_value_getint32(val)); break;
- case UPB_TYPE(INT64):
- case UPB_TYPE(SINT64):
- case UPB_TYPE(SFIXED64):
- lua_pushnumber(L, upb_value_getint64(val)); break;
- case UPB_TYPE(UINT32):
- case UPB_TYPE(FIXED32):
- lua_pushnumber(L, upb_value_getuint32(val)); break;
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64):
- lua_pushnumber(L, upb_value_getuint64(val)); break;
- case UPB_TYPE(DOUBLE):
- lua_pushnumber(L, upb_value_getdouble(val)); break;
- case UPB_TYPE(FLOAT):
- lua_pushnumber(L, upb_value_getfloat(val)); break;
- case UPB_TYPE(BOOL):
- lua_pushboolean(L, upb_value_getbool(val)); break;
- default: luaL_error(L, "internal error");
- }
+static bool streql(const char *a, const char *b) { return strcmp(a, b) == 0; }
+
+static uint32_t lupb_checkint32(lua_State *L, int narg, const char *name) {
+ lua_Number n = lua_tonumber(L, narg);
+ if (n > INT32_MAX || n < INT32_MIN || rint(n) != n)
+ luaL_error(L, "Invalid %s", name);
+ return n;
}
-// Returns a scalar value (ie. not a submessage) as a upb_value.
-static upb_value lupb_getvalue(lua_State *L, int narg, upb_fielddef *f,
- upb_strref *ref) {
- assert(!upb_issubmsg(f));
+// Converts a number or bool from Lua -> upb_value.
+static upb_value lupb_getvalue(lua_State *L, int narg, upb_fieldtype_t type) {
upb_value val;
- if (upb_fielddef_type(f) == UPB_TYPE(BOOL)) {
+ if (type == UPB_TYPE(BOOL)) {
if (!lua_isboolean(L, narg))
luaL_error(L, "Must explicitly pass true or false for boolean fields");
upb_value_setbool(&val, lua_toboolean(L, narg));
- } else if (upb_fielddef_type(f) == UPB_TYPE(STRING)) {
- size_t len;
- ref->ptr = luaL_checklstring(L, narg, &len);
- ref->len = len;
- upb_value_setstrref(&val, ref);
} else {
// Numeric type.
- lua_Number num = 0;
- num = luaL_checknumber(L, narg);
- switch (upb_fielddef_type(f)) {
+ lua_Number num = luaL_checknumber(L, narg);
+ switch (type) {
case UPB_TYPE(INT32):
case UPB_TYPE(SINT32):
case UPB_TYPE(SFIXED32):
@@ -133,374 +122,743 @@ static upb_value lupb_getvalue(lua_State *L, int narg, upb_fielddef *f,
luaL_error(L, "Cannot convert %f to float", num);
upb_value_setfloat(&val, num);
break;
+ default: luaL_error(L, "invalid type");
}
}
return val;
}
-static void lupb_typecheck(lua_State *L, int narg, upb_fielddef *f) {
- upb_strref ref;
- lupb_getvalue(L, narg, f, &ref);
+// Converts a upb_value -> Lua value.
+static void lupb_pushvalue(lua_State *L, upb_value val, upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE(INT32):
+ case UPB_TYPE(SINT32):
+ case UPB_TYPE(SFIXED32):
+ case UPB_TYPE(ENUM):
+ lua_pushnumber(L, upb_value_getint32(val)); break;
+ case UPB_TYPE(INT64):
+ case UPB_TYPE(SINT64):
+ case UPB_TYPE(SFIXED64):
+ lua_pushnumber(L, upb_value_getint64(val)); break;
+ case UPB_TYPE(UINT32):
+ case UPB_TYPE(FIXED32):
+ lua_pushnumber(L, upb_value_getuint32(val)); break;
+ case UPB_TYPE(UINT64):
+ case UPB_TYPE(FIXED64):
+ lua_pushnumber(L, upb_value_getuint64(val)); break;
+ case UPB_TYPE(DOUBLE):
+ lua_pushnumber(L, upb_value_getdouble(val)); break;
+ case UPB_TYPE(FLOAT):
+ lua_pushnumber(L, upb_value_getfloat(val)); break;
+ case UPB_TYPE(BOOL):
+ lua_pushboolean(L, upb_value_getbool(val)); break;
+ case UPB_TYPE(STRING):
+ case UPB_TYPE(BYTES): {
+ const upb_byteregion *r = upb_value_getbyteregion(val);
+ size_t len;
+ const char *str = upb_byteregion_getptr(r, 0, &len);
+ lua_pushlstring(L, str, len);
+ }
+ default: luaL_error(L, "internal error");
+ }
}
-//static void lupb_msg_getorcreate(lua_State *L, upb_msg *msg, upb_msgdef *md);
-static void lupb_fielddef_getorcreate(lua_State *L, upb_fielddef *f);
-static upb_msgdef *lupb_msgdef_check(lua_State *L, int narg);
-static void lupb_msg_pushnew(lua_State *L, const void *md);
-
void lupb_checkstatus(lua_State *L, upb_status *s) {
if (!upb_ok(s)) {
- // Need to copy the string to the stack, so we can free it and not leak
- // it (since luaL_error() does not return).
- const char *str = upb_status_getstr(s);
- char buf[strlen(str)+1];
- strcpy(buf, str);
+ lua_pushstring(L, upb_status_getstr(s));
+ upb_status_uninit(s);
+ lua_error(L);
+ } else {
upb_status_uninit(s);
- luaL_error(L, "%s", buf);
}
- upb_status_uninit(s);
}
-/* object cache ***************************************************************/
+/* refcounted *****************************************************************/
+
+// All upb objects that use upb_refcounted share a common Lua userdata
+// representation and a common scheme for caching Lua wrapper object. They do
+// however have different metatables. Objects are cached in a weak table
+// indexed by the C pointer of the object they are caching.
+
+typedef union {
+ const upb_refcounted *refcounted;
+ const upb_def *def;
+ upb_symtab *symtab;
+} lupb_refcounted;
-// We cache all the lua objects (userdata) we vend in a weak table, indexed by
-// the C pointer of the object they are caching.
+static bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj,
+ const char *type, const void *owner) {
+ if (obj == NULL) {
+ lua_pushnil(L);
+ return false;
+ }
-static void *lupb_cache_getorcreate_size(
- lua_State *L, void *cobj, const char *type, size_t size) {
// Lookup our cache in the registry (we don't put our objects in the registry
// directly because we need our cache to be a weak table).
- void **obj = NULL;
- lua_getfield(L, LUA_REGISTRYINDEX, "upb.objcache");
+ lupb_refcounted *ud = NULL;
+ lua_getfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE);
assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb.
- lua_pushlightuserdata(L, cobj);
+ lua_pushlightuserdata(L, (void*)obj);
lua_rawget(L, -2);
// Stack: objcache, cached value.
- if (lua_isnil(L, -1)) {
+ bool create = lua_isnil(L, -1) ||
+ // A corner case: it is possible for the value to be GC'd
+ // already, in which case we should evict this entry and create
+ // a new one.
+ ((lupb_refcounted*)lua_touserdata(L, -1))->refcounted == NULL;
+ if (create) {
// Remove bad cached value and push new value.
lua_pop(L, 1);
+
// We take advantage of the fact that all of our objects are currently a
// single pointer, and thus have the same layout.
- obj = lua_newuserdata(L, size);
- *obj = cobj;
+ // TODO: this probably violates aliasing.
+ ud = lua_newuserdata(L, sizeof(lupb_refcounted));
+ ud->refcounted = obj;
+ upb_refcounted_donateref(obj, owner, ud);
+
luaL_getmetatable(L, type);
assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb.
lua_setmetatable(L, -2);
// Set it in the cache.
- lua_pushlightuserdata(L, cobj);
+ lua_pushlightuserdata(L, (void*)obj);
lua_pushvalue(L, -2);
lua_rawset(L, -4);
+ } else {
+ // Existing wrapper obj already has a ref.
+ ud = lua_touserdata(L, -1);
+ upb_refcounted_checkref(obj, ud);
+ if (owner)
+ upb_refcounted_unref(obj, owner);
}
lua_insert(L, -2);
lua_pop(L, 1);
- return obj;
-}
-
-// Most types are just 1 pointer and can use this helper.
-static bool lupb_cache_getorcreate(lua_State *L, void *cobj, const char *type) {
- return lupb_cache_getorcreate_size(L, cobj, type, sizeof(void*)) != NULL;
+ return create;
}
-static void lupb_cache_create(lua_State *L, void *cobj, const char *type) {
- bool created =
- lupb_cache_getorcreate_size(L, cobj, type, sizeof(void*)) != NULL;
- (void)created; // For NDEBUG
- assert(created);
+static void lupb_refcounted_pushnewrapper(lua_State *L, upb_refcounted *obj,
+ const char *type, const void *owner) {
+ bool created = lupb_refcounted_pushwrapper(L, obj, type, owner);
+ UPB_ASSERT_VAR(created, created == true);
}
/* lupb_def *******************************************************************/
-// All the def types share the same C layout, even though they are different Lua
-// types with different metatables.
-typedef struct {
- upb_def *def;
-} lupb_def;
-
-static lupb_def *lupb_def_check(lua_State *L, int narg) {
- void *ldef = luaL_checkudata(L, narg, "upb.msgdef");
- if (!ldef) ldef = luaL_checkudata(L, narg, "upb.enumdef");
- if (!ldef) luaL_typerror(L, narg, "upb def");
- return ldef;
-}
-
-static void lupb_def_getorcreate(lua_State *L, const upb_def *def, int owned) {
- bool created = false;
- switch(def->type) {
- case UPB_DEF_MSG:
- created = lupb_cache_getorcreate(L, (void*)def, "upb.msgdef");
- break;
- case UPB_DEF_ENUM:
- created = lupb_cache_getorcreate(L, (void*)def, "upb.enumdef");
- break;
- default:
- luaL_error(L, "unknown deftype %d", def->type);
+static const upb_def *lupb_def_check(lua_State *L, int narg) {
+ lupb_refcounted *r = luaL_testudata(L, narg, LUPB_MSGDEF);
+ if (!r) r = luaL_testudata(L, narg, LUPB_ENUMDEF);
+ if (!r) r = luaL_testudata(L, narg, LUPB_FIELDDEF);
+ if (!r) luaL_typerror(L, narg, "upb def");
+ if (!r->refcounted) luaL_error(L, "called into dead def");
+ return r->def;
+}
+
+static upb_def *lupb_def_checkmutable(lua_State *L, int narg) {
+ const upb_def *def = lupb_def_check(L, narg);
+ if (upb_def_isfrozen(def))
+ luaL_typerror(L, narg, "not allowed on frozen value");
+ return (upb_def*)def;
+}
+
+bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner) {
+ if (def == NULL) {
+ lua_pushnil(L);
+ return false;
}
- if (!owned && created) {
- upb_def_ref(def);
- } else if (owned && !created) {
- upb_def_unref(def);
+
+ const char *type = NULL;
+ switch (def->type) {
+ case UPB_DEF_MSG: type = LUPB_MSGDEF; break;
+ case UPB_DEF_ENUM: type = LUPB_ENUMDEF; break;
+ case UPB_DEF_FIELD: type = LUPB_FIELDDEF; break;
+ default: luaL_error(L, "unknown deftype %d", def->type);
}
+ return lupb_refcounted_pushwrapper(L, upb_upcast(def), type, owner);
}
+void lupb_def_pushnewrapper(lua_State *L, const upb_def *def,
+ const void *owner) {
+ bool created = lupb_def_pushwrapper(L, def, owner);
+ UPB_ASSERT_VAR(created, created == true);
+}
-/* lupb_fielddef **************************************************************/
+static int lupb_def_type(lua_State *L) {
+ const upb_def *def = lupb_def_check(L, 1);
+ lua_pushnumber(L, upb_def_type(def));
+ return 1;
+}
-typedef struct {
- upb_fielddef *field;
-} lupb_fielddef;
-
-static lupb_fielddef *lupb_fielddef_check(lua_State *L, int narg) {
- lupb_fielddef *f = luaL_checkudata(L, narg, "upb.fielddef");
- if (!f) luaL_typerror(L, narg, "upb fielddef");
- return f;
-}
-
-static int lupb_fielddef_index(lua_State *L) {
- lupb_fielddef *f = lupb_fielddef_check(L, 1);
- const char *str = luaL_checkstring(L, 2);
- if (streql(str, "name")) {
- lua_pushstring(L, upb_fielddef_name(f->field));
- } else if (streql(str, "number")) {
- lua_pushinteger(L, upb_fielddef_number(f->field));
- } else if (streql(str, "type")) {
- lua_pushinteger(L, upb_fielddef_type(f->field));
- } else if (streql(str, "label")) {
- lua_pushinteger(L, upb_fielddef_label(f->field));
- } else if (streql(str, "subdef")) {
- lupb_def_getorcreate(L, upb_fielddef_subdef(f->field), false);
- } else if (streql(str, "msgdef")) {
- lupb_def_getorcreate(L, UPB_UPCAST(upb_fielddef_msgdef(f->field)), false);
- } else {
- luaL_error(L, "Invalid fielddef member '%s'", str);
- }
+static int lupb_def_isfrozen(lua_State *L) {
+ const upb_def *def = lupb_def_check(L, 1);
+ lua_pushboolean(L, upb_def_isfrozen(def));
return 1;
}
-static void lupb_fielddef_set(lua_State *L, upb_fielddef *f,
- const char *field, int narg) {
- if (!upb_fielddef_ismutable(f)) luaL_error(L, "fielddef is not mutable.");
- if (streql(field, "name")) {
- const char *name = lua_tostring(L, narg);
- if (!name || !upb_fielddef_setname(f, name))
- luaL_error(L, "Invalid name");
- } else if (streql(field, "number")) {
- if (!upb_fielddef_setnumber(f, lupb_touint32(L, narg, "number")))
- luaL_error(L, "Invalid number");
- } else if (streql(field, "type")) {
- if (!upb_fielddef_settype(f, lupb_touint8(L, narg, "type")))
- luaL_error(L, "Invalid type");
- } else if (streql(field, "label")) {
- if (!upb_fielddef_setlabel(f, lupb_touint8(L, narg, "label")))
- luaL_error(L, "Invalid label");
- } else if (streql(field, "type_name")) {
- const char *name = lua_tostring(L, narg);
- if (!name || !upb_fielddef_settypename(f, name))
- luaL_error(L, "Invalid type_name");
- } else if (streql(field, "default_value")) {
- if (!upb_fielddef_type(f))
- luaL_error(L, "Must set type before setting default_value");
- upb_strref ref;
- upb_fielddef_setdefault(f, lupb_getvalue(L, narg, f, &ref));
+static int lupb_def_fullname(lua_State *L) {
+ const upb_def *def = lupb_def_check(L, 1);
+ lua_pushstring(L, upb_def_fullname(def));
+ return 1;
+}
+
+static int lupb_def_setfullname(lua_State *L) {
+ upb_def *def = lupb_def_checkmutable(L, 1);
+ const char *name = lupb_checkname(L, 2);
+ upb_def_setfullname(def, name);
+ return 0;
+}
+
+#define LUPB_COMMON_DEF_METHODS \
+ {"def_type", lupb_def_type}, \
+ {"full_name", lupb_def_fullname}, \
+ {"is_frozen", lupb_def_isfrozen}, \
+ {"set_full_name", lupb_def_setfullname}, \
+
+
+/* lupb_fielddef **************************************************************/
+
+static const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) {
+ lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_FIELDDEF);
+ if (!r) luaL_typerror(L, narg, "upb fielddef");
+ if (!r->refcounted) luaL_error(L, "called into dead fielddef");
+ return upb_downcast_fielddef(r->def);
+}
+
+static upb_fielddef *lupb_fielddef_checkmutable(lua_State *L, int narg) {
+ const upb_fielddef *f = lupb_fielddef_check(L, narg);
+ if (upb_fielddef_isfrozen(f))
+ luaL_typerror(L, narg, "not allowed on frozen value");
+ return (upb_fielddef*)f;
+}
+
+// Setter functions; these are called by both the constructor and the individual
+// setter API calls like field:set_type().
+
+static void lupb_fielddef_dosetdefault(lua_State *L, upb_fielddef *f,
+ int narg) {
+ int type = lua_type(L, narg);
+ upb_fieldtype_t upbtype = upb_fielddef_type(f);
+ if (type == LUA_TSTRING) {
+ if (!upb_fielddef_isstring(f) && upbtype != UPB_TYPE(ENUM))
+ luaL_argerror(L, narg, "field does not expect a string default");
+ size_t len;
+ const char *str = lua_tolstring(L, narg, &len);
+ if (!upb_fielddef_setdefaultstr(f, str, len))
+ luaL_argerror(L, narg, "invalid default string for enum");
} else {
- luaL_error(L, "Cannot set fielddef member '%s'", field);
+ upb_fielddef_setdefault(f, lupb_getvalue(L, narg, upbtype));
}
}
+static void lupb_fielddef_dosetlabel(lua_State *L, upb_fielddef *f, int narg) {
+ upb_label_t label = luaL_checknumber(L, narg);
+ if (!upb_fielddef_setlabel(f, label))
+ luaL_argerror(L, narg, "invalid field label");
+}
+
+static void lupb_fielddef_dosetnumber(lua_State *L, upb_fielddef *f, int narg) {
+ int32_t n = luaL_checknumber(L, narg);
+ if (!upb_fielddef_setnumber(f, n))
+ luaL_argerror(L, narg, "invalid field number");
+}
+
+static void lupb_fielddef_dosetsubdef(lua_State *L, upb_fielddef *f, int narg) {
+ const upb_def *def = NULL;
+ if (!lua_isnil(L, narg))
+ def = lupb_def_check(L, narg);
+ if (!upb_fielddef_setsubdef(f, def))
+ luaL_argerror(L, narg, "invalid subdef for this field");
+}
+
+static void lupb_fielddef_dosetsubdefname(lua_State *L, upb_fielddef *f,
+ int narg) {
+ const char *name = NULL;
+ if (!lua_isnil(L, narg))
+ name = lupb_checkname(L, narg);
+ if (!upb_fielddef_setsubdefname(f, name))
+ luaL_argerror(L, narg, "field type does not expect a subdef");
+}
+
+static void lupb_fielddef_dosettype(lua_State *L, upb_fielddef *f, int narg) {
+ int32_t type = luaL_checknumber(L, narg);
+ if (!upb_fielddef_settype(f, type))
+ luaL_argerror(L, narg, "invalid field type");
+}
+
+// Setter API calls. These use the setter functions above.
+
+static int lupb_fielddef_setdefault(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetdefault(L, f, 2);
+ return 0;
+}
+
+static int lupb_fielddef_setlabel(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetlabel(L, f, 2);
+ return 0;
+}
+
+static int lupb_fielddef_setnumber(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetnumber(L, f, 2);
+ return 0;
+}
+
+static int lupb_fielddef_setsubdef(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetsubdef(L, f, 2);
+ return 0;
+}
+
+static int lupb_fielddef_setsubdefname(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosetsubdefname(L, f, 2);
+ return 0;
+}
+
+static int lupb_fielddef_settype(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ lupb_fielddef_dosettype(L, f, 2);
+ return 0;
+}
+
+// Constructor and other methods.
+
static int lupb_fielddef_new(lua_State *L) {
- upb_fielddef *f = upb_fielddef_new();
- lupb_cache_create(L, f, "upb.fielddef");
+ upb_fielddef *f = upb_fielddef_new(&f);
+ int narg = lua_gettop(L);
+
+ lupb_def_pushnewrapper(L, upb_upcast(f), &f);
- if (lua_gettop(L) == 0) return 1;
+ if (narg == 0) return 1;
// User can specify initialization values like so:
// upb.FieldDef{label=upb.LABEL_REQUIRED, name="my_field", number=5,
// type=upb.TYPE_INT32, default_value=12, type_name="Foo"}
luaL_checktype(L, 1, LUA_TTABLE);
- // Iterate over table.
- lua_pushnil(L); // first key
- while (lua_next(L, 1)) {
+ for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
luaL_checktype(L, -2, LUA_TSTRING);
const char *key = lua_tostring(L, -2);
- lupb_fielddef_set(L, f, key, -1);
- lua_pop(L, 1);
+ int v = -1;
+ if (streql(key, "name")) upb_fielddef_setname(f, lupb_checkname(L, v));
+ else if (streql(key, "number")) lupb_fielddef_dosetnumber(L, f, v);
+ else if (streql(key, "type")) lupb_fielddef_dosettype(L, f, v);
+ else if (streql(key, "label")) lupb_fielddef_dosetlabel(L, f, v);
+ else if (streql(key, "default_value")) ; // Defer to second pass.
+ else if (streql(key, "subdef")) ; // Defer to second pass.
+ else if (streql(key, "subdef_name")) ; // Defer to second pass.
+ else luaL_error(L, "Cannot set fielddef member '%s'", key);
}
+
+ // Have to do these in a second pass because these depend on the type, so we
+ // have to make sure the type is set if the user specified one.
+ for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
+ const char *key = lua_tostring(L, -2);
+ int v = -1;
+ if (streql(key, "default_value")) lupb_fielddef_dosetdefault(L, f, v);
+ else if (streql(key, "subdef")) lupb_fielddef_dosetsubdef(L, f, v);
+ else if (streql(key, "subdef_name")) lupb_fielddef_dosetsubdefname(L, f, v);
+ }
+
return 1;
}
-static void lupb_fielddef_getorcreate(lua_State *L, upb_fielddef *f) {
- bool created = lupb_cache_getorcreate(L, f, "upb.fielddef");
- if (created) upb_fielddef_ref(f);
+static int lupb_fielddef_default(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ upb_fieldtype_t type = upb_fielddef_type(f);
+ if (upb_fielddef_default_is_symbolic(f))
+ type = UPB_TYPE(STRING);
+ lupb_pushvalue(L, upb_fielddef_default(f), type);
+ return 1;
}
-static int lupb_fielddef_newindex(lua_State *L) {
- lupb_fielddef *f = lupb_fielddef_check(L, 1);
- lupb_fielddef_set(L, f->field, luaL_checkstring(L, 2), 3);
- return 0;
+static int lupb_fielddef_label(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ lua_pushnumber(L, upb_fielddef_label(f));
+ return 1;
+}
+
+static int lupb_fielddef_number(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ int32_t num = upb_fielddef_number(f);
+ if (num)
+ lua_pushnumber(L, num);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+static int lupb_fielddef_selectorbase(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ if (!upb_fielddef_isfrozen(f))
+ luaL_error(L, "_selectorbase is only defined for frozen fielddefs");
+ lua_pushnumber(L, f->selector_base);
+ return 1;
+}
+
+static int lupb_fielddef_hassubdef(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ lua_pushboolean(L, upb_fielddef_hassubdef(f));
+ return 1;
+}
+
+static int lupb_fielddef_msgdef(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ lupb_def_pushwrapper(L, upb_upcast(upb_fielddef_msgdef(f)), NULL);
+ return 1;
+}
+
+static int lupb_fielddef_subdef(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ if (!upb_fielddef_hassubdef(f))
+ luaL_error(L, "Tried to get subdef of non-message field");
+ const upb_def *def = upb_fielddef_subdef(f);
+ lupb_def_pushwrapper(L, def, NULL);
+ return 1;
+}
+
+static int lupb_fielddef_subdefname(lua_State *L) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 1);
+ if (!upb_fielddef_hassubdef(f))
+ luaL_error(L, "Tried to get subdef name of non-message field");
+ lua_pushstring(L, upb_fielddef_subdefname(f));
+ return 1;
+}
+
+static int lupb_fielddef_type(lua_State *L) {
+ const upb_fielddef *f = lupb_fielddef_check(L, 1);
+ lua_pushnumber(L, upb_fielddef_type(f));
+ return 1;
}
static int lupb_fielddef_gc(lua_State *L) {
- lupb_fielddef *lfielddef = lupb_fielddef_check(L, 1);
- upb_fielddef_unref(lfielddef->field);
+ lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_FIELDDEF);
+ upb_def_unref(r->def, r);
+ r->refcounted = NULL;
return 0;
}
+static const struct luaL_Reg lupb_fielddef_m[] = {
+ LUPB_COMMON_DEF_METHODS
+
+ {"default", lupb_fielddef_default},
+ {"has_subdef", lupb_fielddef_hassubdef},
+ {"label", lupb_fielddef_label},
+ {"msgdef", lupb_fielddef_msgdef},
+ {"name", lupb_def_fullname}, // name() is just an alias for fullname()
+ {"number", lupb_fielddef_number},
+ {"subdef", lupb_fielddef_subdef},
+ {"subdef_name", lupb_fielddef_subdefname},
+ {"type", lupb_fielddef_type},
+
+ {"set_default", lupb_fielddef_setdefault},
+ {"set_label", lupb_fielddef_setlabel},
+ {"set_name", lupb_def_setfullname}, // name() is just an alias for fullname()
+ {"set_number", lupb_fielddef_setnumber},
+ {"set_subdef", lupb_fielddef_setsubdef},
+ {"set_subdef_name", lupb_fielddef_setsubdefname},
+ {"set_type", lupb_fielddef_settype},
+
+ // Internal-only.
+ {"_selector_base", lupb_fielddef_selectorbase},
+
+ {NULL, NULL}
+};
+
static const struct luaL_Reg lupb_fielddef_mm[] = {
{"__gc", lupb_fielddef_gc},
- {"__index", lupb_fielddef_index},
- {"__newindex", lupb_fielddef_newindex},
{NULL, NULL}
};
/* lupb_msgdef ****************************************************************/
-static upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) {
- lupb_def *ldef = luaL_checkudata(L, narg, "upb.msgdef");
- luaL_argcheck(L, ldef != NULL, narg, "upb msgdef expected");
- return upb_downcast_msgdef(ldef->def);
+const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) {
+ lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_MSGDEF);
+ if (!r) luaL_typerror(L, narg, LUPB_MSGDEF);
+ if (!r->refcounted) luaL_error(L, "called into dead msgdef");
+ return upb_downcast_msgdef(r->def);
}
-static int lupb_msgdef_gc(lua_State *L) {
- lupb_def *ldef = luaL_checkudata(L, 1, "upb.msgdef");
- upb_def_unref(ldef->def);
- return 0;
+static upb_msgdef *lupb_msgdef_checkmutable(lua_State *L, int narg) {
+ const upb_msgdef *m = lupb_msgdef_check(L, narg);
+ if (upb_msgdef_isfrozen(m))
+ luaL_typerror(L, narg, "not allowed on frozen value");
+ return (upb_msgdef*)m;
}
-static int lupb_msgdef_call(lua_State *L) {
- upb_msgdef *md = lupb_msgdef_check(L, 1);
- lupb_msg_pushnew(L, md);
- return 1;
+static int lupb_msgdef_gc(lua_State *L) {
+ lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_MSGDEF);
+ upb_def_unref(r->def, r);
+ r->refcounted = NULL;
+ return 0;
}
static int lupb_msgdef_new(lua_State *L) {
- upb_msgdef *md = upb_msgdef_new();
- lupb_cache_create(L, md, "upb.msgdef");
+ int narg = lua_gettop(L);
+ upb_msgdef *md = upb_msgdef_new(&md);
+ lupb_def_pushnewrapper(L, upb_upcast(md), &md);
- if (lua_gettop(L) == 0) return 1;
+ if (narg == 0) return 1;
// User can specify initialization values like so:
- // upb.MessageDef{fqname="MyMessage", extstart=8000, fields={...}}
+ // upb.MessageDef{full_name="MyMessage", extstart=8000, fields={...}}
luaL_checktype(L, 1, LUA_TTABLE);
- // Iterate over table.
- lua_pushnil(L); // first key
- while (lua_next(L, 1)) {
+ for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
luaL_checktype(L, -2, LUA_TSTRING);
const char *key = lua_tostring(L, -2);
- if (streql(key, "fqname")) { // fqname="MyMessage"
+ if (streql(key, "full_name")) { // full_name="MyMessage"
const char *fqname = lua_tostring(L, -1);
- if (!fqname || !upb_def_setfqname(UPB_UPCAST(md), fqname))
- luaL_error(L, "Invalid fqname");
+ if (!fqname || !upb_def_setfullname(upb_upcast(md), fqname))
+ luaL_error(L, "Invalid full_name");
} else if (streql(key, "fields")) { // fields={...}
// Iterate over the list of fields.
- lua_pushnil(L);
- luaL_checktype(L, -2, LUA_TTABLE);
- while (lua_next(L, -2)) {
- lupb_fielddef *f = lupb_fielddef_check(L, -1);
- if (!upb_msgdef_addfield(md, f->field)) {
+ luaL_checktype(L, -1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, -1);
+ if (!upb_msgdef_addfield(md, f, NULL)) {
// TODO: more specific error.
luaL_error(L, "Could not add field.");
}
- lua_pop(L, 1);
}
} else {
// TODO: extrange=
luaL_error(L, "Unknown initializer key '%s'", key);
}
+ }
+ return 1;
+}
+
+static int lupb_msgdef_add(lua_State *L) {
+ upb_msgdef *m = lupb_msgdef_checkmutable(L, 1);
+ luaL_checktype(L, 2, LUA_TTABLE);
+ int n = lua_rawlen(L, 2);
+ // TODO: add upb interface that lets us avoid this malloc/free.
+ upb_fielddef **fields = malloc(n * sizeof(upb_fielddef*));
+ for (int i = 0; i < n; i++) {
+ lua_rawgeti(L, -1, i + 1);
+ fields[i] = lupb_fielddef_checkmutable(L, -1);
lua_pop(L, 1);
}
+
+ bool success = upb_msgdef_addfields(m, fields, n, NULL);
+ free(fields);
+ if (!success) luaL_error(L, "fields could not be added");
+ return 0;
+}
+
+static int lupb_msgdef_len(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ lua_pushinteger(L, upb_msgdef_numfields(m));
return 1;
}
-static int lupb_msgdef_fqname(lua_State *L) {
- upb_msgdef *m = lupb_msgdef_check(L, 1);
- lua_pushstring(L, m->base.fqname);
+static int lupb_msgdef_selectorcount(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ lua_pushinteger(L, m->selector_count);
return 1;
}
-static int lupb_msgdef_fieldbyname(lua_State *L) {
- upb_msgdef *m = lupb_msgdef_check(L, 1);
- upb_fielddef *f = upb_msgdef_ntof(m, luaL_checkstring(L, 2));
- if (f) {
- lupb_fielddef_getorcreate(L, f);
+static int lupb_msgdef_field(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ int type = lua_type(L, 2);
+ const upb_fielddef *f;
+ if (type == LUA_TNUMBER) {
+ f = upb_msgdef_itof(m, lua_tointeger(L, 2));
+ } else if (type == LUA_TSTRING) {
+ f = upb_msgdef_ntof(m, lua_tostring(L, 2));
} else {
- lua_pushnil(L);
+ const char *msg = lua_pushfstring(L, "number or string expected, got %s",
+ luaL_typename(L, 2));
+ return luaL_argerror(L, 2, msg);
}
+
+ lupb_def_pushwrapper(L, upb_upcast(f), NULL);
return 1;
}
-static int lupb_msgdef_fieldbynum(lua_State *L) {
- upb_msgdef *m = lupb_msgdef_check(L, 1);
- int num = luaL_checkint(L, 2);
- upb_fielddef *f = upb_msgdef_itof(m, num);
- if (f) {
- lupb_fielddef_getorcreate(L, f);
- } else {
- lua_pushnil(L);
- }
+static int lupb_msgiter_next(lua_State *L) {
+ upb_msg_iter *i = lua_touserdata(L, lua_upvalueindex(1));
+ if (upb_msg_done(i)) return 0;
+ lupb_def_pushwrapper(L, upb_upcast(upb_msg_iter_field(i)), NULL);
+ upb_msg_next(i);
+ return 1;
+}
+
+static int lupb_msgdef_fields(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ upb_msg_iter *i = lua_newuserdata(L, sizeof(upb_msg_iter));
+ upb_msg_begin(i, m);
+ lua_pushcclosure(L, &lupb_msgiter_next, 1);
return 1;
}
static const struct luaL_Reg lupb_msgdef_mm[] = {
- {"__call", lupb_msgdef_call},
{"__gc", lupb_msgdef_gc},
+ {"__len", lupb_msgdef_len},
{NULL, NULL}
};
static const struct luaL_Reg lupb_msgdef_m[] = {
- {"fieldbyname", lupb_msgdef_fieldbyname},
- {"fieldbynum", lupb_msgdef_fieldbynum},
- {"fqname", lupb_msgdef_fqname},
+ LUPB_COMMON_DEF_METHODS
+ {"add", lupb_msgdef_add},
+ {"field", lupb_msgdef_field},
+ {"fields", lupb_msgdef_fields},
+
+ // Internal-only.
+ {"_selector_count", lupb_msgdef_selectorcount},
+
{NULL, NULL}
};
/* lupb_enumdef ***************************************************************/
-static upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) {
- lupb_def *ldef = luaL_checkudata(L, narg, "upb.enumdef");
- return upb_downcast_enumdef(ldef->def);
+const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) {
+ lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_ENUMDEF);
+ if (!r) luaL_typerror(L, narg, LUPB_ENUMDEF);
+ if (!r->refcounted) luaL_error(L, "called into dead enumdef");
+ return upb_downcast_enumdef(r->def);
+}
+
+static upb_enumdef *lupb_enumdef_checkmutable(lua_State *L, int narg) {
+ const upb_enumdef *f = lupb_enumdef_check(L, narg);
+ if (upb_enumdef_isfrozen(f))
+ luaL_typerror(L, narg, "not allowed on frozen value");
+ return (upb_enumdef*)f;
}
static int lupb_enumdef_gc(lua_State *L) {
- upb_enumdef *e = lupb_enumdef_check(L, 1);
- upb_def_unref(UPB_UPCAST(e));
+ lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_ENUMDEF);
+ upb_def_unref(r->def, r);
+ r->refcounted = NULL;
return 0;
}
-static int lupb_enumdef_name(lua_State *L) {
- upb_enumdef *e = lupb_enumdef_check(L, 1);
- lua_pushstring(L, e->base.fqname);
+static int lupb_enumdef_new(lua_State *L) {
+ int narg = lua_gettop(L);
+ upb_enumdef *e = upb_enumdef_new(&e);
+ lupb_def_pushnewrapper(L, upb_upcast(e), &e);
+
+ if (narg == 0) return 1;
+
+ // User can specify initialization values like so:
+ // upb.EnumDef{full_name="MyEnum",
+ // values={
+ // {"FOO_VALUE_1", 1},
+ // {"FOO_VALUE_2", 2}
+ // }
+ // }
+ luaL_checktype(L, 1, LUA_TTABLE);
+ for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) {
+ luaL_checktype(L, -2, LUA_TSTRING);
+ const char *key = lua_tostring(L, -2);
+ if (streql(key, "values")) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ lua_rawgeti(L, -1, 1);
+ luaL_checktype(L, -1, LUA_TSTRING);
+ const char *name = lua_tostring(L, -1);
+ lua_rawgeti(L, -2, 2);
+ int32_t num = lupb_checkint32(L, -1, "value");
+ upb_status status = UPB_STATUS_INIT;
+ upb_enumdef_addval(e, name, num, &status);
+ lupb_checkstatus(L, &status);
+ lua_pop(L, 2); // The key/val we got from lua_rawgeti()
+ }
+ } else if (streql(key, "full_name")) {
+ const char *fullname = lua_tostring(L, -1);
+ if (!fullname || !upb_def_setfullname(upb_upcast(e), fullname))
+ luaL_error(L, "Invalid full_name");
+ } else {
+ luaL_error(L, "Unknown initializer key '%s'", key);
+ }
+ }
+ return 1;
+}
+
+static int lupb_enumdef_add(lua_State *L) {
+ upb_enumdef *e = lupb_enumdef_checkmutable(L, 1);
+ const char *name = lupb_checkname(L, 2);
+ int32_t num = lupb_checkint32(L, 3, "value");
+ upb_status status = UPB_STATUS_INIT;
+ upb_enumdef_addval(e, name, num, &status);
+ lupb_checkstatus(L, &status);
+ return 0;
+}
+
+static int lupb_enumdef_len(lua_State *L) {
+ const upb_enumdef *e = lupb_enumdef_check(L, 1);
+ lua_pushinteger(L, upb_enumdef_numvals(e));
+ return 1;
+}
+
+static int lupb_enumdef_value(lua_State *L) {
+ const upb_enumdef *e = lupb_enumdef_check(L, 1);
+ int type = lua_type(L, 2);
+ if (type == LUA_TNUMBER) {
+ // Pushes "nil" for a NULL pointer.
+ lua_pushstring(L, upb_enumdef_iton(e, lupb_checkint32(L, 2, "value")));
+ } else if (type == LUA_TSTRING) {
+ int32_t num;
+ if (upb_enumdef_ntoi(e, lua_tostring(L, 2), &num)) {
+ lua_pushnumber(L, num);
+ } else {
+ lua_pushnil(L);
+ }
+ } else {
+ const char *msg = lua_pushfstring(L, "number or string expected, got %s",
+ luaL_typename(L, 2));
+ return luaL_argerror(L, 2, msg);
+ }
+ return 1;
+}
+
+static int lupb_enumiter_next(lua_State *L) {
+ upb_enum_iter *i = lua_touserdata(L, lua_upvalueindex(1));
+ if (upb_enum_done(i)) return 0;
+ lua_pushstring(L, upb_enum_iter_name(i));
+ lua_pushnumber(L, upb_enum_iter_number(i));
+ upb_enum_next(i);
+ return 2;
+}
+
+static int lupb_enumdef_values(lua_State *L) {
+ const upb_enumdef *e = lupb_enumdef_check(L, 1);
+ upb_enum_iter *i = lua_newuserdata(L, sizeof(upb_enum_iter));
+ upb_enum_begin(i, e);
+ lua_pushcclosure(L, &lupb_enumiter_next, 1);
return 1;
}
static const struct luaL_Reg lupb_enumdef_mm[] = {
{"__gc", lupb_enumdef_gc},
+ {"__len", lupb_enumdef_len},
{NULL, NULL}
};
static const struct luaL_Reg lupb_enumdef_m[] = {
- {"name", lupb_enumdef_name},
+ LUPB_COMMON_DEF_METHODS
+ {"add", lupb_enumdef_add},
+ {"value", lupb_enumdef_value},
+ {"values", lupb_enumdef_values},
{NULL, NULL}
};
/* lupb_symtab ****************************************************************/
-typedef struct {
- upb_symtab *symtab;
-} lupb_symtab;
-
-static upb_accessor_vtbl *lupb_accessor(upb_fielddef *f);
-
// Inherits a ref on the symtab.
// Checks that narg is a proper lupb_symtab object. If it is, leaves its
// metatable on the stack for cache lookups/updates.
-lupb_symtab *lupb_symtab_check(lua_State *L, int narg) {
- return luaL_checkudata(L, narg, "upb.symtab");
+upb_symtab *lupb_symtab_check(lua_State *L, int narg) {
+ lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_SYMTAB);
+ if (!r) luaL_typerror(L, narg, LUPB_SYMTAB);
+ if (!r->refcounted) luaL_error(L, "called into dead symtab");
+ return r->symtab;
}
// narg is a lua table containing a list of defs to add.
@@ -509,93 +867,91 @@ void lupb_symtab_doadd(lua_State *L, upb_symtab *s, int narg) {
// Iterate over table twice. First iteration to count entries and
// check constraints.
int n = 0;
- lua_pushnil(L); // first key
- while (lua_next(L, narg)) {
+ for (lua_pushnil(L); lua_next(L, narg); lua_pop(L, 1)) {
lupb_def_check(L, -1);
++n;
- lua_pop(L, 1);
}
// Second iteration to build deflist and layout.
upb_def **defs = malloc(n * sizeof(*defs));
n = 0;
- lua_pushnil(L); // first key
- while (lua_next(L, 1)) {
- upb_def *def = lupb_def_check(L, -1)->def;
+ for (lua_pushnil(L); lua_next(L, narg); lua_pop(L, 1)) {
+ upb_def *def = lupb_def_checkmutable(L, -1);
defs[n++] = def;
- upb_msgdef *md = upb_dyncast_msgdef(def);
- if (md) {
- upb_msg_iter i;
- for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
- upb_fielddef *f = upb_msg_iter_field(i);
- upb_fielddef_setaccessor(f, lupb_accessor(f));
- }
- upb_msgdef_layout(md);
- }
- lua_pop(L, 1);
}
upb_status status = UPB_STATUS_INIT;
- upb_symtab_add(s, defs, n, &status);
+ upb_symtab_add(s, defs, n, NULL, &status);
free(defs);
lupb_checkstatus(L, &status);
}
static int lupb_symtab_new(lua_State *L) {
- upb_symtab *s = upb_symtab_new();
- lupb_cache_create(L, s, "upb.symtab");
- if (lua_gettop(L) == 0) return 1;
- lupb_symtab_doadd(L, s, 1);
+ int narg = lua_gettop(L);
+ upb_symtab *s = upb_symtab_new(&s);
+ lupb_refcounted_pushnewrapper(L, upb_upcast(s), LUPB_SYMTAB, &s);
+ if (narg > 0) lupb_symtab_doadd(L, s, 1);
return 1;
}
static int lupb_symtab_add(lua_State *L) {
- lupb_symtab *s = lupb_symtab_check(L, 1);
- lupb_symtab_doadd(L, s->symtab, 2);
+ lupb_symtab_doadd(L, lupb_symtab_check(L, 1), 2);
return 0;
}
static int lupb_symtab_gc(lua_State *L) {
- lupb_symtab *s = lupb_symtab_check(L, 1);
- upb_symtab_unref(s->symtab);
+ lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_SYMTAB);
+ upb_symtab_unref(r->symtab, r);
+ r->refcounted = NULL;
return 0;
}
static int lupb_symtab_lookup(lua_State *L) {
- lupb_symtab *s = lupb_symtab_check(L, 1);
+ upb_symtab *s = lupb_symtab_check(L, 1);
for (int i = 2; i <= lua_gettop(L); i++) {
- const upb_def *def = upb_symtab_lookup(s->symtab, luaL_checkstring(L, i));
- if (def) {
- lupb_def_getorcreate(L, def, true);
- } else {
- lua_pushnil(L);
- }
+ const upb_def *def =
+ upb_symtab_lookup(s, luaL_checkstring(L, i), &def);
+ lupb_def_pushwrapper(L, def, &def);
lua_replace(L, i);
}
return lua_gettop(L) - 1;
}
static int lupb_symtab_getdefs(lua_State *L) {
- lupb_symtab *s = lupb_symtab_check(L, 1);
+ upb_symtab *s = lupb_symtab_check(L, 1);
upb_deftype_t type = luaL_checkint(L, 2);
int count;
- const upb_def **defs = upb_symtab_getdefs(s->symtab, &count, type);
+ const upb_def **defs = upb_symtab_getdefs(s, type, &defs, &count);
// Create the table in which we will return the defs.
lua_createtable(L, count, 0);
for (int i = 0; i < count; i++) {
const upb_def *def = defs[i];
- lupb_def_getorcreate(L, def, true);
+ lupb_def_pushwrapper(L, def, &defs);
lua_rawseti(L, -2, i + 1);
}
free(defs);
return 1;
}
+// This is a *temporary* API that will be removed once pending refactorings are
+// complete (it does not belong here in core because it depends on both
+// the descriptor.proto schema and the protobuf binary format.
+static int lupb_symtab_load_descriptor(lua_State *L) {
+ size_t len;
+ upb_symtab *s = lupb_symtab_check(L, 1);
+ const char *str = luaL_checklstring(L, 2, &len);
+ upb_status status = UPB_STATUS_INIT;
+ upb_load_descriptor_into_symtab(s, str, len, &status);
+ lupb_checkstatus(L, &status);
+ return 0;
+}
+
static const struct luaL_Reg lupb_symtab_m[] = {
{"add", lupb_symtab_add},
{"getdefs", lupb_symtab_getdefs},
{"lookup", lupb_symtab_lookup},
+ {"load_descriptor", lupb_symtab_load_descriptor},
{NULL, NULL}
};
@@ -605,343 +961,28 @@ static const struct luaL_Reg lupb_symtab_mm[] = {
};
-/* lupb_msg********************************************************************/
-
-// Messages are userdata. Primitive values (numbers and bools, and their
-// hasbits) are stored right in the userdata. Other values are stored using
-// integer entries in the environment table and no hasbits are used (since
-// "nil" in the environment table can indicate "not present").
-//
-// The environment table looks like:
-// {msgdef, <string, submessage, and array fields>}
-
-// Must pass a upb_fielddef as the pointer.
-static void lupb_array_pushnew(lua_State *L, const void *f);
-
-static void *lupb_msg_check(lua_State *L, int narg, upb_msgdef **md) {
- void *msg = luaL_checkudata(L, narg, "upb.msg");
- luaL_argcheck(L, msg != NULL, narg, "msg expected");
- // If going all the way to the environment table for the msgdef is an
- // efficiency issue, we could put the pointer right in the userdata.
- lua_getfenv(L, narg);
- lua_rawgeti(L, -1, 1);
- // Shouldn't have to check msgdef userdata validity, environment table can't
- // be accessed from Lua.
- lupb_def *lmd = lua_touserdata(L, -1);
- *md = upb_downcast_msgdef(lmd->def);
- return msg;
-}
-
-static void lupb_msg_pushnew(lua_State *L, const void *md) {
- void *msg = lua_newuserdata(L, upb_msgdef_size(md));
- luaL_getmetatable(L, "upb.msg");
- assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb.
- lua_setmetatable(L, -2);
- upb_msg_clear(msg, md);
- lua_getfenv(L, -1);
- lupb_cache_getorcreate(L, (void*)md, "upb.msgdef");
- lua_rawseti(L, -2, 1);
- lua_pop(L, 1); // Pop the fenv.
-}
-
-static int lupb_msg_new(lua_State *L) {
- upb_msgdef *md = lupb_msgdef_check(L, 1);
- lupb_msg_pushnew(L, md);
- return 1;
-}
-
-static int lupb_msg_index(lua_State *L) {
- upb_msgdef *md;
- void *m = lupb_msg_check(L, 1, &md);
- upb_fielddef *f = upb_msgdef_ntof(md, luaL_checkstring(L, 2));
- if (!f) luaL_argerror(L, 2, "not a field name");
- if (upb_isprimitivetype(upb_fielddef_type(f))) {
- upb_value v = upb_msg_has(m, f) ? upb_msg_get(m, f) : upb_fielddef_default(f);
- lupb_pushvalue(L, v, f);
- } else {
- lua_getfenv(L, 1);
- lua_rawgeti(L, -1, f->offset);
- if (lua_isnil(L, -1)) {
- // Need to lazily create array, string, or submessage.
- if (upb_isseq(f)) {
- lupb_array_pushnew(L, f);
- } else if (upb_isstring(f)) {
- // TODO: (need to figure out default string ownership).
- } else if (upb_issubmsg(f)) {
- lupb_msg_pushnew(L, upb_downcast_msgdef(upb_fielddef_subdef(f)));
- } else {
- luaL_error(L, "internal error");
- }
- lua_rawseti(L, -2, f->offset);
- }
- }
- return 1;
-}
-
-static int lupb_msg_newindex(lua_State *L) {
- upb_msgdef *md;
- void *m = lupb_msg_check(L, 1, &md);
- upb_fielddef *f = upb_msgdef_ntof(md, luaL_checkstring(L, 2));
- if (!f) luaL_error(L, "not a field name");
- if (upb_isprimitivetype(upb_fielddef_type(f))) {
- if (lua_isnil(L, 3))
- upb_msg_clearbit(m, f);
- else
- upb_msg_set(m, f, lupb_getvalue(L, 3, f, NULL));
- } else {
- if (!lua_isnil(L, 3)) lupb_typecheck(L, 3, f);
- lua_getfenv(L, 1);
- lua_pushvalue(L, 3);
- lua_rawseti(L, -1, f->offset);
- }
- return 0;
-}
-
-static const struct luaL_Reg lupb_msg_mm[] = {
- {"__index", lupb_msg_index},
- {"__newindex", lupb_msg_newindex},
- {NULL, NULL}
-};
-
-// Functions that operate on msgdefs but do not live in the msgdef namespace.
-static int lupb_clear(lua_State *L) {
- upb_msgdef *md;
- void *m = lupb_msg_check(L, 1, &md);
- upb_msg_clear(m, md);
- return 0;
-}
-
-static int lupb_has(lua_State *L) {
- upb_msgdef *md;
- void *m = lupb_msg_check(L, 1, &md);
- upb_fielddef *f = upb_msgdef_ntof(md, luaL_checkstring(L, 2));
- if (!f) luaL_argerror(L, 2, "not a field name");
- lua_pushboolean(L, upb_msg_has(m, f));
- return 1;
-}
-
-static int lupb_msgdef(lua_State *L) {
- upb_msgdef *md;
- lupb_msg_check(L, 1, &md);
- lupb_def_getorcreate(L, UPB_UPCAST(md), false);
- return 1;
-}
+/* lupb toplevel **************************************************************/
-// Accessors for arrays, strings, and submessages need access to the current
-// userdata's environment table, which can only be stored in Lua space.
-// Options for storing it are:
-//
-// - put the env tables for all messages and arrays in the registry, keyed by
-// userdata pointer (light userdata), or by a reference using luaL_ref().
-// Then we can just let upb's parse stack track the stack of env tables.
-// Easy but requires all messages and arrays to be in the registry, which
-// seems too heavyweight.
-//
-// - store the stack of env tables in the Lua stack. Convenient, but requires
-// special code to handle resumable decoders.
-//
-// There is also the question of how to obtain the lua_State* pointer.
-// The main options for this are:
-//
-// - make our closure point to a struct:
-// struct { void *msg; lua_State *L; }
-// But then we can't use standard accessors, which expect the closure
-// to point to the data itself. Using the standard accessors for
-// primitive values is both a simplicity and a performance win.
-//
-// - store a lua_State* pointer inside each userdata. Convenient and
-// efficient, but makes every message sizeof(void*) larger.
-// Currently we take this route.
-//
-// - use thread-local storage. Convenient and efficient, but not portable.
-
-typedef void createfunc_t(lua_State *L, const void *param);
-
-static upb_sflow_t lupb_msg_start(void *m, const upb_fielddef *f, bool array,
- createfunc_t *pushnew, const void *param) {
- lua_State *L = *(lua_State**)m;
- int offset = array ? lua_rawlen(L, -1) : f->offset;
- if (!lua_checkstack(L, 3)) luaL_error(L, "stack full");
- lua_rawgeti(L, -1, offset);
- if (lua_isnil(L, -1)) {
- lua_pop(L, 1);
- pushnew(L, param);
- lua_pushvalue(L, -1);
- lua_rawseti(L, -3, offset);
+static int lupb_def_freeze(lua_State *L) {
+ int n = lua_gettop(L);
+ upb_def **defs = malloc(n * sizeof(upb_def*));
+ for (int i = 0; i < n; i++) {
+ // Could allow an array of defs here also.
+ defs[i] = lupb_def_checkmutable(L, i + 1);
}
- void *subval = lua_touserdata(L, -1);
- lua_getfenv(L, -1);
- lua_replace(L, -2); // Replace subval userdata with fenv.
- return UPB_CONTINUE_WITH(subval);
-}
-
-static upb_flow_t lupb_msg_string(void *m, upb_value fval, upb_value val,
- bool array) {
- // Could add lazy materialization of strings here.
- const upb_fielddef *f = upb_value_getfielddef(fval);
- lua_State *L = *(lua_State**)m;
- int offset = array ? lua_rawlen(L, -1) : f->offset;
- if (!lua_checkstack(L, 1)) luaL_error(L, "stack full");
- lupb_pushstring(L, upb_value_getstrref(val));
- lua_rawseti(L, -2, offset);
- return UPB_CONTINUE;
-}
-
-static upb_sflow_t lupb_msg_startseq(void *m, upb_value fval) {
- const upb_fielddef *f = upb_value_getfielddef(fval);
- return lupb_msg_start(m, f, false, lupb_array_pushnew, f);
-}
-
-static upb_sflow_t lupb_msg_startsubmsg(void *m, upb_value fval) {
- const upb_fielddef *f = upb_value_getfielddef(fval);
- return lupb_msg_start(m, f, false, lupb_msg_pushnew, upb_fielddef_subdef(f));
-}
-
-static upb_sflow_t lupb_msg_startsubmsg_r(void *a, upb_value fval) {
- const upb_fielddef *f = upb_value_getfielddef(fval);
- return lupb_msg_start(a, f, true, lupb_msg_pushnew, upb_fielddef_subdef(f));
-}
-
-static upb_flow_t lupb_msg_stringval(void *m, upb_value fval, upb_value val) {
- return lupb_msg_string(m, fval, val, false);
-}
-
-static upb_flow_t lupb_msg_stringval_r(void *a, upb_value fval, upb_value val) {
- return lupb_msg_string(a, fval, val, true);
-}
-
-#define STDMSG(type, size) static upb_accessor_vtbl vtbl = { \
- &lupb_msg_startsubmsg, \
- &upb_stdmsg_set ## type, \
- &lupb_msg_startseq, \
- &lupb_msg_startsubmsg_r, \
- &upb_stdmsg_set ## type ## _r, \
- &upb_stdmsg_has, \
- &upb_stdmsg_getptr, \
- &upb_stdmsg_get ## type, \
- &upb_stdmsg_seqbegin, \
- &upb_stdmsg_ ## size ## byte_seqnext, \
- &upb_stdmsg_seqget ## type};
-
-#define RETURN_STDMSG(type, size) { STDMSG(type, size); return &vtbl; }
-
-static upb_accessor_vtbl *lupb_accessor(upb_fielddef *f) {
- switch (f->type) {
- case UPB_TYPE(DOUBLE): RETURN_STDMSG(double, 8)
- case UPB_TYPE(FLOAT): RETURN_STDMSG(float, 4)
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64): RETURN_STDMSG(uint64, 8)
- case UPB_TYPE(INT64):
- case UPB_TYPE(SFIXED64):
- case UPB_TYPE(SINT64): RETURN_STDMSG(int64, 8)
- case UPB_TYPE(INT32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(ENUM):
- case UPB_TYPE(SFIXED32): RETURN_STDMSG(int32, 4)
- case UPB_TYPE(UINT32):
- case UPB_TYPE(FIXED32): RETURN_STDMSG(uint32, 4)
- case UPB_TYPE(BOOL): { STDMSG(bool, 1); return &vtbl; }
- case UPB_TYPE(GROUP):
- case UPB_TYPE(MESSAGE): RETURN_STDMSG(ptr, 8) // TODO: 32-bit
- case UPB_TYPE(STRING):
- case UPB_TYPE(BYTES): {
- STDMSG(ptr, 8);
- vtbl.set = &lupb_msg_stringval;
- vtbl.append = &lupb_msg_stringval_r;
- return &vtbl;
- }
- }
- return NULL;
-}
-
-
-/* lupb_array ****************************************************************/
-
-// Array: we store all elements in the environment table. Could optimize by
-// storing primitive arrays in our own memory; this would be significantly more
-// space efficient. Lua array elements are 16 bytes each; our own array would
-// be 1/4 the space for 32-bit integers, or 1/16 the space for booleans.
-//
-// The first element of the environment table stores our type (which will be
-// either an integer from upb.TYPE_* or a upb.msgdef), the remaining elements
-// store the elements. We always keep all elements contiguous so we can use
-// lua_objlen()/lua_rawlen() (for Lua 5.1/5.2 respectively) to report its len).
-
-// narg is offset of environment table.
-static size_t lupb_array_getlen(lua_State *L, int narg) {
- return lua_rawlen(L, narg) - 1;
-}
-
-static void lupb_array_check(lua_State *L, int narg) {
- if (!luaL_checkudata(L, narg, "upb.array"))
- luaL_typerror(L, narg, "upb array");
-}
-
-static void lupb_array_pushnew(lua_State *L, const void *f) {
- (void)L;
- (void)f;
-}
-
-static int lupb_array_new(lua_State *L) {
- (void)L;
- return 0;
-}
-
-static int lupb_array_len(lua_State *L) {
- lupb_array_check(L, 1);
- lua_getfenv(L, 1);
- lua_pushnumber(L, lupb_array_getlen(L, -1));
- return 1;
-}
-
-static int lupb_array_index(lua_State *L) {
- assert(lua_gettop(L) == 2); // __index should always be called with 2 args.
- lupb_array_check(L, 1);
- lua_Number num = luaL_checknumber(L, 2);
- if (!lupb_isint(num)) luaL_typerror(L, 2, "integer");
-
- lua_getfenv(L, 1);
- size_t len = lupb_array_getlen(L, -1);
- if (num < 1 || num > len) luaL_error(L, "array bounds check failed");
- lua_rawgeti(L, -1, num + 1);
- return 1;
-}
-
-static int lupb_array_newindex(lua_State *L) {
- assert(lua_gettop(L) == 3); // __newindex should always be called with 3 args.
- lupb_array_check(L, 1);
- lua_Number num = luaL_checknumber(L, 2);
- if (rint(num) != num) luaL_typerror(L, 2, "integer");
-
- lua_getfenv(L, 1);
- size_t len = lupb_array_getlen(L, -1);
- // We only allow extending the index one beyond the end.
- if (num < 1 || num > len + 1) luaL_error(L, "array bounds check failed");
- lua_pushvalue(L, 3);
- lua_rawseti(L, -2, num);
+ upb_status s = UPB_STATUS_INIT;
+ upb_def_freeze(defs, n, &s);
+ free(defs);
+ lupb_checkstatus(L, &s);
return 0;
}
-static const struct luaL_Reg lupb_array_mm[] = {
- {"__len", lupb_array_len},
- {"__index", lupb_array_index},
- {"__newindex", lupb_array_newindex},
- {NULL, NULL}
-};
-
-/* lupb toplevel **************************************************************/
-
static const struct luaL_Reg lupb_toplevel_m[] = {
- {"SymbolTable", lupb_symtab_new},
- {"MessageDef", lupb_msgdef_new},
+ {"EnumDef", lupb_enumdef_new},
{"FieldDef", lupb_fielddef_new},
-
- {"Message", lupb_msg_new},
- {"Array", lupb_array_new},
-
- {"clear", lupb_clear},
- {"msgdef", lupb_msgdef},
- {"has", lupb_has},
+ {"MessageDef", lupb_msgdef_new},
+ {"SymbolTable", lupb_symtab_new},
+ {"freeze", lupb_def_freeze},
{NULL, NULL}
};
@@ -950,14 +991,12 @@ static const struct luaL_Reg lupb_toplevel_m[] = {
static void lupb_register_type(lua_State *L, const char *name,
const luaL_Reg *m, const luaL_Reg *mm) {
luaL_newmetatable(L, name);
- luaL_register(L, NULL, mm); // Register all mm in the metatable.
+ lupb_setfuncs(L, mm); // Register all mm in the metatable.
lua_createtable(L, 0, 0);
- if (m) {
- // Methods go in the mt's __index method. This implies that you can't
- // implement __index and also set methods yourself.
- luaL_register(L, NULL, m);
- lua_setfield(L, -2, "__index");
- }
+ // Methods go in the mt's __index method. This implies that you can't
+ // implement __index.
+ lupb_setfuncs(L, m);
+ lua_setfield(L, -2, "__index");
lua_pop(L, 1); // The mt.
}
@@ -967,46 +1006,71 @@ static void lupb_setfieldi(lua_State *L, const char *field, int i) {
}
int luaopen_upb(lua_State *L) {
- lupb_register_type(L, "upb.msgdef", lupb_msgdef_m, lupb_msgdef_mm);
- lupb_register_type(L, "upb.enumdef", lupb_enumdef_m, lupb_enumdef_mm);
- lupb_register_type(L, "upb.fielddef", NULL, lupb_fielddef_mm);
- lupb_register_type(L, "upb.symtab", lupb_symtab_m, lupb_symtab_mm);
-
- lupb_register_type(L, "upb.msg", NULL, lupb_msg_mm);
- lupb_register_type(L, "upb.array", NULL, lupb_msg_mm);
+ lupb_register_type(L, LUPB_MSGDEF, lupb_msgdef_m, lupb_msgdef_mm);
+ lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm);
+ lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, lupb_fielddef_mm);
+ lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, lupb_symtab_mm);
// Create our object cache.
- lua_createtable(L, 0, 0);
+ lua_newtable(L);
lua_createtable(L, 0, 1); // Cache metatable.
lua_pushstring(L, "v"); // Values are weak.
lua_setfield(L, -2, "__mode");
- lua_setfield(L, LUA_REGISTRYINDEX, "upb.objcache");
+ lua_setmetatable(L, -2);
+ lua_setfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE);
+
+ lupb_newlib(L, "upb", lupb_toplevel_m);
+
+ // Define a couple functions as Lua source (kept here instead of a separate
+ // Lua file so that upb.so is self-contained)
+ const char *lua_source =
+ "return function(upb)\n"
+ " upb.build_defs = function(defs)\n"
+ " local symtab = upb.SymbolTable(defs)\n"
+ " return symtab:getdefs(upb.DEF_ANY)\n"
+ " end\n"
+ "end";
- luaL_register(L, "upb", lupb_toplevel_m);
+ if (luaL_dostring(L, lua_source) != 0)
+ lua_error(L);
+
+ // Call the chunk that will define the extra functions on upb, passing our
+ // package dictionary as the argument.
+ lua_pushvalue(L, -2);
+ lua_call(L, 1, 0);
// Register constants.
lupb_setfieldi(L, "LABEL_OPTIONAL", UPB_LABEL(OPTIONAL));
lupb_setfieldi(L, "LABEL_REQUIRED", UPB_LABEL(REQUIRED));
lupb_setfieldi(L, "LABEL_REPEATED", UPB_LABEL(REPEATED));
- lupb_setfieldi(L, "TYPE_DOUBLE", UPB_TYPE(DOUBLE));
- lupb_setfieldi(L, "TYPE_FLOAT", UPB_TYPE(FLOAT));
- lupb_setfieldi(L, "TYPE_INT64", UPB_TYPE(INT64));
- lupb_setfieldi(L, "TYPE_UINT64", UPB_TYPE(UINT64));
- lupb_setfieldi(L, "TYPE_INT32", UPB_TYPE(INT32));
- lupb_setfieldi(L, "TYPE_FIXED64", UPB_TYPE(FIXED64));
- lupb_setfieldi(L, "TYPE_FIXED32", UPB_TYPE(FIXED32));
- lupb_setfieldi(L, "TYPE_BOOL", UPB_TYPE(BOOL));
- lupb_setfieldi(L, "TYPE_STRING", UPB_TYPE(STRING));
- lupb_setfieldi(L, "TYPE_GROUP", UPB_TYPE(GROUP));
- lupb_setfieldi(L, "TYPE_MESSAGE", UPB_TYPE(MESSAGE));
- lupb_setfieldi(L, "TYPE_BYTES", UPB_TYPE(BYTES));
- lupb_setfieldi(L, "TYPE_UINT32", UPB_TYPE(UINT32));
- lupb_setfieldi(L, "TYPE_ENUM", UPB_TYPE(ENUM));
- lupb_setfieldi(L, "TYPE_SFIXED32", UPB_TYPE(SFIXED32));
- lupb_setfieldi(L, "TYPE_SFIXED64", UPB_TYPE(SFIXED64));
- lupb_setfieldi(L, "TYPE_SINT32", UPB_TYPE(SINT32));
- lupb_setfieldi(L, "TYPE_SINT64", UPB_TYPE(SINT64));
+ lupb_setfieldi(L, "TYPE_DOUBLE", UPB_TYPE(DOUBLE));
+ lupb_setfieldi(L, "TYPE_FLOAT", UPB_TYPE(FLOAT));
+ lupb_setfieldi(L, "TYPE_INT64", UPB_TYPE(INT64));
+ lupb_setfieldi(L, "TYPE_UINT64", UPB_TYPE(UINT64));
+ lupb_setfieldi(L, "TYPE_INT32", UPB_TYPE(INT32));
+ lupb_setfieldi(L, "TYPE_FIXED64", UPB_TYPE(FIXED64));
+ lupb_setfieldi(L, "TYPE_FIXED32", UPB_TYPE(FIXED32));
+ lupb_setfieldi(L, "TYPE_BOOL", UPB_TYPE(BOOL));
+ lupb_setfieldi(L, "TYPE_STRING", UPB_TYPE(STRING));
+ lupb_setfieldi(L, "TYPE_GROUP", UPB_TYPE(GROUP));
+ lupb_setfieldi(L, "TYPE_MESSAGE", UPB_TYPE(MESSAGE));
+ lupb_setfieldi(L, "TYPE_BYTES", UPB_TYPE(BYTES));
+ lupb_setfieldi(L, "TYPE_UINT32", UPB_TYPE(UINT32));
+ lupb_setfieldi(L, "TYPE_ENUM", UPB_TYPE(ENUM));
+ lupb_setfieldi(L, "TYPE_SFIXED32", UPB_TYPE(SFIXED32));
+ lupb_setfieldi(L, "TYPE_SFIXED64", UPB_TYPE(SFIXED64));
+ lupb_setfieldi(L, "TYPE_SINT32", UPB_TYPE(SINT32));
+ lupb_setfieldi(L, "TYPE_SINT64", UPB_TYPE(SINT64));
+
+ lupb_setfieldi(L, "DEF_MSG", UPB_DEF_MSG);
+ lupb_setfieldi(L, "DEF_FIELD", UPB_DEF_FIELD);
+ lupb_setfieldi(L, "DEF_ENUM", UPB_DEF_ENUM);
+ lupb_setfieldi(L, "DEF_SERVICE", UPB_DEF_SERVICE);
+ lupb_setfieldi(L, "DEF_ANY", UPB_DEF_ANY);
return 1; // Return package table.
}
+
+// Alternate names so that the library can be loaded as upb5_1 etc.
+int LUPB_OPENFUNC(upb)(lua_State *L) { return luaopen_upb(L); }
diff --git a/bindings/lua/upb.h b/bindings/lua/upb.h
new file mode 100644
index 0000000..e6b4f2f
--- /dev/null
+++ b/bindings/lua/upb.h
@@ -0,0 +1,45 @@
+/*
+ * upb - a minimalist implementation of protocol buffers.
+ *
+ * Copyright (c) 2012 Google Inc. See LICENSE for details.
+ * Author: Josh Haberman <jhaberman@gmail.com>
+ *
+ * Shared definitions for upb Lua modules.
+ */
+
+#ifndef UPB_LUA_UPB_H_
+#define UPB_LUA_UPB_H_
+
+#include "upb/def.h"
+
+// Lua 5.1/5.2 compatibility code.
+#if LUA_VERSION_NUM == 501
+
+#define lua_rawlen lua_objlen
+#define lupb_newlib(L, name, l) luaL_register(L, name, l)
+#define lupb_setfuncs(L, l) luaL_register(L, NULL, l)
+#define LUPB_OPENFUNC(mod) luaopen_ ## mod ## upb5_1
+
+void *luaL_testudata(lua_State *L, int ud, const char *tname);
+
+#elif LUA_VERSION_NUM == 502
+
+// Lua 5.2 modules are not expected to set a global variable, so "name" is
+// unused.
+#define lupb_newlib(L, name, l) luaL_newlib(L, l)
+#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0)
+int luaL_typerror(lua_State *L, int narg, const char *tname);
+#define LUPB_OPENFUNC(mod) luaopen_ ## mod ## upb5_2
+
+#else
+#error Only Lua 5.1 and 5.2 are supported
+#endif
+
+const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg);
+const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg);
+const char *lupb_checkname(lua_State *L, int narg);
+bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner);
+void lupb_def_pushnewrapper(lua_State *L, const upb_def *def,
+ const void *owner);
+
+#endif // UPB_LUA_UPB_H_
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback