You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2013/09/03 14:45:45 UTC
svn commit: r1519669 - in /qpid/proton/trunk/proton-c: CMakeLists.txt
src/codec/codec.c src/codec/decoder.c src/codec/decoder.h
Author: rhs
Date: Tue Sep 3 12:45:45 2013
New Revision: 1519669
URL: http://svn.apache.org/r1519669
Log:
removed extra layer of decode; separate decode functionality out of codec.c
Added:
qpid/proton/trunk/proton-c/src/codec/decoder.c
qpid/proton/trunk/proton-c/src/codec/decoder.h
Modified:
qpid/proton/trunk/proton-c/CMakeLists.txt
qpid/proton/trunk/proton-c/src/codec/codec.c
Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1519669&r1=1519668&r2=1519669&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
+++ qpid/proton/trunk/proton-c/CMakeLists.txt Tue Sep 3 12:45:45 2013
@@ -244,6 +244,7 @@ set (qpid-proton-core
src/framing/framing.c
src/codec/codec.c
+ src/codec/decoder.c
src/dispatcher/dispatcher.c
src/engine/engine.c
Modified: qpid/proton/trunk/proton-c/src/codec/codec.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/codec/codec.c?rev=1519669&r1=1519668&r2=1519669&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/codec/codec.c (original)
+++ qpid/proton/trunk/proton-c/src/codec/codec.c Tue Sep 3 12:45:45 2013
@@ -35,6 +35,7 @@
#include "../platform.h"
#include "../platform_fmt.h"
#include "../util.h"
+#include "decoder.h"
#define PN_DESCRIPTOR (PN_DESCRIBED)
#define PN_TYPE (64)
@@ -72,13 +73,9 @@ typedef struct {
pn_iatom_t *start;
} pn_atoms_t;
-int pn_decode_atoms(pn_bytes_t *bytes, pn_atoms_t *atoms);
-int pn_decode_one(pn_bytes_t *bytes, pn_atoms_t *atoms);
-
-int pn_print_atom(pn_iatom_t atom);
-int pn_print_atoms(const pn_atoms_t *atoms);
-ssize_t pn_format_atoms(char *buf, size_t n, pn_atoms_t atoms);
-int pn_format_atom(pn_bytes_t *bytes, pn_iatom_t atom);
+static int pn_print_atoms(const pn_atoms_t *atoms);
+static ssize_t pn_format_atoms(char *buf, size_t n, pn_atoms_t atoms);
+static int pn_format_atom(pn_bytes_t *bytes, pn_iatom_t atom);
typedef union {
uint32_t i;
@@ -124,9 +121,9 @@ const char *pn_type_name(pn_type_t type)
return "<UNKNOWN>";
}
-size_t pn_bytes_ltrim(pn_bytes_t *bytes, size_t size);
+static size_t pn_bytes_ltrim(pn_bytes_t *bytes, size_t size);
-int pn_bytes_format(pn_bytes_t *bytes, const char *fmt, ...)
+static int pn_bytes_format(pn_bytes_t *bytes, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
@@ -148,21 +145,7 @@ static inline void pn_atom_init(pn_iatom
atom->type = type;
}
-int pn_print_atom(pn_iatom_t atom)
-{
- char buf[256];
- unsigned size = 256;
- pn_bytes_t bytes = pn_bytes(size, buf);
- int err = pn_format_atom(&bytes, atom);
- if (err && err != PN_OVERFLOW)
- return err;
- printf("%.*s", (int) (size - bytes.size), buf);
- if (err)
- printf("... (truncated)");
- return 0;
-}
-
-int pn_format_atom(pn_bytes_t *bytes, pn_iatom_t atom)
+static int pn_format_atom(pn_bytes_t *bytes, pn_iatom_t atom)
{
if (atom.type == PN_TYPE) {
return pn_bytes_format(bytes, "%s", pn_type_name(atom.u.type));
@@ -296,15 +279,7 @@ int pn_format_atom(pn_bytes_t *bytes, pn
return PN_ARG_ERR;
}
-void pn_print_indent(int level)
-{
- for (int i = 0; i < level; i++)
- {
- printf(" ");
- }
-}
-
-size_t pn_bytes_ltrim(pn_bytes_t *bytes, size_t size)
+static size_t pn_bytes_ltrim(pn_bytes_t *bytes, size_t size)
{
if (size > bytes->size)
size = bytes->size;
@@ -314,7 +289,7 @@ size_t pn_bytes_ltrim(pn_bytes_t *bytes,
return size;
}
-size_t pn_atoms_ltrim(pn_atoms_t *atoms, size_t size)
+static size_t pn_atoms_ltrim(pn_atoms_t *atoms, size_t size)
{
if (size > atoms->size)
size = atoms->size;
@@ -325,7 +300,7 @@ size_t pn_atoms_ltrim(pn_atoms_t *atoms,
return size;
}
-int pn_format_atoms_one(pn_bytes_t *bytes, pn_atoms_t *atoms, int level, pn_fields_t *fields)
+static int pn_format_atoms_one(pn_bytes_t *bytes, pn_atoms_t *atoms, int level, pn_fields_t *fields)
{
if (!atoms->size) return PN_UNDERFLOW;
pn_iatom_t *atom = atoms->start;
@@ -417,7 +392,7 @@ int pn_format_atoms_one(pn_bytes_t *byte
}
}
-ssize_t pn_format_atoms(char *buf, size_t n, pn_atoms_t atoms)
+static ssize_t pn_format_atoms(char *buf, size_t n, pn_atoms_t atoms)
{
pn_bytes_t bytes = {n, buf};
pn_atoms_t copy = atoms;
@@ -435,7 +410,7 @@ ssize_t pn_format_atoms(char *buf, size_
return n - bytes.size;
}
-int pn_print_atoms(const pn_atoms_t *atoms)
+static int pn_print_atoms(const pn_atoms_t *atoms)
{
char buf[512];
memset(buf, 0, sizeof(buf));
@@ -448,36 +423,7 @@ int pn_print_atoms(const pn_atoms_t *ato
return 0;
}
-int pn_decode_atom(pn_bytes_t *bytes, pn_atoms_t *atoms);
-
-int pn_decode_atoms(pn_bytes_t *bytes, pn_atoms_t *atoms)
-{
- pn_bytes_t buf = *bytes;
- pn_atoms_t dat = *atoms;
-
- while (buf.size) {
- int e = pn_decode_atom(&buf, &dat);
- if (e) return e;
- }
-
- atoms->size -= dat.size;
- return 0;
-}
-
-int pn_decode_one(pn_bytes_t *bytes, pn_atoms_t *atoms)
-{
- pn_bytes_t buf = *bytes;
- pn_atoms_t dat = *atoms;
-
- int e = pn_decode_atom(&buf, &dat);
- if (e) return e;
-
- atoms->size -= dat.size;
- bytes->size -= buf.size;
- return 0;
-}
-
-uint8_t pn_type2code(pn_type_t type)
+static uint8_t pn_type2code(pn_type_t type)
{
switch (type)
{
@@ -512,7 +458,7 @@ uint8_t pn_type2code(pn_type_t type)
}
}
-static inline int pn_i_bytes_writef8(pn_bytes_t *bytes, uint8_t value)
+static inline int pni_bytes_writef8(pn_bytes_t *bytes, uint8_t value)
{
if (bytes->size) {
bytes->start[0] = value;
@@ -523,7 +469,7 @@ static inline int pn_i_bytes_writef8(pn_
}
}
-static inline int pn_i_bytes_writef16(pn_bytes_t *bytes, uint16_t value)
+static inline int pni_bytes_writef16(pn_bytes_t *bytes, uint16_t value)
{
if (bytes->size < 2) {
return PN_OVERFLOW;
@@ -535,7 +481,7 @@ static inline int pn_i_bytes_writef16(pn
}
}
-static inline int pn_i_bytes_writef32(pn_bytes_t *bytes, uint32_t value)
+static inline int pni_bytes_writef32(pn_bytes_t *bytes, uint32_t value)
{
if (bytes->size < 4) {
return PN_OVERFLOW;
@@ -549,7 +495,7 @@ static inline int pn_i_bytes_writef32(pn
}
}
-static inline int pn_i_bytes_writef64(pn_bytes_t *bytes, uint64_t value) {
+static inline int pni_bytes_writef64(pn_bytes_t *bytes, uint64_t value) {
if (bytes->size < 8) {
return PN_OVERFLOW;
} else {
@@ -566,7 +512,7 @@ static inline int pn_i_bytes_writef64(pn
}
}
-static inline int pn_i_bytes_writef128(pn_bytes_t *bytes, char *value) {
+static inline int pni_bytes_writef128(pn_bytes_t *bytes, char *value) {
if (bytes->size < 16) {
return PN_OVERFLOW;
} else {
@@ -576,12 +522,12 @@ static inline int pn_i_bytes_writef128(p
}
}
-static inline int pn_i_bytes_writev8(pn_bytes_t *bytes, const pn_bytes_t *value)
+static inline int pni_bytes_writev8(pn_bytes_t *bytes, const pn_bytes_t *value)
{
if (bytes->size < 1 + value->size) {
return PN_OVERFLOW;
} else {
- int e = pn_i_bytes_writef8(bytes, value->size);
+ int e = pni_bytes_writef8(bytes, value->size);
if (e) return e;
memmove(bytes->start, value->start, value->size);
pn_bytes_ltrim(bytes, value->size);
@@ -589,12 +535,12 @@ static inline int pn_i_bytes_writev8(pn_
}
}
-static inline int pn_i_bytes_writev32(pn_bytes_t *bytes, const pn_bytes_t *value)
+static inline int pni_bytes_writev32(pn_bytes_t *bytes, const pn_bytes_t *value)
{
if (bytes->size < 4 + value->size) {
return PN_OVERFLOW;
} else {
- int e = pn_i_bytes_writef32(bytes, value->size);
+ int e = pni_bytes_writef32(bytes, value->size);
if (e) return e;
memmove(bytes->start, value->start, value->size);
pn_bytes_ltrim(bytes, value->size);
@@ -602,403 +548,6 @@ static inline int pn_i_bytes_writev32(pn
}
}
-int pn_decode_type(pn_bytes_t *bytes, pn_atoms_t *atoms, uint8_t *code)
-{
- if (!bytes->size) return PN_UNDERFLOW;
- if (!atoms->size) return PN_OVERFLOW;
-
- if (bytes->start[0] != PNE_DESCRIPTOR) {
- *code = bytes->start[0];
- pn_bytes_ltrim(bytes, 1);
- return 0;
- } else {
- pn_atom_init(&atoms->start[0], PN_DESCRIPTOR);
- pn_bytes_ltrim(bytes, 1);
- pn_atoms_ltrim(atoms, 1);
- int e = pn_decode_atom(bytes, atoms);
- if (e) return e;
- e = pn_decode_type(bytes, atoms, code);
- return e;
- }
-}
-
-pn_type_t pn_code2type(uint8_t code)
-{
- switch (code)
- {
- case PNE_DESCRIPTOR:
- return (pn_type_t) PN_ARG_ERR;
- case PNE_NULL:
- return PN_NULL;
- case PNE_TRUE:
- case PNE_FALSE:
- case PNE_BOOLEAN:
- return PN_BOOL;
- case PNE_UBYTE:
- return PN_UBYTE;
- case PNE_BYTE:
- return PN_BYTE;
- case PNE_USHORT:
- return PN_USHORT;
- case PNE_SHORT:
- return PN_SHORT;
- case PNE_UINT0:
- case PNE_SMALLUINT:
- case PNE_SMALLINT:
- case PNE_UINT:
- return PN_UINT;
- case PNE_INT:
- return PN_INT;
- case PNE_UTF32:
- return PN_CHAR;
- case PNE_FLOAT:
- return PN_FLOAT;
- case PNE_LONG:
- return PN_LONG;
- case PNE_MS64:
- return PN_TIMESTAMP;
- case PNE_DOUBLE:
- return PN_DOUBLE;
- case PNE_DECIMAL32:
- return PN_DECIMAL32;
- case PNE_DECIMAL64:
- return PN_DECIMAL64;
- case PNE_DECIMAL128:
- return PN_DECIMAL128;
- case PNE_UUID:
- return PN_UUID;
- case PNE_ULONG0:
- case PNE_SMALLULONG:
- case PNE_SMALLLONG:
- case PNE_ULONG:
- return PN_ULONG;
- case PNE_VBIN8:
- case PNE_VBIN32:
- return PN_BINARY;
- case PNE_STR8_UTF8:
- case PNE_STR32_UTF8:
- return PN_STRING;
- case PNE_SYM8:
- case PNE_SYM32:
- return PN_SYMBOL;
- case PNE_LIST0:
- case PNE_LIST8:
- case PNE_LIST32:
- return PN_LIST;
- case PNE_ARRAY8:
- case PNE_ARRAY32:
- return PN_ARRAY;
- case PNE_MAP8:
- case PNE_MAP32:
- return PN_MAP;
- default:
- printf("Unrecognised typecode: %u\n", code);
- return (pn_type_t) PN_ARG_ERR;
- }
-}
-
-static inline uint8_t pn_i_bytes_readf8(pn_bytes_t *bytes)
-{
- uint8_t r = bytes->start[0];
- pn_bytes_ltrim(bytes, 1);
- return r;
-}
-
-static inline uint16_t pn_i_bytes_readf16(pn_bytes_t *bytes)
-{
- uint16_t a = (uint8_t) bytes->start[0];
- uint16_t b = (uint8_t) bytes->start[1];
- uint16_t r = a << 8
- | b;
- pn_bytes_ltrim(bytes, 2);
- return r;
-}
-
-static inline uint32_t pn_i_bytes_readf32(pn_bytes_t *bytes)
-{
- uint32_t a = (uint8_t) bytes->start[0];
- uint32_t b = (uint8_t) bytes->start[1];
- uint32_t c = (uint8_t) bytes->start[2];
- uint32_t d = (uint8_t) bytes->start[3];
- uint32_t r = a << 24
- | b << 16
- | c << 8
- | d;
- pn_bytes_ltrim(bytes, 4);
- return r;
-}
-
-static inline uint64_t pn_i_bytes_readf64(pn_bytes_t *bytes)
-{
- uint64_t a = pn_i_bytes_readf32(bytes);
- uint64_t b = pn_i_bytes_readf32(bytes);
- return a << 32 | b;
-}
-
-int pn_decode_value(pn_bytes_t *bytes, pn_atoms_t *atoms, uint8_t code)
-{
- size_t size;
- size_t count;
- conv_t conv;
-
- if (!atoms->size) return PN_OVERFLOW;
-
- pn_iatom_t atom;
-
- switch (code)
- {
- case PNE_DESCRIPTOR:
- return PN_ARG_ERR;
- case PNE_NULL:
- atom.type=PN_NULL;
- break;
- case PNE_TRUE:
- atom.type=PN_BOOL, atom.u.as_bool=true;
- break;
- case PNE_FALSE:
- atom.type=PN_BOOL, atom.u.as_bool=false;
- break;
- case PNE_BOOLEAN:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_BOOL, atom.u.as_bool=(pn_i_bytes_readf8(bytes) != 0);
- break;
- case PNE_UBYTE:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_UBYTE, atom.u.as_ubyte=pn_i_bytes_readf8(bytes);
- break;
- case PNE_BYTE:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_BYTE, atom.u.as_byte=(int8_t) pn_i_bytes_readf8(bytes);
- break;
- case PNE_USHORT:
- if (bytes->size < 2) return PN_UNDERFLOW;
- atom.type=PN_USHORT, atom.u.as_ushort=pn_i_bytes_readf16(bytes);
- break;
- case PNE_SHORT:
- if (bytes->size < 2) return PN_UNDERFLOW;
- atom.type=PN_SHORT, atom.u.as_short=(int16_t) pn_i_bytes_readf16(bytes);
- break;
- case PNE_UINT:
- if (bytes->size < 4) return PN_UNDERFLOW;
- atom.type=PN_UINT, atom.u.as_uint=pn_i_bytes_readf32(bytes);
- break;
- case PNE_UINT0:
- atom.type=PN_UINT, atom.u.as_uint=0;
- break;
- case PNE_SMALLUINT:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_UINT, atom.u.as_uint=pn_i_bytes_readf8(bytes);
- break;
- case PNE_SMALLINT:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_INT, atom.u.as_int=pn_i_bytes_readf8(bytes);
- break;
- case PNE_INT:
- if (bytes->size < 4) return PN_UNDERFLOW;
- atom.type=PN_INT, atom.u.as_int=(int32_t) pn_i_bytes_readf32(bytes);
- break;
- case PNE_UTF32:
- if (bytes->size < 4) return PN_UNDERFLOW;
- atom.type=PN_CHAR, atom.u.as_char=pn_i_bytes_readf32(bytes);
- break;
- case PNE_FLOAT:
- if (bytes->size < 4) return PN_UNDERFLOW;
- // XXX: this assumes the platform uses IEEE floats
- conv.i = pn_i_bytes_readf32(bytes);
- atom.type=PN_FLOAT, atom.u.as_float=conv.f;
- break;
- case PNE_DECIMAL32:
- if (bytes->size < 4) return PN_UNDERFLOW;
- atom.type=PN_DECIMAL32, atom.u.as_decimal32=pn_i_bytes_readf32(bytes);
- break;
- case PNE_ULONG:
- if (bytes->size < 8) return PN_UNDERFLOW;
- atom.type=PN_ULONG, atom.u.as_ulong=pn_i_bytes_readf64(bytes);
- break;
- case PNE_LONG:
- if (bytes->size < 8) return PN_UNDERFLOW;
- atom.type=PN_LONG, atom.u.as_long=(int64_t) pn_i_bytes_readf64(bytes);
- break;
- case PNE_MS64:
- if (bytes->size < 8) return PN_UNDERFLOW;
- atom.type=PN_TIMESTAMP, atom.u.as_timestamp=(pn_timestamp_t) pn_i_bytes_readf64(bytes);
- break;
- case PNE_DOUBLE:
- // XXX: this assumes the platform uses IEEE floats
- if (bytes->size < 8) return PN_UNDERFLOW;
- conv.l = pn_i_bytes_readf64(bytes);
- atom.type=PN_DOUBLE, atom.u.as_double=conv.d;
- break;
- case PNE_DECIMAL64:
- if (bytes->size < 8) return PN_UNDERFLOW;
- atom.type=PN_DECIMAL64, atom.u.as_decimal64=pn_i_bytes_readf64(bytes);
- break;
- case PNE_ULONG0:
- atom.type=PN_ULONG, atom.u.as_ulong=0;
- break;
- case PNE_SMALLULONG:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_ULONG, atom.u.as_ulong=pn_i_bytes_readf8(bytes);
- break;
- case PNE_SMALLLONG:
- if (!bytes->size) return PN_UNDERFLOW;
- atom.type=PN_LONG, atom.u.as_long=(int8_t) pn_i_bytes_readf8(bytes);
- break;
- case PNE_DECIMAL128:
- if (bytes->size < 16) return PN_UNDERFLOW;
- atom.type = PN_DECIMAL128;
- memmove(&atom.u.as_decimal128.bytes, bytes->start, 16);
- pn_bytes_ltrim(bytes, 16);
- break;
- case PNE_UUID:
- if (bytes->size < 16) return PN_UNDERFLOW;
- atom.type = PN_UUID;
- memmove(atom.u.as_uuid.bytes, bytes->start, 16);
- pn_bytes_ltrim(bytes, 16);
- break;
- case PNE_VBIN8:
- case PNE_STR8_UTF8:
- case PNE_SYM8:
- case PNE_VBIN32:
- case PNE_STR32_UTF8:
- case PNE_SYM32:
- switch (code & 0xF0)
- {
- case 0xA0:
- if (!bytes->size) return PN_UNDERFLOW;
- size = pn_i_bytes_readf8(bytes);
- break;
- case 0xB0:
- if (bytes->size < 4) return PN_UNDERFLOW;
- size = pn_i_bytes_readf32(bytes);
- break;
- default:
- return PN_ARG_ERR;
- }
-
- {
- char *start = (char *) (bytes->start);
- pn_bytes_t binary = {size, start};
- switch (code & 0x0F)
- {
- case 0x0:
- atom.type=PN_BINARY, atom.u.as_binary=binary;
- break;
- case 0x1:
- atom.type=PN_STRING, atom.u.as_binary=binary;
- break;
- case 0x3:
- atom.type=PN_SYMBOL, atom.u.as_binary=binary;
- break;
- default:
- return PN_ARG_ERR;
- }
- }
-
- if (bytes->size < size) return PN_UNDERFLOW;
- pn_bytes_ltrim(bytes, size);
- break;
- case PNE_LIST0:
- atom.type=PN_LIST, atom.u.count=0;
- break;
- case PNE_ARRAY8:
- case PNE_ARRAY32:
- case PNE_LIST8:
- case PNE_LIST32:
- case PNE_MAP8:
- case PNE_MAP32:
- switch (code)
- {
- case PNE_ARRAY8:
- case PNE_LIST8:
- case PNE_MAP8:
- if (bytes->size < 2) return PN_UNDERFLOW;
- size = pn_i_bytes_readf8(bytes);
- count = pn_i_bytes_readf8(bytes);
- break;
- case PNE_ARRAY32:
- case PNE_LIST32:
- case PNE_MAP32:
- size = pn_i_bytes_readf32(bytes);
- count = pn_i_bytes_readf32(bytes);
- break;
- default:
- return PN_ARG_ERR;
- }
-
- switch (code)
- {
- case PNE_ARRAY8:
- case PNE_ARRAY32:
- {
- if (!atoms->size) return PN_OVERFLOW;
- pn_atom_init(&atoms->start[0], PN_ARRAY);
- atoms->start[0].u.count=count;
- pn_atoms_ltrim(atoms, 1);
- uint8_t acode;
- int e = pn_decode_type(bytes, atoms, &acode);
- if (e) return e;
- if (!atoms->size) return PN_OVERFLOW;
- pn_type_t type = pn_code2type(acode);
- if (type < 0) return type;
- pn_atom_init(&atoms->start[0], (pn_type_t) PN_TYPE);
- atoms->start[0].u.type=type;
- pn_atoms_ltrim(atoms, 1);
- for (unsigned i = 0; i < count; i++)
- {
- e = pn_decode_value(bytes, atoms, acode);
- if (e) return e;
- }
- }
- return 0;
- case PNE_LIST8:
- case PNE_LIST32:
- if (!atoms->size) return PN_OVERFLOW;
- pn_atom_init(&atoms->start[0], PN_LIST);
- atoms->start[0].u.count=count;
- pn_atoms_ltrim(atoms, 1);
- break;
- case PNE_MAP8:
- case PNE_MAP32:
- if (!atoms->size) return PN_OVERFLOW;
- pn_atom_init(&atoms->start[0], PN_MAP);
- atoms->start[0].u.count=count;
- pn_atoms_ltrim(atoms, 1);
- break;
- default:
- return PN_ARG_ERR;
- }
-
- for (unsigned i = 0; i < count; i++)
- {
- int e = pn_decode_atom(bytes, atoms);
- if (e) return e;
- }
-
- return 0;
- default:
- printf("Unrecognised typecode: %u\n", code);
- return PN_ARG_ERR;
- }
-
- if (!atoms->size) return PN_OVERFLOW;
- atoms->start[0] = atom;
- pn_atoms_ltrim(atoms, 1);
-
- return 0;
-}
-
-int pn_decode_atom(pn_bytes_t *bytes, pn_atoms_t *atoms)
-{
- uint8_t code;
- int e;
-
- if ((e = pn_decode_type(bytes, atoms, &code))) return e;
- if ((e = pn_decode_value(bytes, atoms, code))) return e;
-
- return 0;
-}
-
// data
typedef struct {
@@ -1030,6 +579,7 @@ struct pn_data_t {
size_t base_parent;
size_t base_current;
size_t extras;
+ pn_decoder_t *decoder;
pn_error_t *error;
};
@@ -1039,6 +589,7 @@ static void pn_data_finalize(void *objec
free(data->nodes);
pn_buffer_free(data->buf);
pn_error_free(data->error);
+ pn_free(data->decoder);
free(data->iatoms);
}
@@ -1079,6 +630,7 @@ pn_data_t *pn_data(size_t capacity)
data->base_parent = 0;
data->base_current = 0;
data->extras = 0;
+ data->decoder = pn_decoder();
data->error = pn_error();
return data;
}
@@ -1957,6 +1509,26 @@ pn_type_t pn_data_type(pn_data_t *data)
}
}
+pn_type_t pni_data_parent_type(pn_data_t *data)
+{
+ pn_node_t *node = pn_data_node(data, data->parent);
+ if (node) {
+ return node->atom.type;
+ } else {
+ return (pn_type_t) -1;
+ }
+}
+
+size_t pn_data_siblings(pn_data_t *data)
+{
+ pn_node_t *node = pn_data_node(data, data->parent);
+ if (node) {
+ return node->children;
+ } else {
+ return 0;
+ }
+}
+
bool pn_data_enter(pn_data_t *data)
{
if (data->current) {
@@ -2208,12 +1780,12 @@ static int pn_data_encode_node(pn_data_t
if (pn_is_in_array(data, parent, node)) {
code = pn_type2code(parent->type);
if (pn_is_first_in_array(data, parent, node)) {
- err = pn_i_bytes_writef8(bytes, code);
+ err = pni_bytes_writef8(bytes, code);
if (err) return err;
}
} else {
code = pn_node2code(node);
- err = pn_i_bytes_writef8(bytes, code);
+ err = pni_bytes_writef8(bytes, code);
if (err) return err;
}
@@ -2222,33 +1794,33 @@ static int pn_data_encode_node(pn_data_t
case PNE_NULL:
case PNE_TRUE:
case PNE_FALSE: return 0;
- case PNE_BOOLEAN: return pn_i_bytes_writef8(bytes, atom->u.as_bool);
- case PNE_UBYTE: return pn_i_bytes_writef8(bytes, atom->u.as_ubyte);
- case PNE_BYTE: return pn_i_bytes_writef8(bytes, atom->u.as_byte);
- case PNE_USHORT: return pn_i_bytes_writef16(bytes, atom->u.as_ushort);
- case PNE_SHORT: return pn_i_bytes_writef16(bytes, atom->u.as_short);
+ case PNE_BOOLEAN: return pni_bytes_writef8(bytes, atom->u.as_bool);
+ case PNE_UBYTE: return pni_bytes_writef8(bytes, atom->u.as_ubyte);
+ case PNE_BYTE: return pni_bytes_writef8(bytes, atom->u.as_byte);
+ case PNE_USHORT: return pni_bytes_writef16(bytes, atom->u.as_ushort);
+ case PNE_SHORT: return pni_bytes_writef16(bytes, atom->u.as_short);
case PNE_UINT0: return 0;
- case PNE_SMALLUINT: return pn_i_bytes_writef8(bytes, atom->u.as_uint);
- case PNE_UINT: return pn_i_bytes_writef32(bytes, atom->u.as_uint);
- case PNE_SMALLINT: return pn_i_bytes_writef8(bytes, atom->u.as_int);
- case PNE_INT: return pn_i_bytes_writef32(bytes, atom->u.as_int);
- case PNE_UTF32: return pn_i_bytes_writef32(bytes, atom->u.as_char);
- case PNE_ULONG: return pn_i_bytes_writef64(bytes, atom->u.as_ulong);
- case PNE_SMALLULONG: return pn_i_bytes_writef8(bytes, atom->u.as_ulong);
- case PNE_LONG: return pn_i_bytes_writef64(bytes, atom->u.as_long);
- case PNE_MS64: return pn_i_bytes_writef64(bytes, atom->u.as_timestamp);
- case PNE_FLOAT: c.f = atom->u.as_float; return pn_i_bytes_writef32(bytes, c.i);
- case PNE_DOUBLE: c.d = atom->u.as_double; return pn_i_bytes_writef64(bytes, c.l);
- case PNE_DECIMAL32: return pn_i_bytes_writef32(bytes, atom->u.as_decimal32);
- case PNE_DECIMAL64: return pn_i_bytes_writef64(bytes, atom->u.as_decimal64);
- case PNE_DECIMAL128: return pn_i_bytes_writef128(bytes, atom->u.as_decimal128.bytes);
- case PNE_UUID: return pn_i_bytes_writef128(bytes, atom->u.as_uuid.bytes);
- case PNE_VBIN8: return pn_i_bytes_writev8(bytes, &atom->u.as_binary);
- case PNE_VBIN32: return pn_i_bytes_writev32(bytes, &atom->u.as_binary);
- case PNE_STR8_UTF8: return pn_i_bytes_writev8(bytes, &atom->u.as_string);
- case PNE_STR32_UTF8: return pn_i_bytes_writev32(bytes, &atom->u.as_string);
- case PNE_SYM8: return pn_i_bytes_writev8(bytes, &atom->u.as_symbol);
- case PNE_SYM32: return pn_i_bytes_writev32(bytes, &atom->u.as_symbol);
+ case PNE_SMALLUINT: return pni_bytes_writef8(bytes, atom->u.as_uint);
+ case PNE_UINT: return pni_bytes_writef32(bytes, atom->u.as_uint);
+ case PNE_SMALLINT: return pni_bytes_writef8(bytes, atom->u.as_int);
+ case PNE_INT: return pni_bytes_writef32(bytes, atom->u.as_int);
+ case PNE_UTF32: return pni_bytes_writef32(bytes, atom->u.as_char);
+ case PNE_ULONG: return pni_bytes_writef64(bytes, atom->u.as_ulong);
+ case PNE_SMALLULONG: return pni_bytes_writef8(bytes, atom->u.as_ulong);
+ case PNE_LONG: return pni_bytes_writef64(bytes, atom->u.as_long);
+ case PNE_MS64: return pni_bytes_writef64(bytes, atom->u.as_timestamp);
+ case PNE_FLOAT: c.f = atom->u.as_float; return pni_bytes_writef32(bytes, c.i);
+ case PNE_DOUBLE: c.d = atom->u.as_double; return pni_bytes_writef64(bytes, c.l);
+ case PNE_DECIMAL32: return pni_bytes_writef32(bytes, atom->u.as_decimal32);
+ case PNE_DECIMAL64: return pni_bytes_writef64(bytes, atom->u.as_decimal64);
+ case PNE_DECIMAL128: return pni_bytes_writef128(bytes, atom->u.as_decimal128.bytes);
+ case PNE_UUID: return pni_bytes_writef128(bytes, atom->u.as_uuid.bytes);
+ case PNE_VBIN8: return pni_bytes_writev8(bytes, &atom->u.as_binary);
+ case PNE_VBIN32: return pni_bytes_writev32(bytes, &atom->u.as_binary);
+ case PNE_STR8_UTF8: return pni_bytes_writev8(bytes, &atom->u.as_string);
+ case PNE_STR32_UTF8: return pni_bytes_writev32(bytes, &atom->u.as_string);
+ case PNE_SYM8: return pni_bytes_writev8(bytes, &atom->u.as_symbol);
+ case PNE_SYM32: return pni_bytes_writev32(bytes, &atom->u.as_symbol);
case PNE_ARRAY32:
node->start = bytes->start;
node->small = false;
@@ -2256,11 +1828,11 @@ static int pn_data_encode_node(pn_data_t
if (bytes->size < 4) return PN_OVERFLOW;
pn_bytes_ltrim(bytes, 4);
- err = pn_i_bytes_writef32(bytes, node->described ? node->children - 1 : node->children);
+ err = pni_bytes_writef32(bytes, node->described ? node->children - 1 : node->children);
if (err) return err;
if (node->described) {
- err = pn_i_bytes_writef8(bytes, 0);
+ err = pni_bytes_writef8(bytes, 0);
if (err) return err;
}
return 0;
@@ -2271,7 +1843,7 @@ static int pn_data_encode_node(pn_data_t
// we'll backfill the size later
if (bytes->size < 4) return PN_OVERFLOW;
pn_bytes_ltrim(bytes, 4);
- return pn_i_bytes_writef32(bytes, node->children);
+ return pni_bytes_writef32(bytes, node->children);
default:
return pn_error_format(data->error, PN_ERR, "unrecognized encoding: %u", code);
}
@@ -2284,7 +1856,7 @@ static int pn_data_encode_node_exit(pn_d
case PN_ARRAY:
if ((node->described && node->children == 1) ||
(!node->described && node->children == 0)) {
- int err = pn_i_bytes_writef8(bytes, pn_type2code(node->type));
+ int err = pni_bytes_writef8(bytes, pn_type2code(node->type));
if (err) return err;
}
case PN_LIST:
@@ -2293,12 +1865,12 @@ static int pn_data_encode_node_exit(pn_d
// backfill size
size_t size = bytes->start - node->start - 1;
pn_bytes_t size_bytes = {1, node->start};
- return pn_i_bytes_writef8(&size_bytes, size);
+ return pni_bytes_writef8(&size_bytes, size);
} else {
// backfill size
size_t size = bytes->start - node->start - 4;
pn_bytes_t size_bytes = {4, node->start};
- return pn_i_bytes_writef32(&size_bytes, size);
+ return pni_bytes_writef32(&size_bytes, size);
}
default:
return 0;
@@ -2344,198 +1916,9 @@ ssize_t pn_data_encode(pn_data_t *data,
return size - lbytes.size;
}
-int pn_data_parse_atoms(pn_data_t *data, pn_atoms_t atoms, int offset, int limit)
-{
- int count = 0;
- int step, i;
-
- for (i = offset; i < (int) atoms.size; i++) {
- if (count == limit) return i - offset;
- pn_iatom_t atom = atoms.start[i];
- if (atom.type == PN_TYPE) return PN_ERR;
- switch (atom.type)
- {
- case PN_NULL:
- pn_data_put_null(data);
- count++;
- break;
- case PN_BOOL:
- pn_data_put_bool(data, atom.u.as_bool);
- count++;
- break;
- case PN_UBYTE:
- pn_data_put_ubyte(data, atom.u.as_ubyte);
- count++;
- break;
- case PN_BYTE:
- pn_data_put_byte(data, atom.u.as_byte);
- count++;
- break;
- case PN_USHORT:
- pn_data_put_ushort(data, atom.u.as_ushort);
- count++;
- break;
- case PN_SHORT:
- pn_data_put_short(data, atom.u.as_short);
- count++;
- break;
- case PN_UINT:
- pn_data_put_uint(data, atom.u.as_uint);
- count++;
- break;
- case PN_INT:
- pn_data_put_int(data, atom.u.as_int);
- count++;
- break;
- case PN_CHAR:
- pn_data_put_char(data, atom.u.as_char);
- count++;
- break;
- case PN_ULONG:
- pn_data_put_ulong(data, atom.u.as_ulong);
- count++;
- break;
- case PN_LONG:
- pn_data_put_long(data, atom.u.as_long);
- count++;
- break;
- case PN_TIMESTAMP:
- pn_data_put_timestamp(data, atom.u.as_timestamp);
- count++;
- break;
- case PN_FLOAT:
- pn_data_put_float(data, atom.u.as_float);
- count++;
- break;
- case PN_DOUBLE:
- pn_data_put_double(data, atom.u.as_double);
- count++;
- break;
- case PN_DECIMAL32:
- pn_data_put_decimal32(data, atom.u.as_decimal32);
- count++;
- break;
- case PN_DECIMAL64:
- pn_data_put_decimal64(data, atom.u.as_decimal64);
- count++;
- break;
- case PN_DECIMAL128:
- pn_data_put_decimal128(data, atom.u.as_decimal128);
- count++;
- break;
- case PN_UUID:
- pn_data_put_uuid(data, atom.u.as_uuid);
- count++;
- break;
- case PN_BINARY:
- pn_data_put_binary(data, atom.u.as_binary);
- count++;
- break;
- case PN_STRING:
- pn_data_put_string(data, atom.u.as_string);
- count++;
- break;
- case PN_SYMBOL:
- pn_data_put_symbol(data, atom.u.as_symbol);
- count++;
- break;
- case PN_LIST:
- case PN_MAP:
- switch (atom.type) {
- case PN_LIST:
- pn_data_put_list(data);
- break;
- case PN_MAP:
- pn_data_put_map(data);
- break;
- default:
- return PN_ERR;
- }
- pn_data_enter(data);
- step = pn_data_parse_atoms(data, atoms, i+1, atom.u.count);
- if (step < 0) {
- return step;
- } else {
- i += step;
- }
- pn_data_exit(data);
- count++;
- break;
- case PN_ARRAY:
- {
- bool described = (atoms.start[i+1].type == PN_DESCRIPTOR);
- pn_data_put_array(data, described, (pn_type_t) 0);
- pn_node_t *array = pn_data_current(data);
- pn_data_enter(data);
- if (described) {
- i++;
- step = pn_data_parse_atoms(data, atoms, i+1, 1);
- if (step < 0) {
- return step;
- } else {
- i += step;
- }
- }
-
- if (atoms.start[i+1].type != PN_TYPE) {
- return PN_ERR;
- }
- array->type = atoms.start[i+1].u.type;
-
- i++;
-
- step = pn_data_parse_atoms(data, atoms, i+1, atom.u.count);
- if (step < 0) {
- return step;
- } else {
- i += step;
- }
- pn_data_exit(data);
- }
- count++;
- break;
- case PN_DESCRIPTOR:
- pn_data_put_described(data);
- pn_data_enter(data);
- step = pn_data_parse_atoms(data, atoms, i+1, 2);
- if (step < 0) {
- return step;
- } else {
- i += step;
- }
- pn_data_exit(data);
- count++;
- break;
- }
- }
-
- return i - offset;
-}
-
ssize_t pn_data_decode(pn_data_t *data, const char *bytes, size_t size)
{
- size_t asize = 64;
- pn_atoms_t latoms;
- pn_bytes_t lbytes;
-
- while (true) {
- PN_ENSURE(data->iatoms, data->iatom_capacity, asize, pn_iatom_t);
- latoms.size = asize;
- latoms.start = data->iatoms;
- lbytes.size = size;
- lbytes.start = (char *)bytes; // PROTON-77
-
- int err = pn_decode_one(&lbytes, &latoms);
-
- if (!err) {
- err = pn_data_parse_atoms(data, latoms, 0, -1);
- return lbytes.size;
- } else if (err == PN_OVERFLOW) {
- asize *= 2;
- } else {
- return err;
- }
- }
+ return pn_decoder_decode(data->decoder, bytes, size, data);
}
int pn_data_put_list(pn_data_t *data)
@@ -2566,6 +1949,12 @@ int pn_data_put_array(pn_data_t *data, b
return 0;
}
+void pni_data_set_array_type(pn_data_t *data, pn_type_t type)
+{
+ pn_node_t *array = pn_data_current(data);
+ array->type = type;
+}
+
int pn_data_put_described(pn_data_t *data)
{
pn_node_t *node = pn_data_add(data);
Added: qpid/proton/trunk/proton-c/src/codec/decoder.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/codec/decoder.c?rev=1519669&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/codec/decoder.c (added)
+++ qpid/proton/trunk/proton-c/src/codec/decoder.c Tue Sep 3 12:45:45 2013
@@ -0,0 +1,493 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <proton/error.h>
+#include <proton/object.h>
+#include <proton/codec.h>
+#include "encodings.h"
+
+#include <string.h>
+
+typedef struct {
+ const char *input;
+ size_t size;
+ const char *position;
+ pn_error_t *error;
+} pn_decoder_t;
+
+static void pn_decoder_initialize(void *obj)
+{
+ pn_decoder_t *decoder = (pn_decoder_t *) obj;
+ decoder->input = NULL;
+ decoder->size = 0;
+ decoder->position = NULL;
+ decoder->error = pn_error();
+}
+
+static void pn_decoder_finalize(void *obj) {
+ pn_decoder_t *decoder = (pn_decoder_t *) obj;
+ pn_error_free(decoder->error);
+}
+
+#define pn_decoder_hashcode NULL
+#define pn_decoder_compare NULL
+#define pn_decoder_inspect NULL
+
+pn_decoder_t *pn_decoder()
+{
+ static pn_class_t clazz = PN_CLASS(pn_decoder);
+ return (pn_decoder_t *) pn_new(sizeof(pn_decoder_t), &clazz);
+}
+
+static inline uint8_t pn_decoder_readf8(pn_decoder_t *decoder)
+{
+ uint8_t r = decoder->position[0];
+ decoder->position++;
+ return r;
+}
+
+static inline uint16_t pn_decoder_readf16(pn_decoder_t *decoder)
+{
+ uint16_t a = (uint8_t) decoder->position[0];
+ uint16_t b = (uint8_t) decoder->position[1];
+ uint16_t r = a << 8
+ | b;
+ decoder->position += 2;
+ return r;
+}
+
+static inline uint32_t pn_decoder_readf32(pn_decoder_t *decoder)
+{
+ uint32_t a = (uint8_t) decoder->position[0];
+ uint32_t b = (uint8_t) decoder->position[1];
+ uint32_t c = (uint8_t) decoder->position[2];
+ uint32_t d = (uint8_t) decoder->position[3];
+ uint32_t r = a << 24
+ | b << 16
+ | c << 8
+ | d;
+ decoder->position += 4;
+ return r;
+}
+
+static inline uint64_t pn_decoder_readf64(pn_decoder_t *decoder)
+{
+ uint64_t a = pn_decoder_readf32(decoder);
+ uint64_t b = pn_decoder_readf32(decoder);
+ return a << 32 | b;
+}
+
+static inline void pn_decoder_readf128(pn_decoder_t *decoder, void *dst)
+{
+ memmove(dst, decoder->position, 16);
+ decoder->position += 16;
+}
+
+static inline size_t pn_decoder_remaining(pn_decoder_t *decoder)
+{
+ return decoder->input + decoder->size - decoder->position;
+}
+
+typedef union {
+ uint32_t i;
+ uint32_t a[2];
+ uint64_t l;
+ float f;
+ double d;
+} conv_t;
+
+static inline pn_type_t pn_code2type(uint8_t code)
+{
+ switch (code)
+ {
+ case PNE_DESCRIPTOR:
+ return (pn_type_t) PN_ARG_ERR;
+ case PNE_NULL:
+ return PN_NULL;
+ case PNE_TRUE:
+ case PNE_FALSE:
+ case PNE_BOOLEAN:
+ return PN_BOOL;
+ case PNE_UBYTE:
+ return PN_UBYTE;
+ case PNE_BYTE:
+ return PN_BYTE;
+ case PNE_USHORT:
+ return PN_USHORT;
+ case PNE_SHORT:
+ return PN_SHORT;
+ case PNE_UINT0:
+ case PNE_SMALLUINT:
+ case PNE_SMALLINT:
+ case PNE_UINT:
+ return PN_UINT;
+ case PNE_INT:
+ return PN_INT;
+ case PNE_UTF32:
+ return PN_CHAR;
+ case PNE_FLOAT:
+ return PN_FLOAT;
+ case PNE_LONG:
+ return PN_LONG;
+ case PNE_MS64:
+ return PN_TIMESTAMP;
+ case PNE_DOUBLE:
+ return PN_DOUBLE;
+ case PNE_DECIMAL32:
+ return PN_DECIMAL32;
+ case PNE_DECIMAL64:
+ return PN_DECIMAL64;
+ case PNE_DECIMAL128:
+ return PN_DECIMAL128;
+ case PNE_UUID:
+ return PN_UUID;
+ case PNE_ULONG0:
+ case PNE_SMALLULONG:
+ case PNE_SMALLLONG:
+ case PNE_ULONG:
+ return PN_ULONG;
+ case PNE_VBIN8:
+ case PNE_VBIN32:
+ return PN_BINARY;
+ case PNE_STR8_UTF8:
+ case PNE_STR32_UTF8:
+ return PN_STRING;
+ case PNE_SYM8:
+ case PNE_SYM32:
+ return PN_SYMBOL;
+ case PNE_LIST0:
+ case PNE_LIST8:
+ case PNE_LIST32:
+ return PN_LIST;
+ case PNE_ARRAY8:
+ case PNE_ARRAY32:
+ return PN_ARRAY;
+ case PNE_MAP8:
+ case PNE_MAP32:
+ return PN_MAP;
+ default:
+ return (pn_type_t) PN_ARG_ERR;
+ }
+}
+
+int pn_decoder_decode_type(pn_decoder_t *decoder, pn_data_t *data, uint8_t *code);
+int pn_decoder_single(pn_decoder_t *decoder, pn_data_t *data);
+void pni_data_set_array_type(pn_data_t *data, pn_type_t type);
+
+int pn_decoder_decode_value(pn_decoder_t *decoder, pn_data_t *data, uint8_t code)
+{
+ int err;
+ conv_t conv;
+ pn_decimal128_t dec128;
+ pn_uuid_t uuid;
+ size_t size;
+ size_t count;
+
+ switch (code)
+ {
+ case PNE_NULL:
+ err = pn_data_put_null(data);
+ break;
+ case PNE_TRUE:
+ err = pn_data_put_bool(data, true);
+ break;
+ case PNE_FALSE:
+ err = pn_data_put_bool(data, false);
+ break;
+ case PNE_BOOLEAN:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_bool(data, pn_decoder_readf8(decoder) != 0);
+ break;
+ case PNE_UBYTE:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_ubyte(data, pn_decoder_readf8(decoder));
+ break;
+ case PNE_BYTE:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_byte(data, pn_decoder_readf8(decoder));
+ break;
+ case PNE_USHORT:
+ if (pn_decoder_remaining(decoder) < 2) return PN_UNDERFLOW;
+ err = pn_data_put_ushort(data, pn_decoder_readf16(decoder));
+ break;
+ case PNE_SHORT:
+ if (pn_decoder_remaining(decoder) < 2) return PN_UNDERFLOW;
+ err = pn_data_put_short(data, pn_decoder_readf16(decoder));
+ break;
+ case PNE_UINT:
+ if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
+ err = pn_data_put_uint(data, pn_decoder_readf32(decoder));
+ break;
+ case PNE_UINT0:
+ err = pn_data_put_uint(data, 0);
+ break;
+ case PNE_SMALLUINT:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_uint(data, pn_decoder_readf8(decoder));
+ break;
+ case PNE_SMALLINT:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_int(data, pn_decoder_readf8(decoder));
+ break;
+ case PNE_INT:
+ if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
+ err = pn_data_put_int(data, pn_decoder_readf32(decoder));
+ break;
+ case PNE_UTF32:
+ if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
+ err = pn_data_put_char(data, pn_decoder_readf32(decoder));
+ break;
+ case PNE_FLOAT:
+ if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
+ // XXX: this assumes the platform uses IEEE floats
+ conv.i = pn_decoder_readf32(decoder);
+ err = pn_data_put_float(data, conv.f);
+ break;
+ case PNE_DECIMAL32:
+ if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
+ err = pn_data_put_decimal32(data, pn_decoder_readf32(decoder));
+ break;
+ case PNE_ULONG:
+ if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
+ err = pn_data_put_ulong(data, pn_decoder_readf64(decoder));
+ break;
+ case PNE_LONG:
+ if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
+ err = pn_data_put_long(data, pn_decoder_readf64(decoder));
+ break;
+ case PNE_MS64:
+ if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
+ err = pn_data_put_timestamp(data, pn_decoder_readf64(decoder));
+ break;
+ case PNE_DOUBLE:
+ // XXX: this assumes the platform uses IEEE floats
+ if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
+ conv.l = pn_decoder_readf64(decoder);
+ err = pn_data_put_double(data, conv.d);
+ break;
+ case PNE_DECIMAL64:
+ if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
+ err = pn_data_put_decimal64(data, pn_decoder_readf64(decoder));
+ break;
+ case PNE_ULONG0:
+ err = pn_data_put_ulong(data, 0);
+ break;
+ case PNE_SMALLULONG:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_ulong(data, pn_decoder_readf8(decoder));
+ break;
+ case PNE_SMALLLONG:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ err = pn_data_put_long(data, pn_decoder_readf8(decoder));
+ break;
+ case PNE_DECIMAL128:
+ if (pn_decoder_remaining(decoder) < 16) return PN_UNDERFLOW;
+ pn_decoder_readf128(decoder, &dec128);
+ err = pn_data_put_decimal128(data, dec128);
+ break;
+ case PNE_UUID:
+ if (pn_decoder_remaining(decoder) < 16) return PN_UNDERFLOW;
+ pn_decoder_readf128(decoder, &uuid);
+ err = pn_data_put_uuid(data, uuid);
+ break;
+ case PNE_VBIN8:
+ case PNE_STR8_UTF8:
+ case PNE_SYM8:
+ case PNE_VBIN32:
+ case PNE_STR32_UTF8:
+ case PNE_SYM32:
+ switch (code & 0xF0)
+ {
+ case 0xA0:
+ if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
+ size = pn_decoder_readf8(decoder);
+ break;
+ case 0xB0:
+ if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
+ size = pn_decoder_readf32(decoder);
+ break;
+ default:
+ return PN_ARG_ERR;
+ }
+
+ if (pn_decoder_remaining(decoder) < size) return PN_UNDERFLOW;
+
+ {
+ char *start = (char *) decoder->position;
+ pn_bytes_t bytes = {size, start};
+ switch (code & 0x0F)
+ {
+ case 0x0:
+ err = pn_data_put_binary(data, bytes);
+ break;
+ case 0x1:
+ err = pn_data_put_string(data, bytes);
+ break;
+ case 0x3:
+ err = pn_data_put_symbol(data, bytes);
+ break;
+ default:
+ return PN_ARG_ERR;
+ }
+ }
+
+ decoder->position += size;
+ break;
+ case PNE_LIST0:
+ err = pn_data_put_list(data);
+ break;
+ case PNE_ARRAY8:
+ case PNE_ARRAY32:
+ case PNE_LIST8:
+ case PNE_LIST32:
+ case PNE_MAP8:
+ case PNE_MAP32:
+ switch (code)
+ {
+ case PNE_ARRAY8:
+ case PNE_LIST8:
+ case PNE_MAP8:
+ if (pn_decoder_remaining(decoder) < 2) return PN_UNDERFLOW;
+ size = pn_decoder_readf8(decoder);
+ count = pn_decoder_readf8(decoder);
+ break;
+ case PNE_ARRAY32:
+ case PNE_LIST32:
+ case PNE_MAP32:
+ size = pn_decoder_readf32(decoder);
+ count = pn_decoder_readf32(decoder);
+ break;
+ default:
+ return PN_ARG_ERR;
+ }
+
+ switch (code)
+ {
+ case PNE_ARRAY8:
+ case PNE_ARRAY32:
+ {
+ uint8_t next = *decoder->position;
+ bool described = (next == PNE_DESCRIPTOR);
+ err = pn_data_put_array(data, described, (pn_type_t) 0);
+ if (err) return err;
+
+ pn_data_enter(data);
+ uint8_t acode;
+ int e = pn_decoder_decode_type(decoder, data, &acode);
+ if (e) return e;
+ pn_type_t type = pn_code2type(acode);
+ if (type < 0) return type;
+ for (size_t i = 0; i < count; i++)
+ {
+ e = pn_decoder_decode_value(decoder, data, acode);
+ if (e) return e;
+ }
+ pn_data_exit(data);
+
+ pni_data_set_array_type(data, type);
+ }
+ return 0;
+ case PNE_LIST8:
+ case PNE_LIST32:
+ err = pn_data_put_list(data);
+ if (err) return err;
+ break;
+ case PNE_MAP8:
+ case PNE_MAP32:
+ err = pn_data_put_map(data);
+ if (err) return err;
+ break;
+ default:
+ return PN_ARG_ERR;
+ }
+
+ pn_data_enter(data);
+ for (size_t i = 0; i < count; i++)
+ {
+ int e = pn_decoder_single(decoder, data);
+ if (e) return e;
+ }
+ pn_data_exit(data);
+
+ return 0;
+ default:
+ return pn_error_format(decoder->error, PN_ARG_ERR, "unrecognized typecode: %u", code);
+ }
+
+ return err;
+}
+
+pn_type_t pni_data_parent_type(pn_data_t *data);
+
+int pn_decoder_decode_type(pn_decoder_t *decoder, pn_data_t *data, uint8_t *code)
+{
+ int err;
+
+ if (!pn_decoder_remaining(decoder)) {
+ return PN_UNDERFLOW;
+ }
+
+ uint8_t next = *decoder->position++;
+
+ if (next == PNE_DESCRIPTOR) {
+ if (pni_data_parent_type(data) != PN_ARRAY) {
+ err = pn_data_put_described(data);
+ if (err) return err;
+ // pn_decoder_single has the corresponding exit
+ pn_data_enter(data);
+ }
+ err = pn_decoder_single(decoder, data);
+ if (err) return err;
+ err = pn_decoder_decode_type(decoder, data, code);
+ if (err) return err;
+ } else {
+ *code = next;
+ }
+
+ return 0;
+}
+
+size_t pn_data_siblings(pn_data_t *data);
+
+int pn_decoder_single(pn_decoder_t *decoder, pn_data_t *data)
+{
+ uint8_t code;
+ int err = pn_decoder_decode_type(decoder, data, &code);
+ if (err) return err;
+ err = pn_decoder_decode_value(decoder, data, code);
+ if (err) return err;
+ if (pni_data_parent_type(data) == PN_DESCRIBED && pn_data_siblings(data) > 1) {
+ pn_data_exit(data);
+ }
+ return 0;
+}
+
+ssize_t pn_decoder_decode(pn_decoder_t *decoder, const char *src, size_t size, pn_data_t *dst)
+{
+ decoder->input = src;
+ decoder->size = size;
+ decoder->position = src;
+
+ int err = pn_decoder_single(decoder, dst);
+ if (err) return err;
+
+ return decoder->position - decoder->input;
+}
Added: qpid/proton/trunk/proton-c/src/codec/decoder.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/codec/decoder.h?rev=1519669&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/codec/decoder.h (added)
+++ qpid/proton/trunk/proton-c/src/codec/decoder.h Tue Sep 3 12:45:45 2013
@@ -0,0 +1,30 @@
+#ifndef _PROTON_DECODER_H
+#define _PROTON_DECODER_H 1
+
+/*
+ *
+ * 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.
+ *
+ */
+
+typedef struct pn_decoder_t pn_decoder_t;
+
+pn_decoder_t *pn_decoder();
+ssize_t pn_decoder_decode(pn_decoder_t *decoder, const char *src, size_t size, pn_data_t *dst);
+
+#endif /* decoder.h */
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org