You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2015/11/26 05:24:36 UTC
[1/3] qpid-proton git commit: NO-JIRAL: Remove some unnecessary
global constants from the program data segment
Repository: qpid-proton
Updated Branches:
refs/heads/go1 9e788b2d4 -> dfb5b06d5
NO-JIRAL: Remove some unnecessary global constants from the program data segment
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/37be7760
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/37be7760
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/37be7760
Branch: refs/heads/go1
Commit: 37be7760324e92045135c244d4722bb7624ecd4b
Parents: 1cfa056
Author: Andrew Stitcher <as...@apache.org>
Authored: Mon Nov 23 18:11:07 2015 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Tue Nov 24 10:23:58 2015 -0500
----------------------------------------------------------------------
proton-c/include/proton/object.h | 8 +++++---
proton-c/src/codec/codec.c | 7 +++++--
proton-c/src/object/map.c | 12 +++++++-----
proton-c/src/object/object.c | 9 +++------
proton-c/src/protocol.h.py | 27 ++++++++++++++-------------
5 files changed, 34 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37be7760/proton-c/include/proton/object.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/object.h b/proton-c/include/proton/object.h
index 064b082..8595eae 100644
--- a/proton-c/include/proton/object.h
+++ b/proton-c/include/proton/object.h
@@ -61,9 +61,11 @@ struct pn_class_t {
int (*inspect)(void *, pn_string_t *);
};
-PN_EXTERN extern const pn_class_t * const PN_OBJECT;
-PN_EXTERN extern const pn_class_t * const PN_VOID;
-PN_EXTERN extern const pn_class_t * const PN_WEAKREF;
+// Hack alert: Declare these as arrays so we can treat the name
+// of the single object as the address
+PN_EXTERN extern const pn_class_t PN_OBJECT[];
+PN_EXTERN extern const pn_class_t PN_VOID[];
+PN_EXTERN extern const pn_class_t PN_WEAKREF[];
#define PN_CLASSDEF(PREFIX) \
static void PREFIX ## _initialize_cast(void *object) { \
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37be7760/proton-c/src/codec/codec.c
----------------------------------------------------------------------
diff --git a/proton-c/src/codec/codec.c b/proton-c/src/codec/codec.c
index 1e58251..45026ee 100644
--- a/proton-c/src/codec/codec.c
+++ b/proton-c/src/codec/codec.c
@@ -68,6 +68,7 @@ const char *pn_type_name(pn_type_t type)
case PN_ARRAY: return "PN_ARRAY";
case PN_LIST: return "PN_LIST";
case PN_MAP: return "PN_MAP";
+ default: break;
}
return "<UNKNOWN>";
@@ -267,7 +268,7 @@ int pni_inspect_enter(void *ctx, pn_data_t *data, pni_node_t *node)
return 0;
}
const char *name = (index < grandfields->field_count)
- ? FIELD_STRINGPOOL+FIELD_FIELDS[grandfields->first_field_index+index]
+ ? FIELD_STRINGPOOL.STRING0+FIELD_FIELDS[grandfields->first_field_index+index]
: NULL;
if (name) {
err = pn_string_addf(str, "%s=", name);
@@ -287,7 +288,7 @@ int pni_inspect_enter(void *ctx, pn_data_t *data, pni_node_t *node)
return pn_string_addf(str, "{");
default:
if (fields && index == 0) {
- err = pn_string_addf(str, "%s", FIELD_STRINGPOOL+FIELD_NAME[fields->name_index]);
+ err = pn_string_addf(str, "%s", FIELD_STRINGPOOL.STRING0+FIELD_NAME[fields->name_index]);
if (err) return err;
err = pn_string_addf(str, "(");
if (err) return err;
@@ -2130,6 +2131,8 @@ int pn_data_appendn(pn_data_t *data, pn_data_t *src, int limit)
pn_data_enter(src);
level++;
break;
+ default:
+ break;
}
if (err) { pn_data_restore(src, point); return err; }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37be7760/proton-c/src/object/map.c
----------------------------------------------------------------------
diff --git a/proton-c/src/object/map.c b/proton-c/src/object/map.c
index d0dc714..20bb4ea 100644
--- a/proton-c/src/object/map.c
+++ b/proton-c/src/object/map.c
@@ -392,10 +392,8 @@ static bool pni_identity_equals(void *a, void *b)
return a == b;
}
-extern const pn_class_t * const PN_UINTPTR;
-
#define CID_pni_uintptr CID_pn_void
-static const pn_class_t *pni_uintptr_reify(void *object) { return PN_UINTPTR; }
+static const pn_class_t *pni_uintptr_reify(void *object);
#define pni_uintptr_new NULL
#define pni_uintptr_free NULL
#define pni_uintptr_initialize NULL
@@ -407,8 +405,12 @@ static int pni_uintptr_refcount(void *object) { return -1; }
#define pni_uintptr_compare NULL
#define pni_uintptr_inspect NULL
-static const pn_class_t PNI_UINTPTR = PN_METACLASS(pni_uintptr);
-const pn_class_t * const PN_UINTPTR = &PNI_UINTPTR;
+static const pn_class_t PN_UINTPTR[] = {PN_METACLASS(pni_uintptr)};
+
+static const pn_class_t *pni_uintptr_reify(void *object)
+{
+ return PN_UINTPTR;
+}
pn_hash_t *pn_hash(const pn_class_t *clazz, size_t capacity, float load_factor)
{
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37be7760/proton-c/src/object/object.c
----------------------------------------------------------------------
diff --git a/proton-c/src/object/object.c b/proton-c/src/object/object.c
index 4137f07..b0c1b33 100644
--- a/proton-c/src/object/object.c
+++ b/proton-c/src/object/object.c
@@ -29,8 +29,7 @@
uintptr_t pn_object_hashcode(void *object) { return (uintptr_t) object; }
intptr_t pn_object_compare(void *a, void *b) { return (intptr_t) a - (intptr_t) b; }
-static const pn_class_t PNI_OBJECT = PN_CLASS(pn_object);
-const pn_class_t * const PN_OBJECT = &PNI_OBJECT;
+const pn_class_t PN_OBJECT[] = {PN_CLASS(pn_object)};
#define pn_void_initialize NULL
static void *pn_void_new(const pn_class_t *clazz, size_t size) { return malloc(size); }
@@ -44,8 +43,7 @@ uintptr_t pn_void_hashcode(void *object) { return (uintptr_t) object; }
intptr_t pn_void_compare(void *a, void *b) { return (intptr_t) a - (intptr_t) b; }
int pn_void_inspect(void *object, pn_string_t *dst) { return pn_string_addf(dst, "%p", object); }
-static const pn_class_t PNI_VOID = PN_METACLASS(pn_void);
-const pn_class_t * const PN_VOID = &PNI_VOID;
+const pn_class_t PN_VOID[] = {PN_METACLASS(pn_void)};
const char *pn_class_name(const pn_class_t *clazz)
{
@@ -311,5 +309,4 @@ static int pn_weakref_inspect(void *object, pn_string_t *dst) {
return pn_inspect(object, dst);
}
-static const pn_class_t PNI_WEAKREF = PN_METACLASS(pn_weakref);
-const pn_class_t * const PN_WEAKREF = &PNI_WEAKREF;
+const pn_class_t PN_WEAKREF[] = {PN_METACLASS(pn_weakref)};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37be7760/proton-c/src/protocol.h.py
----------------------------------------------------------------------
diff --git a/proton-c/src/protocol.h.py b/proton-c/src/protocol.h.py
index bbc0dfe..0f58906 100644
--- a/proton-c/src/protocol.h.py
+++ b/proton-c/src/protocol.h.py
@@ -57,17 +57,12 @@ typedef struct {
} pn_fields_t;
extern const pn_fields_t FIELDS[];
-extern const char * const FIELD_STRINGPOOL;
extern const uint16_t FIELD_NAME[];
extern const uint16_t FIELD_FIELDS[];
-extern const unsigned char FIELD_MIN;
-extern const unsigned char FIELD_MAX;
""")
-print("#ifdef DEFINE_FIELDS")
-
print('struct FIELD_STRINGS {')
-print(' const char FIELD_STRINGS_NULL[sizeof("")];')
+print(' const char STRING0[sizeof("")];')
strings = set()
for name, fnames in fields.values():
strings.add(name)
@@ -77,16 +72,20 @@ for str in strings:
print(' const char FIELD_STRINGS_%s[sizeof("%s")];' % (istr, str))
print("};")
print()
-print('const struct FIELD_STRINGS FIELD_STRINGS = {')
+
+print("extern const struct FIELD_STRINGS FIELD_STRINGPOOL;")
+print("#ifdef DEFINE_FIELDS")
+print()
+
+print('const struct FIELD_STRINGS FIELD_STRINGPOOL = {')
print(' "",')
for str in strings:
print(' "%s",'% str)
print("};")
-print('const char * const FIELD_STRINGPOOL = (const char * const) &FIELD_STRINGS;')
print()
print("/* This is an array of offsets into FIELD_STRINGPOOL */")
print("const uint16_t FIELD_NAME[] = {")
-print(" offsetof(struct FIELD_STRINGS, FIELD_STRINGS_NULL),")
+print(" offsetof(struct FIELD_STRINGS, STRING0),")
index = 1
for i in range(256):
if i in fields:
@@ -98,7 +97,7 @@ print("};")
print("/* This is an array of offsets into FIELD_STRINGPOOL */")
print("const uint16_t FIELD_FIELDS[] = {")
-print(" offsetof(struct FIELD_STRINGS, FIELD_STRINGS_NULL),")
+print(" offsetof(struct FIELD_STRINGS, STRING0),")
index = 1
for i in range(256):
if i in fields:
@@ -137,9 +136,11 @@ for i in range(field_min, field_max+1):
print("};")
print()
-print('const unsigned char FIELD_MIN = %d;' % field_min)
-print('const unsigned char FIELD_MAX = %d;' % field_max)
-print()
print("#endif")
print()
+print('enum {')
+print(' FIELD_MIN = %d,' % field_min)
+print(' FIELD_MAX = %d' % field_max)
+print('};')
+print()
print("#endif /* protocol.h */")
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[3/3] qpid-proton git commit: Merge commit 'master' into go1
Posted by as...@apache.org.
Merge commit 'master' into go1
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/dfb5b06d
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/dfb5b06d
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/dfb5b06d
Branch: refs/heads/go1
Commit: dfb5b06d5a81d18ffc10adaba5f927417e7f7011
Parents: 9e788b2 587f3cd
Author: Andrew Stitcher <as...@apache.org>
Authored: Wed Nov 25 23:18:23 2015 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed Nov 25 23:18:23 2015 -0500
----------------------------------------------------------------------
amqp/types.go | 8 +++-----
amqp/unmarshal.go | 6 +++---
2 files changed, 6 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/dfb5b06d/amqp/types.go
----------------------------------------------------------------------
diff --cc amqp/types.go
index abcff25,0000000..697d896
mode 100644,000000..100644
--- a/amqp/types.go
+++ b/amqp/types.go
@@@ -1,203 -1,0 +1,201 @@@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package amqp
+
+// #include <proton/codec.h>
+import "C"
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "time"
+ "unsafe"
+)
+
- type Type C.pn_type_t
-
+// Older proton versions don't define C.PN_INVALID, so define it here.
+// In C it is pn_type_t(-1), in Go use the bitwise NOT operator to get the same value.
- const pnInvalid = ^C.pn_type_t(0)
++const pnInvalid = C.pn_type_t(^0)
+
- func (t Type) String() string {
++func (t C.pn_type_t) String() string {
+ switch C.pn_type_t(t) {
+ case C.PN_NULL:
+ return "null"
+ case C.PN_BOOL:
+ return "bool"
+ case C.PN_UBYTE:
+ return "ubyte"
+ case C.PN_BYTE:
+ return "byte"
+ case C.PN_USHORT:
+ return "ushort"
+ case C.PN_SHORT:
+ return "short"
+ case C.PN_CHAR:
+ return "char"
+ case C.PN_UINT:
+ return "uint"
+ case C.PN_INT:
+ return "int"
+ case C.PN_ULONG:
+ return "ulong"
+ case C.PN_LONG:
+ return "long"
+ case C.PN_TIMESTAMP:
+ return "timestamp"
+ case C.PN_FLOAT:
+ return "float"
+ case C.PN_DOUBLE:
+ return "double"
+ case C.PN_DECIMAL32:
+ return "decimal32"
+ case C.PN_DECIMAL64:
+ return "decimal64"
+ case C.PN_DECIMAL128:
+ return "decimal128"
+ case C.PN_UUID:
+ return "uuid"
+ case C.PN_BINARY:
+ return "binary"
+ case C.PN_STRING:
+ return "string"
+ case C.PN_SYMBOL:
+ return "symbol"
+ case C.PN_DESCRIBED:
+ return "described"
+ case C.PN_ARRAY:
+ return "array"
+ case C.PN_LIST:
+ return "list"
+ case C.PN_MAP:
+ return "map"
+ default:
- if uint32(t) == uint32(pnInvalid) {
++ if t == pnInvalid {
+ return "no-data"
+ }
+ return fmt.Sprintf("unknown-type(%d)", t)
+ }
+}
+
+// Go types
+var (
+ bytesType = reflect.TypeOf([]byte{})
+ valueType = reflect.TypeOf(reflect.Value{})
+)
+
+// TODO aconway 2015-04-08: can't handle AMQP maps with key types that are not valid Go map keys.
+
+// Map is a generic map that can have mixed key and value types and so can represent any AMQP map
+type Map map[interface{}]interface{}
+
+// List is a generic list that can hold mixed values and can represent any AMQP list.
+//
+type List []interface{}
+
+// Symbol is a string that is encoded as an AMQP symbol
+type Symbol string
+
+func (s Symbol) GoString() string { return fmt.Sprintf("s\"%s\"", s) }
+
+// Binary is a string that is encoded as an AMQP binary.
+// It is a string rather than a byte[] because byte[] is not hashable and can't be used as
+// a map key, AMQP frequently uses binary types as map keys. It can convert to and from []byte
+type Binary string
+
+func (b Binary) GoString() string { return fmt.Sprintf("b\"%s\"", b) }
+
+// GoString for Map prints values with their types, useful for debugging.
+func (m Map) GoString() string {
+ out := &bytes.Buffer{}
+ fmt.Fprintf(out, "%T{", m)
+ i := len(m)
+ for k, v := range m {
+ fmt.Fprintf(out, "%T(%#v): %T(%#v)", k, k, v, v)
+ i--
+ if i > 0 {
+ fmt.Fprint(out, ", ")
+ }
+ }
+ fmt.Fprint(out, "}")
+ return out.String()
+}
+
+// GoString for List prints values with their types, useful for debugging.
+func (l List) GoString() string {
+ out := &bytes.Buffer{}
+ fmt.Fprintf(out, "%T{", l)
+ for i := 0; i < len(l); i++ {
+ fmt.Fprintf(out, "%T(%#v)", l[i], l[i])
+ if i == len(l)-1 {
+ fmt.Fprint(out, ", ")
+ }
+ }
+ fmt.Fprint(out, "}")
+ return out.String()
+}
+
+// pnTime converts Go time.Time to Proton millisecond Unix time.
+func pnTime(t time.Time) C.pn_timestamp_t {
+ secs := t.Unix()
+ // Note: sub-second accuracy is not guaraunteed if the Unix time in
+ // nanoseconds cannot be represented by an int64 (sometime around year 2260)
+ msecs := (t.UnixNano() % int64(time.Second)) / int64(time.Millisecond)
+ return C.pn_timestamp_t(secs*1000 + msecs)
+}
+
+// goTime converts a pn_timestamp_t to a Go time.Time.
+func goTime(t C.pn_timestamp_t) time.Time {
+ secs := int64(t) / 1000
+ nsecs := (int64(t) % 1000) * int64(time.Millisecond)
+ return time.Unix(secs, nsecs)
+}
+
+func goBytes(cBytes C.pn_bytes_t) (bytes []byte) {
+ if cBytes.start != nil {
+ bytes = C.GoBytes(unsafe.Pointer(cBytes.start), C.int(cBytes.size))
+ }
+ return
+}
+
+func goString(cBytes C.pn_bytes_t) (str string) {
+ if cBytes.start != nil {
+ str = C.GoStringN(cBytes.start, C.int(cBytes.size))
+ }
+ return
+}
+
+func pnBytes(b []byte) C.pn_bytes_t {
+ if len(b) == 0 {
+ return C.pn_bytes_t{0, nil}
+ } else {
+ return C.pn_bytes_t{C.size_t(len(b)), (*C.char)(unsafe.Pointer(&b[0]))}
+ }
+}
+
+func cPtr(b []byte) *C.char {
+ if len(b) == 0 {
+ return nil
+ }
+ return (*C.char)(unsafe.Pointer(&b[0]))
+}
+
+func cLen(b []byte) C.size_t {
+ return C.size_t(len(b))
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/dfb5b06d/amqp/unmarshal.go
----------------------------------------------------------------------
diff --cc amqp/unmarshal.go
index 25bb519,0000000..05ecb8d
mode 100644,000000..100644
--- a/amqp/unmarshal.go
+++ b/amqp/unmarshal.go
@@@ -1,561 -1,0 +1,561 @@@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+oor more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+package amqp
+
+// #include <proton/codec.h>
+import "C"
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "reflect"
+ "unsafe"
+)
+
+const minDecode = 1024
+
+// Error returned if AMQP data cannot be unmarshaled as the desired Go type.
+type UnmarshalError struct {
+ // The name of the AMQP type.
+ AMQPType string
+ // The Go type.
+ GoType reflect.Type
+}
+
+func newUnmarshalError(pnType C.pn_type_t, v interface{}) *UnmarshalError {
- return &UnmarshalError{Type(pnType).String(), reflect.TypeOf(v)}
++ return &UnmarshalError{C.pn_type_t(pnType).String(), reflect.TypeOf(v)}
+}
+
+func (e UnmarshalError) Error() string {
+ if e.GoType.Kind() != reflect.Ptr {
+ return fmt.Sprintf("cannot unmarshal to type %s, not a pointer", e.GoType)
+ } else {
+ return fmt.Sprintf("cannot unmarshal AMQP %s to %s", e.AMQPType, e.GoType)
+ }
+}
+
+func doRecover(err *error) {
+ r := recover()
+ switch r := r.(type) {
+ case nil:
+ case *UnmarshalError:
+ *err = r
+ default:
+ panic(r)
+ }
+}
+
+//
+// Decoding from a pn_data_t
+//
+// NOTE: we use panic() to signal a decoding error, simplifies decoding logic.
+// We recover() at the highest possible level - i.e. in the exported Unmarshal or Decode.
+//
+
+// Decoder decodes AMQP values from an io.Reader.
+//
+type Decoder struct {
+ reader io.Reader
+ buffer bytes.Buffer
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder has it's own buffer and may read more data than required for the
+// AMQP values requested. Use Buffered to see if there is data left in the
+// buffer.
+//
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{r, bytes.Buffer{}}
+}
+
+// Buffered returns a reader of the data remaining in the Decoder's buffer. The
+// reader is valid until the next call to Decode.
+//
+func (d *Decoder) Buffered() io.Reader {
+ return bytes.NewReader(d.buffer.Bytes())
+}
+
+// Decode reads the next AMQP value from the Reader and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the conversion of AMQP into a Go value.
+//
+func (d *Decoder) Decode(v interface{}) (err error) {
+ defer doRecover(&err)
+ data := C.pn_data(0)
+ defer C.pn_data_free(data)
+ var n int
+ for n == 0 {
+ n, err = decode(data, d.buffer.Bytes())
+ if err != nil {
+ return err
+ }
+ if n == 0 { // n == 0 means not enough data, read more
+ err = d.more()
+ } else {
+ unmarshal(v, data)
+ }
+ }
+ d.buffer.Next(n)
+ return
+}
+
+/*
+Unmarshal decodes AMQP-encoded bytes and stores the result in the value pointed to by v.
+Types are converted as follows:
+
+ +---------------------------+----------------------------------------------------------------------+
+ |To Go types |From AMQP types |
+ +===========================+======================================================================+
+ |bool |bool |
+ +---------------------------+----------------------------------------------------------------------+
+ |int, int8, int16, |Equivalent or smaller signed integer type: byte, short, int, long. |
+ |int32, int64 | |
+ +---------------------------+----------------------------------------------------------------------+
+ |uint, uint8, uint16, |Equivalent or smaller unsigned integer type: ubyte, ushort, uint, |
+ |uint32, uint64 types |ulong |
+ +---------------------------+----------------------------------------------------------------------+
+ |float32, float64 |Equivalent or smaller float or double. |
+ +---------------------------+----------------------------------------------------------------------+
+ |string, []byte |string, symbol or binary. |
+ +---------------------------+----------------------------------------------------------------------+
+ |Symbol |symbol |
+ +---------------------------+----------------------------------------------------------------------+
+ |map[K]T |map, provided all keys and values can unmarshal to types K, T |
+ +---------------------------+----------------------------------------------------------------------+
+ |Map |map, any AMQP map |
+ +---------------------------+----------------------------------------------------------------------+
+ |interface{} |Any AMQP value can be unmarshaled to an interface{} as follows: |
+ | +------------------------+---------------------------------------------+
+ | |AMQP Type |Go Type in interface{} |
+ | +========================+=============================================+
+ | |bool |bool |
+ | +------------------------+---------------------------------------------+
+ | |byte,short,int,long |int8,int16,int32,int64 |
+ | +------------------------+---------------------------------------------+
+ | |ubyte,ushort,uint,ulong |uint8,uint16,uint32,uint64 |
+ | +------------------------+---------------------------------------------+
+ | |float, double |float32, float64 |
+ | +------------------------+---------------------------------------------+
+ | |string |string |
+ | +------------------------+---------------------------------------------+
+ | |symbol |Symbol |
+ | +------------------------+---------------------------------------------+
+ | |binary |Binary |
+ | +------------------------+---------------------------------------------+
+ | |nulll |nil |
+ | +------------------------+---------------------------------------------+
+ | |map |Map |
+ | +------------------------+---------------------------------------------+
+ | |list |List |
+ +---------------------------+------------------------+---------------------------------------------+
+
+The following Go types cannot be unmarshaled: uintptr, function, interface, channel.
+
+TODO
+
+Go types: array, struct.
+
+AMQP types: decimal32/64/128, char (round trip), timestamp, uuid, array, multi-section message bodies.
+
+AMQP maps with mixed/unhashable key types need an alternate representation.
+
+Described types.
+*/
+func Unmarshal(bytes []byte, v interface{}) (n int, err error) {
+ defer doRecover(&err)
+
+ data := C.pn_data(0)
+ defer C.pn_data_free(data)
+ n, err = decode(data, bytes)
+ if err != nil {
+ return 0, err
+ }
+ if n == 0 {
+ return 0, fmt.Errorf("not enough data")
+ } else {
+ unmarshal(v, data)
+ }
+ return n, nil
+}
+
+// more reads more data when we can't parse a complete AMQP type
+func (d *Decoder) more() error {
+ var readSize int64 = minDecode
+ if int64(d.buffer.Len()) > readSize { // Grow by doubling
+ readSize = int64(d.buffer.Len())
+ }
+ var n int64
+ n, err := d.buffer.ReadFrom(io.LimitReader(d.reader, readSize))
+ if n == 0 && err == nil { // ReadFrom won't report io.EOF, just returns 0
+ err = io.EOF
+ }
+ return err
+}
+
+// Unmarshal from data into value pointed at by v.
+func unmarshal(v interface{}, data *C.pn_data_t) {
+ pnType := C.pn_data_type(data)
+ switch v := v.(type) {
+ case *bool:
+ switch pnType {
+ case C.PN_BOOL:
+ *v = bool(C.pn_data_get_bool(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ case *int8:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int8(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int8(C.pn_data_get_byte(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ case *uint8:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint8(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint8(C.pn_data_get_ubyte(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ case *int16:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int16(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int16(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int16(C.pn_data_get_short(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ case *uint16:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint16(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint16(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint16(C.pn_data_get_ushort(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ case *int32:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int32(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int32(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int32(C.pn_data_get_short(data))
+ case C.PN_INT:
+ *v = int32(C.pn_data_get_int(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ case *uint32:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint32(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint32(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint32(C.pn_data_get_ushort(data))
+ case C.PN_UINT:
+ *v = uint32(C.pn_data_get_uint(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *int64:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int64(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int64(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int64(C.pn_data_get_short(data))
+ case C.PN_INT:
+ *v = int64(C.pn_data_get_int(data))
+ case C.PN_LONG:
+ *v = int64(C.pn_data_get_long(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *uint64:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint64(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint64(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint64(C.pn_data_get_ushort(data))
+ case C.PN_ULONG:
+ *v = uint64(C.pn_data_get_ulong(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *int:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = int(C.pn_data_get_char(data))
+ case C.PN_BYTE:
+ *v = int(C.pn_data_get_byte(data))
+ case C.PN_SHORT:
+ *v = int(C.pn_data_get_short(data))
+ case C.PN_INT:
+ *v = int(C.pn_data_get_int(data))
+ case C.PN_LONG:
+ if unsafe.Sizeof(0) == 8 {
+ *v = int(C.pn_data_get_long(data))
+ } else {
+ panic(newUnmarshalError(pnType, v))
+ }
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *uint:
+ switch pnType {
+ case C.PN_CHAR:
+ *v = uint(C.pn_data_get_char(data))
+ case C.PN_UBYTE:
+ *v = uint(C.pn_data_get_ubyte(data))
+ case C.PN_USHORT:
+ *v = uint(C.pn_data_get_ushort(data))
+ case C.PN_UINT:
+ *v = uint(C.pn_data_get_uint(data))
+ case C.PN_ULONG:
+ if unsafe.Sizeof(0) == 8 {
+ *v = uint(C.pn_data_get_ulong(data))
+ } else {
+ panic(newUnmarshalError(pnType, v))
+ }
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *float32:
+ switch pnType {
+ case C.PN_FLOAT:
+ *v = float32(C.pn_data_get_float(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *float64:
+ switch pnType {
+ case C.PN_FLOAT:
+ *v = float64(C.pn_data_get_float(data))
+ case C.PN_DOUBLE:
+ *v = float64(C.pn_data_get_double(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *string:
+ switch pnType {
+ case C.PN_STRING:
+ *v = goString(C.pn_data_get_string(data))
+ case C.PN_SYMBOL:
+ *v = goString(C.pn_data_get_symbol(data))
+ case C.PN_BINARY:
+ *v = goString(C.pn_data_get_binary(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *[]byte:
+ switch pnType {
+ case C.PN_STRING:
+ *v = goBytes(C.pn_data_get_string(data))
+ case C.PN_SYMBOL:
+ *v = goBytes(C.pn_data_get_symbol(data))
+ case C.PN_BINARY:
+ *v = goBytes(C.pn_data_get_binary(data))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *Binary:
+ switch pnType {
+ case C.PN_BINARY:
+ *v = Binary(goBytes(C.pn_data_get_binary(data)))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *Symbol:
+ switch pnType {
+ case C.PN_SYMBOL:
+ *v = Symbol(goBytes(C.pn_data_get_symbol(data)))
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+
+ case *interface{}:
+ getInterface(data, v)
+
+ default:
+ if reflect.TypeOf(v).Kind() != reflect.Ptr {
+ panic(newUnmarshalError(pnType, v))
+ }
+ switch reflect.TypeOf(v).Elem().Kind() {
+ case reflect.Map:
+ getMap(data, v)
+ case reflect.Slice:
+ getList(data, v)
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+ }
+ err := dataError("unmarshaling", data)
+ if err != nil {
+ panic(err)
+ }
+ return
+}
+
+func rewindUnmarshal(v interface{}, data *C.pn_data_t) {
+ C.pn_data_rewind(data)
+ C.pn_data_next(data)
+ unmarshal(v, data)
+}
+
+// Getting into an interface is driven completely by the AMQP type, since the interface{}
+// target is type-neutral.
+func getInterface(data *C.pn_data_t, v *interface{}) {
+ pnType := C.pn_data_type(data)
+ switch pnType {
- case C.PN_NULL, C.pn_type_t(pnInvalid): // No data.
++ case C.PN_NULL, pnInvalid: // No data.
+ *v = nil
+ case C.PN_BOOL:
+ *v = bool(C.pn_data_get_bool(data))
+ case C.PN_UBYTE:
+ *v = uint8(C.pn_data_get_ubyte(data))
+ case C.PN_BYTE:
+ *v = int8(C.pn_data_get_byte(data))
+ case C.PN_USHORT:
+ *v = uint16(C.pn_data_get_ushort(data))
+ case C.PN_SHORT:
+ *v = int16(C.pn_data_get_short(data))
+ case C.PN_UINT:
+ *v = uint32(C.pn_data_get_uint(data))
+ case C.PN_INT:
+ *v = int32(C.pn_data_get_int(data))
+ case C.PN_CHAR:
+ *v = uint8(C.pn_data_get_char(data))
+ case C.PN_ULONG:
+ *v = uint64(C.pn_data_get_ulong(data))
+ case C.PN_LONG:
+ *v = int64(C.pn_data_get_long(data))
+ case C.PN_FLOAT:
+ *v = float32(C.pn_data_get_float(data))
+ case C.PN_DOUBLE:
+ *v = float64(C.pn_data_get_double(data))
+ case C.PN_BINARY:
+ *v = Binary(goBytes(C.pn_data_get_binary(data)))
+ case C.PN_STRING:
+ *v = goString(C.pn_data_get_string(data))
+ case C.PN_SYMBOL:
+ *v = Symbol(goString(C.pn_data_get_symbol(data)))
+ case C.PN_MAP:
+ m := make(Map)
+ unmarshal(&m, data)
+ *v = m
+ case C.PN_LIST:
+ l := make(List, 0)
+ unmarshal(&l, data)
+ *v = l
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+}
+
+// get into map pointed at by v
+func getMap(data *C.pn_data_t, v interface{}) {
+ mapValue := reflect.ValueOf(v).Elem()
+ mapValue.Set(reflect.MakeMap(mapValue.Type())) // Clear the map
+ switch pnType := C.pn_data_type(data); pnType {
+ case C.PN_MAP:
+ count := int(C.pn_data_get_map(data))
+ if bool(C.pn_data_enter(data)) {
+ defer C.pn_data_exit(data)
+ for i := 0; i < count/2; i++ {
+ if bool(C.pn_data_next(data)) {
+ key := reflect.New(mapValue.Type().Key())
+ unmarshal(key.Interface(), data)
+ if bool(C.pn_data_next(data)) {
+ val := reflect.New(mapValue.Type().Elem())
+ unmarshal(val.Interface(), data)
+ mapValue.SetMapIndex(key.Elem(), val.Elem())
+ }
+ }
+ }
+ }
- case C.pn_type_t(pnInvalid): // Leave the map empty
++ case pnInvalid: // Leave the map empty
+ default:
+ panic(newUnmarshalError(pnType, v))
+ }
+}
+
+func getList(data *C.pn_data_t, v interface{}) {
+ pnType := C.pn_data_type(data)
+ if pnType != C.PN_LIST {
+ panic(newUnmarshalError(pnType, v))
+ }
+ count := int(C.pn_data_get_list(data))
+ listValue := reflect.MakeSlice(reflect.TypeOf(v).Elem(), count, count)
+ if bool(C.pn_data_enter(data)) {
+ for i := 0; i < count; i++ {
+ if bool(C.pn_data_next(data)) {
+ val := reflect.New(listValue.Type().Elem())
+ unmarshal(val.Interface(), data)
+ listValue.Index(i).Set(val.Elem())
+ }
+ }
+ C.pn_data_exit(data)
+ }
+ reflect.ValueOf(v).Elem().Set(listValue)
+}
+
+// decode from bytes.
+// Return bytes decoded or 0 if we could not decode a complete object.
+//
+func decode(data *C.pn_data_t, bytes []byte) (int, error) {
+ if len(bytes) == 0 {
+ return 0, nil
+ }
+ n := int(C.pn_data_decode(data, cPtr(bytes), cLen(bytes)))
+ if n == int(C.PN_UNDERFLOW) {
+ C.pn_error_clear(C.pn_data_error(data))
+ return 0, nil
+ } else if n <= 0 {
+ return 0, fmt.Errorf("unmarshal %s", PnErrorCode(n))
+ }
+ return n, nil
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
[2/3] qpid-proton git commit: NO-JIRA: Eliminate PN_INVALID as global
constant variable taking space in program data segment.
Posted by as...@apache.org.
NO-JIRA: Eliminate PN_INVALID as global constant variable taking space in
program data segment.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/587f3cd8
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/587f3cd8
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/587f3cd8
Branch: refs/heads/go1
Commit: 587f3cd8ff2ac626d02fdb509b9b2540e6f2ab89
Parents: 37be776
Author: Andrew Stitcher <as...@apache.org>
Authored: Tue Nov 24 10:22:01 2015 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Tue Nov 24 14:08:08 2015 -0500
----------------------------------------------------------------------
proton-c/bindings/go/src/qpid.apache.org/amqp/types.go | 8 +++-----
.../bindings/go/src/qpid.apache.org/amqp/unmarshal.go | 6 +++---
proton-c/include/proton/codec.h | 11 +++++++----
proton-c/src/codec/codec.c | 2 --
4 files changed, 13 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/587f3cd8/proton-c/bindings/go/src/qpid.apache.org/amqp/types.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/types.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/types.go
index abcff25..697d896 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/types.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/types.go
@@ -30,13 +30,11 @@ import (
"unsafe"
)
-type Type C.pn_type_t
-
// Older proton versions don't define C.PN_INVALID, so define it here.
// In C it is pn_type_t(-1), in Go use the bitwise NOT operator to get the same value.
-const pnInvalid = ^C.pn_type_t(0)
+const pnInvalid = C.pn_type_t(^0)
-func (t Type) String() string {
+func (t C.pn_type_t) String() string {
switch C.pn_type_t(t) {
case C.PN_NULL:
return "null"
@@ -89,7 +87,7 @@ func (t Type) String() string {
case C.PN_MAP:
return "map"
default:
- if uint32(t) == uint32(pnInvalid) {
+ if t == pnInvalid {
return "no-data"
}
return fmt.Sprintf("unknown-type(%d)", t)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/587f3cd8/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go b/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
index 25bb519..05ecb8d 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/unmarshal.go
@@ -41,7 +41,7 @@ type UnmarshalError struct {
}
func newUnmarshalError(pnType C.pn_type_t, v interface{}) *UnmarshalError {
- return &UnmarshalError{Type(pnType).String(), reflect.TypeOf(v)}
+ return &UnmarshalError{C.pn_type_t(pnType).String(), reflect.TypeOf(v)}
}
func (e UnmarshalError) Error() string {
@@ -451,7 +451,7 @@ func rewindUnmarshal(v interface{}, data *C.pn_data_t) {
func getInterface(data *C.pn_data_t, v *interface{}) {
pnType := C.pn_data_type(data)
switch pnType {
- case C.PN_NULL, C.pn_type_t(pnInvalid): // No data.
+ case C.PN_NULL, pnInvalid: // No data.
*v = nil
case C.PN_BOOL:
*v = bool(C.pn_data_get_bool(data))
@@ -517,7 +517,7 @@ func getMap(data *C.pn_data_t, v interface{}) {
}
}
}
- case C.pn_type_t(pnInvalid): // Leave the map empty
+ case pnInvalid: // Leave the map empty
default:
panic(newUnmarshalError(pnType, v))
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/587f3cd8/proton-c/include/proton/codec.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/codec.h b/proton-c/include/proton/codec.h
index 3f6a6dc..3f7e5ac 100644
--- a/proton-c/include/proton/codec.h
+++ b/proton-c/include/proton/codec.h
@@ -174,11 +174,14 @@ typedef enum {
* An AMQP map. A polymorphic container of other AMQP values formed
* into key/value pairs.
*/
- PN_MAP = 25
-} pn_type_t;
+ PN_MAP = 25,
-/** A special invalid type value that is returned when no valid type is available. */
-PN_EXTERN extern const pn_type_t PN_INVALID;
+ /**
+ * A special invalid type value that is returned when no valid type
+ * is available.
+ */
+ PN_INVALID = -1
+} pn_type_t;
/**
* Return a string name for an AMQP type.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/587f3cd8/proton-c/src/codec/codec.c
----------------------------------------------------------------------
diff --git a/proton-c/src/codec/codec.c b/proton-c/src/codec/codec.c
index 45026ee..1cc1ee7 100644
--- a/proton-c/src/codec/codec.c
+++ b/proton-c/src/codec/codec.c
@@ -74,8 +74,6 @@ const char *pn_type_name(pn_type_t type)
return "<UNKNOWN>";
}
-const pn_type_t PN_INVALID = (pn_type_t) -1;
-
static inline void pni_atom_init(pn_atom_t *atom, pn_type_t type)
{
memset(atom, 0, sizeof(pn_atom_t));
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org