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 2012/09/24 19:13:29 UTC

svn commit: r1389489 - in /qpid/proton/trunk: proton-c/bindings/python/ proton-c/include/proton/ proton-c/src/ proton-c/src/codec/ proton-c/src/dispatcher/ proton-c/src/message/ tests/proton_tests/

Author: rhs
Date: Mon Sep 24 17:13:28 2012
New Revision: 1389489

URL: http://svn.apache.org/viewvc?rev=1389489&view=rev
Log:
improved codec interface and capabilities

Added:
    qpid/proton/trunk/tests/proton_tests/codec.py
Modified:
    qpid/proton/trunk/proton-c/bindings/python/proton.py
    qpid/proton/trunk/proton-c/bindings/python/python.i
    qpid/proton/trunk/proton-c/include/proton/buffer.h
    qpid/proton/trunk/proton-c/include/proton/codec.h
    qpid/proton/trunk/proton-c/include/proton/cproton.i
    qpid/proton/trunk/proton-c/include/proton/parser.h
    qpid/proton/trunk/proton-c/src/buffer.c
    qpid/proton/trunk/proton-c/src/codec/codec.c
    qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c
    qpid/proton/trunk/proton-c/src/message/message.c
    qpid/proton/trunk/proton-c/src/parser.c
    qpid/proton/trunk/proton-c/src/proton-dump.c
    qpid/proton/trunk/proton-c/src/proton.c
    qpid/proton/trunk/proton-c/src/util.c
    qpid/proton/trunk/tests/proton_tests/__init__.py
    qpid/proton/trunk/tests/proton_tests/engine.py
    qpid/proton/trunk/tests/proton_tests/message.py
    qpid/proton/trunk/tests/proton_tests/messenger.py

Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
+++ qpid/proton/trunk/proton-c/bindings/python/proton.py Mon Sep 24 17:13:28 2012
@@ -19,7 +19,7 @@ EXCEPTIONS = {
 class Messenger(object):
 
   def __init__(self, name=None):
-    self._mng = pn_messenger(name);
+    self._mng = pn_messenger(name)
 
   def __del__(self):
     if hasattr(self, "_mng"):
@@ -268,5 +268,233 @@ class Message(object):
         self._check(err)
         return data
 
+class DataException(ProtonException):
+  pass
+
+class Data:
+
+  NULL = PN_NULL
+  BOOL = PN_BOOL
+  UBYTE = PN_UBYTE
+  BYTE = PN_BYTE
+  USHORT = PN_USHORT
+  SHORT = PN_SHORT
+  UINT = PN_UINT
+  INT = PN_INT
+  ULONG = PN_ULONG
+  LONG = PN_LONG
+  FLOAT = PN_FLOAT
+  DOUBLE = PN_DOUBLE
+  BINARY = PN_BINARY
+  STRING = PN_STRING
+  SYMBOL = PN_SYMBOL
+  DESCRIBED = PN_DESCRIPTOR
+  ARRAY = PN_ARRAY
+  LIST = PN_LIST
+  MAP = PN_MAP
+
+  def __init__(self, capacity=16):
+    self._data = pn_data(capacity)
+
+  def __del__(self):
+    if hasattr(self, "_data"):
+      pn_data_free(self._data)
+      del self._data
+
+  def _check(self, err):
+    if err < 0:
+      exc = EXCEPTIONS.get(err, DataException)
+      raise exc("[%s]: %s" % (err, "xxx"))
+    else:
+      return err
+
+  def rewind(self):
+    pn_data_rewind(self._data)
+
+  def next(self):
+    found, dtype = pn_data_next(self._data)
+    if found:
+      return dtype
+    else:
+      return None
+
+  def prev(self):
+    found, dtype = pn_data_prev(self._data)
+    if found:
+      return dtype
+    else:
+      return None
+
+  def enter(self):
+    return pn_data_enter(self._data)
+
+  def exit(self):
+    return pn_data_exit(self._data)
+
+  def encode(self):
+    size = 1024
+    while True:
+      cd, enc = pn_data_encode(self._data, size)
+      if cd == PN_OVERFLOW:
+        size *= 2
+      elif cd >= 0:
+        return enc
+      else:
+        self._check(cd)
+
+  def decode(self, encoded):
+    return self._check(pn_data_decode(self._data, encoded))
+
+  def put_list(self):
+    self._check(pn_data_put_list(self._data))
+
+  def put_map(self):
+    self._check(pn_data_put_map(self._data))
+
+  def put_array(self, described, etype):
+    self._check(pn_data_put_array(self._data, described, etype))
+
+  def put_described(self):
+    self._check(pn_data_put_described(self._data))
+
+  def put_null(self):
+    self._check(pn_data_put_null(self._data))
+
+  def put_bool(self, b):
+    self._check(pn_data_put_bool(self._data, b))
+
+  def put_ubyte(self, ub):
+    self._check(pn_data_put_ubyte(self._data, ub))
+
+  def put_byte(self, b):
+    self._check(pn_data_put_byte(self._data, b))
+
+  def put_ushort(self, us):
+    self._check(pn_data_put_ushort(self._data, us))
+
+  def put_short(self, s):
+    self._check(pn_data_put_short(self._data, s))
+
+  def put_uint(self, ui):
+    self._check(pn_data_put_uint(self._data, ui))
+
+  def put_int(self, i):
+    self._check(pn_data_put_int(self._data, i))
+
+  def put_ulong(self, ul):
+    self._check(pn_data_put_ulong(self._data, ul))
+
+  def put_long(self, l):
+    self._check(pn_data_put_long(self._data, l))
+
+  def put_float(self, f):
+    self._check(pn_data_put_float(self._data, f))
+
+  def put_double(self, d):
+    self._check(pn_data_put_double(self._data, d))
+
+  def put_binary(self, b):
+    self._check(pn_data_put_binary(self._data, b))
+
+  def put_string(self, s):
+    self._check(pn_data_put_string(self._data, s))
+
+  def put_symbol(self, s):
+    self._check(pn_data_put_symbol(self._data, s))
+
+  def get_list(self):
+    err, count = pn_data_get_list(self._data)
+    self._check(err)
+    return count
+
+  def get_map(self):
+    err, count = pn_data_get_map(self._data)
+    self._check(err)
+    return count
+
+  def get_array(self):
+    err, count, described, type = pn_data_get_array(self._data)
+    self._check(err)
+    return count, described, type
+
+  def get_described(self):
+    self._check(pn_data_get_described(self._data))
+
+  def get_null(self):
+    self._check(pn_data_get_null(self._data))
+
+  def get_bool(self):
+    err, b = pn_data_get_bool(self._data)
+    self._check(err)
+    return b
+
+  def get_ubyte(self):
+    err, value = pn_data_get_ubyte(self._data)
+    self._check(err)
+    return value
+
+  def get_byte(self):
+    err, value = pn_data_get_byte(self._data)
+    self._check(err)
+    return value
+
+  def get_ushort(self):
+    err, value = pn_data_get_ushort(self._data)
+    self._check(err)
+    return value
+
+  def get_short(self):
+    err, value = pn_data_get_short(self._data)
+    self._check(err)
+    return value
+
+  def get_uint(self):
+    err, value = pn_data_get_uint(self._data)
+    self._check(err)
+    return value
+
+  def get_int(self):
+    err, value = pn_data_get_int(self._data)
+    self._check(err)
+    return value
+
+  def get_ulong(self):
+    err, value = pn_data_get_ulong(self._data)
+    self._check(err)
+    return value
+
+  def get_long(self):
+    err, value = pn_data_get_long(self._data)
+    self._check(err)
+    return value
+
+  def get_float(self):
+    err, value = pn_data_get_float(self._data)
+    self._check(err)
+    return value
+
+  def get_double(self):
+    err, value = pn_data_get_double(self._data)
+    self._check(err)
+    return value
+
+  def get_binary(self):
+    err, value = pn_data_get_binary(self._data)
+    self._check(err)
+    return value
+
+  def get_string(self):
+    err, value = pn_data_get_string(self._data)
+    self._check(err)
+    return value
+
+  def get_symbol(self):
+    err, value = pn_data_get_symbol(self._data)
+    self._check(err)
+    return value
+
+  def dump(self):
+    pn_data_dump(self._data)
+
 __all__ = ["Messenger", "Message", "ProtonException", "MessengerException",
-           "MessageException", "Timeout"]
+           "MessageException", "Timeout", "Data"]

Modified: qpid/proton/trunk/proton-c/bindings/python/python.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/python.i?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/python.i (original)
+++ qpid/proton/trunk/proton-c/bindings/python/python.i Mon Sep 24 17:13:28 2012
@@ -38,6 +38,14 @@ typedef int int32_t;
   $result = PyString_FromStringAndSize($1.start, $1.size);
 }
 
+%typemap(in, numinputs=0) pn_bytes_t * (pn_bytes_t temp) {
+  $1 = &temp;
+}
+
+%typemap(argout) pn_bytes_t * {
+  $result = Py_BuildValue("NN", $result, PyString_FromStringAndSize(temp$argnum.start, temp$argnum.size));
+}
+
 int pn_message_load(pn_message_t *msg, char *STRING, size_t LENGTH);
 %ignore pn_message_load;
 
@@ -214,4 +222,22 @@ ssize_t pn_input(pn_transport_t *transpo
 %}
 %ignore pn_connector_free;
 
+ssize_t pn_data_decode(pn_data_t *data, char *STRING, size_t LENGTH);
+%ignore pn_data_decode;
+
+%rename(pn_data_encode) wrap_pn_data_encode;
+%inline %{
+  int wrap_pn_data_encode(pn_data_t *data, char *OUTPUT, size_t *OUTPUT_SIZE) {
+    ssize_t sz = pn_data_encode(data, OUTPUT, *OUTPUT_SIZE);
+    if (sz >= 0) {
+      *OUTPUT_SIZE = sz;
+    } else {
+      *OUTPUT_SIZE = 0;
+    }
+    return sz;
+  }
+%}
+%ignore pn_data_encode;
+
+
 %include "proton/cproton.i"

Modified: qpid/proton/trunk/proton-c/include/proton/buffer.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/buffer.h?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/buffer.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/buffer.h Mon Sep 24 17:13:28 2012
@@ -33,11 +33,12 @@ typedef struct pn_buffer_t pn_buffer_t;
 pn_buffer_t *pn_buffer(size_t capacity);
 void pn_buffer_free(pn_buffer_t *buf);
 size_t pn_buffer_size(pn_buffer_t *buf);
+size_t pn_buffer_capacity(pn_buffer_t *buf);
 int pn_buffer_append(pn_buffer_t *buf, const char *bytes, size_t size);
 int pn_buffer_prepend(pn_buffer_t *buf, const char *bytes, size_t size);
 size_t pn_buffer_get(pn_buffer_t *buf, size_t offset, size_t size, char *dst);
 int pn_buffer_trim(pn_buffer_t *buf, size_t left, size_t right);
-int pn_buffer_clear(pn_buffer_t *buf);
+void pn_buffer_clear(pn_buffer_t *buf);
 int pn_buffer_defrag(pn_buffer_t *buf);
 pn_bytes_t pn_buffer_bytes(pn_buffer_t *buf);
 int pn_buffer_print(pn_buffer_t *buf);

Modified: qpid/proton/trunk/proton-c/include/proton/codec.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/codec.h?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/codec.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/codec.h Mon Sep 24 17:13:28 2012
@@ -77,50 +77,73 @@ typedef struct {
   } u;
 } pn_atom_t;
 
-typedef struct {
-  size_t size;
-  pn_atom_t *start;
-} pn_atoms_t;
-
-// XXX: incremental decode and scan/fill both ways could be used for things like accessing lists/arrays
-int pn_decode_atoms(pn_bytes_t *bytes, pn_atoms_t *atoms);
-int pn_encode_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_atom_t atom);
-const char *pn_type_str(pn_type_t type);
-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_atom_t atom);
-
-int pn_fill_atoms(pn_atoms_t *atoms, const char *fmt, ...);
-int pn_vfill_atoms(pn_atoms_t *atoms, const char *fmt, va_list ap);
-int pn_ifill_atoms(pn_atoms_t *atoms, const char *fmt, ...);
-int pn_vifill_atoms(pn_atoms_t *atoms, const char *fmt, va_list ap);
-int pn_scan_atoms(const pn_atoms_t *atoms, const char *fmt, ...);
-int pn_vscan_atoms(const pn_atoms_t *atoms, const char *fmt, va_list ap);
-
 // data
 
 typedef struct pn_data_t pn_data_t;
 
 pn_data_t *pn_data(size_t capacity);
-size_t pn_data_size(pn_data_t *data);
 void pn_data_free(pn_data_t *data);
-int pn_data_clear(pn_data_t *data);
-int pn_data_grow(pn_data_t *data);
-int pn_data_decode(pn_data_t *data, char *bytes, size_t *size);
-int pn_data_encode(pn_data_t *data, char *bytes, size_t *size);
-int pn_data_intern(pn_data_t *data);
+int pn_data_errno(pn_data_t *data);
+const char *pn_data_error(pn_data_t *data);
 int pn_data_vfill(pn_data_t *data, const char *fmt, va_list ap);
 int pn_data_fill(pn_data_t *data, const char *fmt, ...);
 int pn_data_vscan(pn_data_t *data, const char *fmt, va_list ap);
 int pn_data_scan(pn_data_t *data, const char *fmt, ...);
+
+int pn_data_clear(pn_data_t *data);
+size_t pn_data_size(pn_data_t *data);
+void pn_data_rewind(pn_data_t *data);
+bool pn_data_next(pn_data_t *data, pn_type_t *type);
+bool pn_data_prev(pn_data_t *data, pn_type_t *type);
+bool pn_data_enter(pn_data_t *data);
+bool pn_data_exit(pn_data_t *data);
+
 int pn_data_print(pn_data_t *data);
-pn_atoms_t pn_data_atoms(pn_data_t *data);
-pn_atoms_t pn_data_available(pn_data_t *data);
 int pn_data_format(pn_data_t *data, char *bytes, size_t *size);
-int pn_data_resize(pn_data_t *data, size_t size);
+ssize_t pn_data_encode(pn_data_t *data, char *bytes, size_t size);
+ssize_t pn_data_decode(pn_data_t *data, char *bytes, size_t size);
+
+int pn_data_put_list(pn_data_t *data);
+int pn_data_put_map(pn_data_t *data);
+int pn_data_put_array(pn_data_t *data, bool described, pn_type_t type);
+int pn_data_put_described(pn_data_t *data);
+int pn_data_put_null(pn_data_t *data);
+int pn_data_put_bool(pn_data_t *data, bool b);
+int pn_data_put_ubyte(pn_data_t *data, uint8_t ub);
+int pn_data_put_byte(pn_data_t *data, int8_t b);
+int pn_data_put_ushort(pn_data_t *data, uint16_t us);
+int pn_data_put_short(pn_data_t *data, int16_t s);
+int pn_data_put_uint(pn_data_t *data, uint32_t ui);
+int pn_data_put_int(pn_data_t *data, int32_t i);
+int pn_data_put_ulong(pn_data_t *data, uint64_t ul);
+int pn_data_put_long(pn_data_t *data, int64_t l);
+int pn_data_put_float(pn_data_t *data, float f);
+int pn_data_put_double(pn_data_t *data, double d);
+int pn_data_put_binary(pn_data_t *data, pn_bytes_t bytes);
+int pn_data_put_string(pn_data_t *data, pn_bytes_t string);
+int pn_data_put_symbol(pn_data_t *data, pn_bytes_t symbol);
+
+int pn_data_get_list(pn_data_t *data, size_t *count);
+int pn_data_get_map(pn_data_t *data, size_t *count);
+int pn_data_get_array(pn_data_t *data, size_t *count, bool *described, pn_type_t *type);
+int pn_data_get_described(pn_data_t *data);
+int pn_data_get_null(pn_data_t *data);
+int pn_data_get_bool(pn_data_t *data, bool *b);
+int pn_data_get_ubyte(pn_data_t *data, uint8_t *ub);
+int pn_data_get_byte(pn_data_t *data, int8_t *b);
+int pn_data_get_ushort(pn_data_t *data, uint16_t *us);
+int pn_data_get_short(pn_data_t *data, int16_t *s);
+int pn_data_get_uint(pn_data_t *data, uint32_t *ui);
+int pn_data_get_int(pn_data_t *data, int32_t *i);
+int pn_data_get_ulong(pn_data_t *data, uint64_t *ul);
+int pn_data_get_long(pn_data_t *data, int64_t *l);
+int pn_data_get_float(pn_data_t *data, float *f);
+int pn_data_get_double(pn_data_t *data, double *d);
+int pn_data_get_binary(pn_data_t *data, pn_bytes_t *bytes);
+int pn_data_get_string(pn_data_t *data, pn_bytes_t *string);
+int pn_data_get_symbol(pn_data_t *data, pn_bytes_t *symbol);
+
+void pn_data_dump(pn_data_t *data);
 
 #ifdef __cplusplus
 }

Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
+++ qpid/proton/trunk/proton-c/include/proton/cproton.i Mon Sep 24 17:13:28 2012
@@ -1282,7 +1282,40 @@
 
 %include "proton/messenger.h"
 
+%include "proton/ssl.h"
 
+%ignore pn_decode_atoms;
+%ignore pn_encode_atoms;
+%ignore pn_decode_one;
 
-%include "proton/ssl.h"
+%ignore pn_print_atom;
+%ignore pn_type_str;
+%ignore pn_print_atoms;
+%ignore pn_format_atoms;
+%ignore pn_format_atom;
+
+%ignore pn_fill_atoms;
+%ignore pn_vfill_atoms;
+%ignore pn_ifill_atoms;
+%ignore pn_vifill_atoms;
+%ignore pn_scan_atoms;
+%ignore pn_vscan_atoms;
+%ignore pn_data_vfill;
+%ignore pn_data_vscan;
+
+%include <typemaps.i>
+%apply int *OUTPUT {pn_type_t *type};
+%apply bool *OUTPUT {bool *};
+%apply unsigned char *OUTPUT {uint8_t *};
+%apply signed char *OUTPUT {int8_t *};
+%apply unsigned short *OUTPUT {uint16_t *};
+%apply short *OUTPUT {int16_t *};
+%apply unsigned int *OUTPUT {uint32_t *};
+%apply int *OUTPUT {int32_t *};
+%apply uint64_t *OUTPUT {uint64_t *};
+%apply long *OUTPUT {int64_t *};
+%apply float *OUTPUT {float *};
+%apply double *OUTPUT {double *};
+%apply size_t *OUTPUT {size_t *count};
 
+%include "proton/codec.h"

Modified: qpid/proton/trunk/proton-c/include/proton/parser.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/parser.h?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/parser.h (original)
+++ qpid/proton/trunk/proton-c/include/proton/parser.h Mon Sep 24 17:13:28 2012
@@ -31,7 +31,7 @@ extern "C" {
 typedef struct pn_parser_t pn_parser_t;
 
 pn_parser_t *pn_parser(void);
-int pn_parser_parse(pn_parser_t *parser, const char *str, pn_atoms_t *atoms);
+int pn_parser_parse(pn_parser_t *parser, const char *str, pn_data_t *data);
 int pn_parser_errno(pn_parser_t *parser);
 const char *pn_parser_error(pn_parser_t *parser);
 void pn_parser_free(pn_parser_t *parser);

Modified: qpid/proton/trunk/proton-c/src/buffer.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/buffer.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/buffer.c (original)
+++ qpid/proton/trunk/proton-c/src/buffer.c Mon Sep 24 17:13:28 2012
@@ -57,6 +57,11 @@ size_t pn_buffer_size(pn_buffer_t *buf)
   return buf->size;
 }
 
+size_t pn_buffer_capacity(pn_buffer_t *buf)
+{
+  return buf->capacity;
+}
+
 size_t pn_buffer_available(pn_buffer_t *buf)
 {
   return buf->capacity - buf->size;
@@ -221,11 +226,10 @@ int pn_buffer_trim(pn_buffer_t *buf, siz
   return 0;
 }
 
-int pn_buffer_clear(pn_buffer_t *buf)
+void pn_buffer_clear(pn_buffer_t *buf)
 {
   buf->start = 0;
   buf->size = 0;
-  return 0;
 }
 
 static void pn_buffer_rotate (pn_buffer_t *buf, size_t sz) {

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=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/codec/codec.c (original)
+++ qpid/proton/trunk/proton-c/src/codec/codec.c Mon Sep 24 17:13:28 2012
@@ -35,6 +35,28 @@
 #include "encodings.h"
 #include "../util.h"
 
+typedef struct {
+  size_t size;
+  pn_atom_t *start;
+} pn_atoms_t;
+
+int pn_decode_atoms(pn_bytes_t *bytes, pn_atoms_t *atoms);
+int pn_encode_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_atom_t atom);
+const char *pn_type_str(pn_type_t type);
+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_atom_t atom);
+
+int pn_fill_atoms(pn_atoms_t *atoms, const char *fmt, ...);
+int pn_vfill_atoms(pn_atoms_t *atoms, const char *fmt, va_list ap);
+int pn_ifill_atoms(pn_atoms_t *atoms, const char *fmt, ...);
+int pn_vifill_atoms(pn_atoms_t *atoms, const char *fmt, va_list ap);
+int pn_scan_atoms(const pn_atoms_t *atoms, const char *fmt, ...);
+int pn_vscan_atoms(const pn_atoms_t *atoms, const char *fmt, va_list ap);
+
 typedef union {
   uint32_t i;
   uint32_t a[2];
@@ -390,7 +412,7 @@ uint8_t pn_type2code(pn_type_t type)
   case PN_ARRAY: return PNE_ARRAY32;
   case PN_MAP: return PNE_MAP32;
   default:
-    pn_fatal("not a value type: %u", type);
+    pn_fatal("not a value type: %u\n", type);
     return 0;
   }
 }
@@ -509,7 +531,7 @@ int pn_encode_value(pn_bytes_t *bytes, p
   case PN_ULONG: return pn_bytes_writef64(bytes, atom->u.as_ulong);
   case PN_LONG: return pn_bytes_writef64(bytes, atom->u.as_long);
   case PN_FLOAT: c.f = atom->u.as_float; return pn_bytes_writef32(bytes, c.i);
-  case PN_DOUBLE: c.d = atom->u.as_double; return pn_bytes_writef32(bytes, c.l);
+  case PN_DOUBLE: c.d = atom->u.as_double; return pn_bytes_writef64(bytes, c.l);
   case PN_BINARY: return pn_bytes_writev32(bytes, &atom->u.as_binary);
   case PN_STRING: return pn_bytes_writev32(bytes, &atom->u.as_string);
   case PN_SYMBOL: return pn_bytes_writev32(bytes, &atom->u.as_symbol);
@@ -1628,35 +1650,66 @@ int pn_vscan_atoms(const pn_atoms_t *ato
 
 // data
 
+typedef struct {
+  size_t next;
+  size_t prev;
+  size_t down;
+  size_t parent;
+  size_t children;
+  pn_atom_t atom;
+  // for arrays
+  bool described;
+  pn_type_t type;
+  bool data;
+  size_t data_offset;
+  size_t data_size;
+} pn_node_t;
+
 struct pn_data_t {
   size_t capacity;
   size_t size;
-  pn_atom_t *atoms;
-  bool deep;
+  pn_node_t *nodes;
   pn_buffer_t *buf;
+  size_t parent;
+  size_t current;
+  size_t extras;
+  pn_error_t *error;
 };
 
-
 pn_data_t *pn_data(size_t capacity)
 {
   pn_data_t *data = malloc(sizeof(pn_data_t));
   data->capacity = capacity;
   data->size = 0;
-  data->atoms = capacity ? malloc(capacity * sizeof(pn_atom_t)) : NULL;
-  data->deep = false;
-  data->buf = NULL;
+  data->nodes = capacity ? malloc(capacity * sizeof(pn_node_t)) : NULL;
+  data->buf = pn_buffer(64);
+  data->parent = 0;
+  data->current = 0;
+  data->extras = 0;
+  data->error = pn_error();
   return data;
 }
 
 void pn_data_free(pn_data_t *data)
 {
   if (data) {
+    free(data->nodes);
     pn_buffer_free(data->buf);
-    free(data->atoms);
+    pn_error_free(data->error);
     free(data);
   }
 }
 
+int pn_data_errno(pn_data_t *data)
+{
+  return pn_error_code(data->error);
+}
+
+const char *pn_data_error(pn_data_t *data)
+{
+  return pn_error_text(data->error);
+}
+
 size_t pn_data_size(pn_data_t *data)
 {
   return data ? data->size : 0;
@@ -1666,10 +1719,10 @@ int pn_data_clear(pn_data_t *data)
 {
   if (data) {
     data->size = 0;
-    if (data->buf) {
-      int e = pn_buffer_clear(data->buf);
-      if (e) return e;
-    }
+    data->extras = 0;
+    data->parent = 0;
+    data->current = 0;
+    pn_buffer_clear(data->buf);
   }
   return 0;
 }
@@ -1677,109 +1730,237 @@ int pn_data_clear(pn_data_t *data)
 int pn_data_grow(pn_data_t *data)
 {
   data->capacity = 2*(data->capacity ? data->capacity : 16);
-  data->atoms = realloc(data->atoms, data->capacity * sizeof(pn_atom_t));
+  data->nodes = realloc(data->nodes, data->capacity * sizeof(pn_node_t));
   return 0;
 }
 
-int pn_data_decode(pn_data_t *data, char *bytes, size_t *size)
+ssize_t pn_data_intern(pn_data_t *data, char *start, size_t size)
 {
-  pn_atoms_t atoms;
-  pn_bytes_t lbytes;
-
-  while (true) {
-    atoms.size = data->capacity;
-    atoms.start = data->atoms;
-    lbytes.size = *size;
-    lbytes.start = bytes;
+  size_t offset = pn_buffer_size(data->buf);
+  int err = pn_buffer_append(data->buf, start, size);
+  if (err) return err;
+  else return offset;
+}
 
-    int err = pn_decode_one(&lbytes, &atoms);
+pn_bytes_t *pn_data_bytes(pn_data_t *data, pn_node_t *node)
+{
+  switch (node->atom.type) {
+  case PN_BINARY: return &node->atom.u.as_binary;
+  case PN_STRING: return &node->atom.u.as_string;
+  case PN_SYMBOL: return &node->atom.u.as_symbol;
+  default: return NULL;
+  }
+}
 
-    if (!err) {
-      data->size = atoms.size;
-      *size = lbytes.size;
-      return 0;
-    } else if (err == PN_OVERFLOW) {
-      err = pn_data_grow(data);
-      if (err) return err;
-      atoms.size = data->capacity;
-    } else {
-      return err;
+void pn_data_rebase(pn_data_t *data, char *base)
+{
+  for (int i = 0; i < data->size; i++) {
+    pn_node_t *node = &data->nodes[i];
+    if (node->data) {
+      pn_bytes_t *bytes = pn_data_bytes(data, node);
+      bytes->start = base + node->data_offset;
     }
   }
 }
 
-int pn_data_encode(pn_data_t *data, char *bytes, size_t *size)
+int pn_data_intern_node(pn_data_t *data, pn_node_t *node)
 {
-  pn_atoms_t atoms = {.size=data->size, .start=data->atoms};
-  pn_bytes_t lbytes = pn_bytes(*size, bytes);
+  pn_bytes_t *bytes = pn_data_bytes(data, node);
+  size_t oldcap = pn_buffer_capacity(data->buf);
+  ssize_t offset = pn_data_intern(data, bytes->start, bytes->size);
+  if (offset < 0) return offset;
+  node->data = true;
+  node->data_offset = offset;
+  node->data_size = bytes->size;
+  pn_bytes_t buf = pn_buffer_bytes(data->buf);
+  bytes->start = buf.start + offset;
 
-  int err = pn_encode_atoms(&lbytes, &atoms);
-  if (err) return err;
+  if (pn_buffer_capacity(data->buf) != oldcap) {
+    pn_data_rebase(data, buf.start);
+  }
 
-  *size = lbytes.size;
   return 0;
 }
 
-int pn_data_intern_bytes(pn_data_t *data, pn_bytes_t *bytes)
-{
-  pn_bytes_t prev = pn_buffer_bytes(data->buf);
-  int err = pn_buffer_append(data->buf, bytes->start, bytes->size);
-  if (err) return err;
-  bytes->start = prev.start + prev.size;
-  return 0;
-}
+pn_node_t *pn_data_node(pn_data_t *data, size_t nd);
 
-int pn_data_intern(pn_data_t *data)
+int pn_data_vfill(pn_data_t *data, const char *fmt, va_list ap)
 {
-  if (!data) return PN_ARG_ERR;
-  if (!data->buf) {
-    data->buf = pn_buffer(64);
-  }
-
-  for (int i = 0; i < data->size; i++) {
-    pn_atom_t *atom = data->atoms + i;
-    pn_bytes_t *bytes;
-    switch (atom->type) {
-    case PN_BINARY:
-      bytes = &atom->u.as_binary;
+  int err;
+  while (*fmt) {
+    char code = *(fmt++);
+    if (!code) return 0;
+
+    switch (code) {
+    case 'n':
+      err = pn_data_put_null(data);
       break;
-    case PN_STRING:
-      bytes = &atom->u.as_string;
+    case 'o':
+      err = pn_data_put_bool(data, va_arg(ap, int));
       break;
-    case PN_SYMBOL:
-      bytes = &atom->u.as_symbol;
+    case 'B':
+      err = pn_data_put_ubyte(data, va_arg(ap, unsigned int));
+      break;
+    case 'b':
+      err = pn_data_put_byte(data, va_arg(ap, int));
+      break;
+    case 'H':
+      err = pn_data_put_ushort(data, va_arg(ap, unsigned int));
+      break;
+    case 'h':
+      err = pn_data_put_short(data, va_arg(ap, int));
+      break;
+    case 'I':
+      err = pn_data_put_uint(data, va_arg(ap, uint32_t));
+      break;
+    case 'i':
+      err = pn_data_put_int(data, va_arg(ap, uint32_t));
+      break;
+    case 'L':
+      err = pn_data_put_ulong(data, va_arg(ap, uint64_t));
+      break;
+    case 'l':
+      err = pn_data_put_long(data, va_arg(ap, int64_t));
+      break;
+    case 'f':
+      err = pn_data_put_float(data, va_arg(ap, double));
+      break;
+    case 'd':
+      err = pn_data_put_double(data, va_arg(ap, double));
+      break;
+    case 'z':
+      {
+        size_t size = va_arg(ap, size_t);
+        char *start = va_arg(ap, char *);
+        if (start) {
+          err = pn_data_put_binary(data, pn_bytes(size, start));
+        } else {
+          err = pn_data_put_null(data);
+        }
+      }
+      break;
+    case 'S':
+    case 's':
+      {
+        char *start = va_arg(ap, char *);
+        size_t size;
+        if (start) {
+          size = strlen(start);
+          if (code == 'S') {
+            err = pn_data_put_string(data, pn_bytes(size, start));
+          } else {
+            err = pn_data_put_symbol(data, pn_bytes(size, start));
+          }
+        } else {
+          err = pn_data_put_null(data);
+        }
+      }
+      break;
+    case 'D':
+      err = pn_data_put_described(data);
+      pn_data_enter(data);
+      break;
+    case 'T':
+      {
+        pn_node_t *parent = pn_data_node(data, data->parent);
+        if (parent->atom.type == PN_ARRAY) {
+          parent->type = va_arg(ap, int);
+        } else {
+          return pn_error_format(data->error, PN_ERR, "naked type");
+        }
+      }
+      break;
+    case '@':
+      {
+        bool described;
+        if (*(fmt + 1) == 'D') {
+          fmt++;
+          described = true;
+        } else {
+          described = false;
+        }
+        err = pn_data_put_array(data, described, 0);
+        pn_data_enter(data);
+      }
+      break;
+    case '[':
+      if (*(fmt - 2) != 'T') {
+        err = pn_data_put_list(data);
+        if (err) return err;
+        pn_data_enter(data);
+      }
+      break;
+    case '{':
+      err = pn_data_put_map(data);
+      if (err) return err;
+      pn_data_enter(data);
+      break;
+    case '}':
+    case ']':
+      if (!pn_data_exit(data))
+        return pn_error_format(data->error, PN_ERR, "exit failed");
+      break;
+    case '?':
+      if (!va_arg(ap, int)) {
+        err = pn_data_put_null(data);
+        if (err) return err;
+        pn_data_enter(data);
+      }
+      break;
+    case '*':
+      {
+        int count = va_arg(ap, int);
+        void *ptr = va_arg(ap, void *);
+
+        char c = *(fmt++);
+
+        switch (c)
+        {
+        case 's':
+          {
+            char **sptr = ptr;
+            for (int i = 0; i < count; i++)
+            {
+              char *sym = *(sptr++);
+              err = pn_data_fill(data, "s", sym);
+              if (err) return err;
+            }
+          }
+          break;
+        default:
+          fprintf(stderr, "unrecognized * code: 0x%.2X '%c'\n", code, code);
+          return PN_ARG_ERR;
+        }
+      }
       break;
     default:
-      continue;
+      fprintf(stderr, "unrecognized fill code: 0x%.2X '%c'\n", code, code);
+      return PN_ARG_ERR;
     }
-    int err = pn_data_intern_bytes(data, bytes);
+
     if (err) return err;
+
+    pn_node_t *parent = pn_data_node(data, data->parent);
+    while (parent) {
+      if (parent->atom.type == PN_DESCRIPTOR && parent->children == 2) {
+        pn_data_exit(data);
+        parent = pn_data_node(data, data->parent);
+      } else if (parent->atom.type == PN_NULL && parent->children == 1) {
+        pn_data_exit(data);
+        pn_node_t *current = pn_data_node(data, data->current);
+        current->down = 0;
+        current->children = 0;
+        if (err) return err;
+        parent = pn_data_node(data, data->parent);
+      } else {
+        break;
+      }
+    }
   }
 
   return 0;
 }
 
-int pn_data_vfill(pn_data_t *data, const char *fmt, va_list ap)
-{
-  pn_atoms_t atoms;
-
-  while (true) {
-    va_list cp;
-    va_copy(cp, ap);
-    atoms.size=data->capacity - data->size;
-    atoms.start=data->atoms + data->size;
-    int err = pn_vfill_atoms(&atoms, fmt, cp);
-    if (!err) {
-      data->size += atoms.size;
-      return 0;
-    } else if (err == PN_OVERFLOW) {
-      err = pn_data_grow(data);
-      if (err) return err;
-    } else {
-      return err;
-    }
-  }
-}
 
 int pn_data_fill(pn_data_t *data, const char *fmt, ...)
 {
@@ -1792,8 +1973,316 @@ int pn_data_fill(pn_data_t *data, const 
 
 int pn_data_vscan(pn_data_t *data, const char *fmt, va_list ap)
 {
-  pn_atoms_t atoms = {.size=data->size, .start=data->atoms};
-  return pn_vscan_atoms(&atoms, fmt, ap);
+  pn_data_rewind(data);
+  bool *scanarg = NULL;
+  bool at = false;
+  int level = 0;
+  int count_level = -1;
+  int resume_count = 0;
+
+  while (*fmt) {
+    char code = *(fmt++);
+
+    bool found;
+    pn_type_t type;
+
+    bool scanned;
+    bool suspend = resume_count > 0;
+
+    switch (code) {
+    case 'n':
+      found = suspend ? false : pn_data_next(data, &type);
+      if (found && type == PN_NULL) {
+        scanned = true;
+      } else {
+        scanned = false;
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'o':
+      {
+        bool *value = va_arg(ap, bool *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_BOOL) {
+          pn_data_get_bool(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'B':
+      {
+        uint8_t *value = va_arg(ap, uint8_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_UBYTE) {
+          pn_data_get_ubyte(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'b':
+      {
+        int8_t *value = va_arg(ap, int8_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_BYTE) {
+          pn_data_get_byte(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'H':
+      {
+        uint16_t *value = va_arg(ap, uint16_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_USHORT) {
+          pn_data_get_ushort(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'h':
+      {
+        int16_t *value = va_arg(ap, int16_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_SHORT) {
+          pn_data_get_short(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'I':
+      {
+        uint32_t *value = va_arg(ap, uint32_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_UINT) {
+          pn_data_get_uint(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'i':
+      {
+        int32_t *value = va_arg(ap, int32_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_INT) {
+          pn_data_get_int(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'L':
+      {
+        uint64_t *value = va_arg(ap, uint64_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_ULONG) {
+          pn_data_get_ulong(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'l':
+      {
+        int64_t *value = va_arg(ap, int64_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_LONG) {
+          pn_data_get_long(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'f':
+      {
+        float *value = va_arg(ap, float *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_FLOAT) {
+          pn_data_get_float(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'd':
+      {
+        double *value = va_arg(ap, double *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_DOUBLE) {
+          pn_data_get_double(data, value);
+          scanned = true;
+        } else {
+          *value = 0;
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'z':
+      {
+        pn_bytes_t *bytes = va_arg(ap, pn_bytes_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_BINARY) {
+          pn_data_get_binary(data, bytes);
+          scanned = true;
+        } else {
+          *bytes = (pn_bytes_t) {0, 0};
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'S':
+      {
+        pn_bytes_t *bytes = va_arg(ap, pn_bytes_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_STRING) {
+          pn_data_get_string(data, bytes);
+          scanned = true;
+        } else {
+          *bytes = (pn_bytes_t) {0, 0};
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 's':
+      {
+        pn_bytes_t *bytes = va_arg(ap, pn_bytes_t *);
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_SYMBOL) {
+          pn_data_get_symbol(data, bytes);
+          scanned = true;
+        } else {
+          *bytes = (pn_bytes_t) {0, 0};
+          scanned = false;
+        }
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case 'D':
+      found = suspend ? false : pn_data_next(data, &type);
+      if (found && type == PN_DESCRIPTOR) {
+        pn_data_enter(data);
+        scanned = true;
+      } else {
+        resume_count = 2;
+        scanned = false;
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+      /*    case 'T':
+      if (atom && atom->type == PN_TYPE) {
+        pn_type_t *type = va_arg(ap, pn_type_t *);
+        *type = atom->u.type;
+        scanned = true;
+      } else {
+        scanned = false;
+      }
+      if (atoms) pn_atoms_ltrim(atoms, 1);
+      return 0;*/
+    case '@':
+      found = suspend ? false : pn_data_next(data, &type);
+      if (found && type == PN_ARRAY) {
+        pn_data_enter(data);
+        scanned = true;
+        at = true;
+      } else {
+        if (!resume_count) resume_count = 2;
+        scanned = false;
+      }
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case '[':
+      if (at) {
+        scanned = true;
+        at = false;
+      } else {
+        found = suspend ? false : pn_data_next(data, &type);
+        if (found && type == PN_LIST) {
+          pn_data_enter(data);
+          scanned = true;
+        } else {
+          if (!resume_count) resume_count = 1;
+          scanned = false;
+        }
+      }
+      level++;
+      break;
+    case '{':
+      found = suspend ? false : pn_data_next(data, &type);
+      if (found && type == PN_MAP) {
+        pn_data_enter(data);
+        scanned = true;
+      } else {
+        if (!resume_count) resume_count = 1;
+        scanned = false;
+      }
+      level++;
+      break;
+    case ']':
+    case '}':
+      level--;
+      if (!suspend && !pn_data_exit(data))
+        return pn_error_format(data->error, PN_ERR, "exit failed");
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case '.':
+      found = suspend ? false : pn_data_next(data, &type);
+      scanned = found;
+      if (resume_count && level == count_level) resume_count--;
+      break;
+    case '?':
+      if (!*fmt || *fmt == '?')
+        return pn_error_format(data->error, PN_ARG_ERR, "codes must follow a ?");
+      scanarg = va_arg(ap, bool *);
+      break;
+    default:
+      return pn_error_format(data->error, PN_ARG_ERR, "unrecognized scan code: 0x%.2X '%c'", code, code);
+    }
+
+    if (scanarg && code != '?') {
+      *scanarg = scanned;
+      scanarg = NULL;
+    }
+  }
+
+  return 0;
 }
 
 int pn_data_scan(pn_data_t *data, const char *fmt, ...)
@@ -1805,26 +2294,23 @@ int pn_data_scan(pn_data_t *data, const 
   return err;
 }
 
-int pn_data_print(pn_data_t *data)
-{
-  pn_atoms_t atoms = {.size=data->size, .start=data->atoms};
-  return pn_print_atoms(&atoms);
-}
-
-pn_atoms_t pn_data_atoms(pn_data_t *data)
-{
-  return (pn_atoms_t) {.size=data->size, .start=data->atoms};
-}
+int pn_data_as_atoms(pn_data_t *data, pn_atoms_t *atoms);
 
-pn_atoms_t pn_data_available(pn_data_t *data)
+int pn_data_print(pn_data_t *data)
 {
-  return (pn_atoms_t) {.size=data->capacity - data->size,
-      .start=data->atoms + data->size};
+  pn_atom_t atoms[data->size + data->extras];
+  pn_atoms_t latoms = {.size=data->size + data->extras, .start=atoms};
+  pn_data_as_atoms(data, &latoms);
+  return pn_print_atoms(&latoms);
 }
 
 int pn_data_format(pn_data_t *data, char *bytes, size_t *size)
 {
-  ssize_t sz = pn_format_atoms(bytes, *size, pn_data_atoms(data));
+  pn_atom_t atoms[data->size + data->extras];
+  pn_atoms_t latoms = {.size=data->size + data->extras, .start=atoms};
+  pn_data_as_atoms(data, &latoms);
+
+  ssize_t sz = pn_format_atoms(bytes, *size, latoms);
   if (sz < 0) {
     return sz;
   } else {
@@ -1839,3 +2325,806 @@ int pn_data_resize(pn_data_t *data, size
   data->size = size;
   return 0;
 }
+
+
+pn_node_t *pn_data_node(pn_data_t *data, size_t nd)
+{
+  if (nd) {
+    return &data->nodes[nd - 1];
+  } else {
+    return NULL;
+  }
+}
+
+size_t pn_data_id(pn_data_t *data, pn_node_t *node)
+{
+  return node - data->nodes + 1;
+}
+
+pn_node_t *pn_data_new(pn_data_t *data)
+{
+  if (data->capacity <= data->size) {
+    pn_data_grow(data);
+  }
+  pn_node_t *node = pn_data_node(data, ++(data->size));
+  node->next = 0;
+  node->down = 0;
+  node->children = 0;
+  return node;
+}
+
+void pn_data_rewind(pn_data_t *data)
+{
+  data->parent = 0;
+  data->current = 0;
+}
+
+pn_node_t *pn_data_current(pn_data_t *data)
+{
+  return pn_data_node(data, data->current);
+}
+
+bool pn_data_next(pn_data_t *data, pn_type_t *type)
+{
+  pn_node_t *current = pn_data_current(data);
+  pn_node_t *parent = pn_data_node(data, data->parent);
+  size_t next;
+
+  if (current) {
+    next = current->next;
+  } else if (parent && parent->down) {
+    next = parent->down;
+  } else if (!parent && data->size) {
+    next = 1;
+  } else {
+    *type = -1;
+    return false;
+  }
+
+  if (next) {
+    data->current = next;
+    current = pn_data_current(data);
+    *type = current->atom.type;
+    return true;
+  } else {
+    *type = -1;
+    return false;
+  }
+}
+
+bool pn_data_prev(pn_data_t *data, pn_type_t *type)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->prev) {
+    data->current = node->prev;
+    pn_node_t *prev = pn_data_current(data);
+    *type = prev->atom.type;
+    return true;
+  } else {
+    *type = -1;
+    return false;
+  }
+}
+
+bool pn_data_enter(pn_data_t *data)
+{
+  if (data->current) {
+    data->parent = data->current;
+    data->current = 0;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool pn_data_exit(pn_data_t *data)
+{
+  if (data->parent) {
+    pn_node_t *parent = pn_data_node(data, data->parent);
+    data->current = data->parent;
+    data->parent = parent->parent;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void pn_data_dump(pn_data_t *data)
+{
+  char buf[1024];
+  printf("{current=%zi, parent=%zi}\n", data->current, data->parent);
+  for (int i = 0; i < data->size; i++)
+  {
+    pn_node_t *node = &data->nodes[i];
+    pn_bytes_t bytes = pn_bytes(1024, buf);
+    pn_format_atom(&bytes, node->atom);
+    printf("Node %i: prev=%zi, next=%zi, parent=%zi, down=%zi, children=%zi, type=%i (%s)\n",
+           i + 1, node->prev, node->next, node->parent, node->down, node->children, node->atom.type,
+           buf);
+  }
+}
+
+pn_node_t *pn_data_add(pn_data_t *data)
+{
+  pn_node_t *current = pn_data_current(data);
+  pn_node_t *parent = pn_data_node(data, data->parent);
+  pn_node_t *node;
+
+  if (current) {
+    if (current->next) {
+      node = pn_data_node(data, current->next);
+    } else {
+      node = pn_data_new(data);
+      // refresh the pointers in case we grew
+      current = pn_data_current(data);
+      parent = pn_data_node(data, data->parent);
+      node->prev = data->current;
+      current->next = pn_data_id(data, node);
+      node->parent = data->parent;
+      if (parent) {
+        if (!parent->down) {
+          parent->down = pn_data_id(data, node);
+        }
+        parent->children++;
+      }
+    }
+  } else if (parent) {
+    if (parent->down) {
+      node = pn_data_node(data, parent->down);
+    } else {
+      node = pn_data_new(data);
+      // refresh the pointers in case we grew
+      parent = pn_data_node(data, data->parent);
+      node->prev = 0;
+      node->parent = data->parent;
+      parent->down = pn_data_id(data, node);
+      parent->children++;
+    }
+  } else if (data->size) {
+    node = pn_data_node(data, 1);
+  } else {
+    node = pn_data_new(data);
+    node->prev = 0;
+    node->parent = 0;
+  }
+
+  node->down = 0;
+  node->children = 0;
+  node->data = false;
+  node->data_offset = 0;
+  node->data_size = 0;
+  data->current = pn_data_id(data, node);
+  return node;
+}
+
+
+int pn_data_as_atoms(pn_data_t *data, pn_atoms_t *atoms)
+{
+  pn_node_t *node = data->size ? pn_data_node(data, 1) : NULL;
+  size_t natoms = 0;
+  while (node) {
+    if (natoms >= atoms->size) {
+      return PN_OVERFLOW;
+    }
+
+    switch (node->atom.type) {
+    case PN_LIST:
+    case PN_MAP:
+      node->atom.u.count = node->children;
+      break;
+    case PN_ARRAY:
+      node->atom.u.count = node->described ? node->children - 1 : node->children;
+      break;
+    default:
+      break;
+    }
+
+    atoms->start[natoms++] = node->atom;
+
+    if (node->atom.type == PN_ARRAY) {
+      if (node->described) {
+        atoms->start[natoms++] = (pn_atom_t) {.type=PN_DESCRIPTOR};
+      } else {
+        atoms->start[natoms++] = (pn_atom_t) {.type=PN_TYPE, .u.type=node->type};
+      }
+    }
+
+    pn_node_t *parent = pn_data_node(data, node->parent);
+    if (parent && parent->atom.type == PN_ARRAY && parent->described &&
+        parent->down == pn_data_id(data, node)) {
+      atoms->start[natoms++] = (pn_atom_t) {.type=PN_TYPE, .u.type=parent->type};
+    }
+
+    size_t next = 0;
+    if (node->down) {
+      next = node->down;
+    } else if (node->next) {
+      next = node->next;
+    } else {
+      while (parent) {
+        if (parent->next) {
+          next = parent->next;
+          break;
+        } else {
+          parent = pn_data_node(data, parent->parent);
+        }
+      }
+    }
+
+    node = pn_data_node(data, next);
+  }
+
+  atoms->size = natoms;
+  return 0;
+}
+
+ssize_t pn_data_encode(pn_data_t *data, char *bytes, size_t size)
+{
+  pn_atom_t atoms[data->size + data->extras];
+
+  pn_atoms_t latoms = {.size=data->size + data->extras, .start=atoms};
+  pn_data_as_atoms(data, &latoms);
+  pn_bytes_t lbytes = pn_bytes(size, bytes);
+
+  int err = pn_encode_atoms(&lbytes, &latoms);
+  if (err) return err;
+  return 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 < atoms.size; i++) {
+    if (count == limit) return i - offset;
+    pn_atom_t atom = atoms.start[i];
+    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_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_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_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, 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;
+    case PN_TYPE:
+      return PN_ERR;
+      break;
+    }
+  }
+
+  return i - offset;
+}
+
+ssize_t pn_data_decode(pn_data_t *data, char *bytes, size_t size)
+{
+  size_t asize = 64;
+  pn_atoms_t latoms;
+  pn_bytes_t lbytes;
+
+  while (true) {
+    pn_atom_t atoms[asize];
+    latoms.size = asize;
+    latoms.start = atoms;
+    lbytes.size = size;
+    lbytes.start = bytes;
+
+    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;
+    }
+  }
+}
+
+int pn_data_put_list(pn_data_t *data)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_LIST;
+  node->atom.u.count = 0;
+  return 0;
+}
+
+int pn_data_put_map(pn_data_t *data)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_MAP;
+  node->atom.u.count = 0;
+  return 0;
+}
+
+int pn_data_put_array(pn_data_t *data, bool described, pn_type_t type)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_ARRAY;
+  node->atom.u.count = 0;
+  node->described = described;
+  node->type = type;
+  // XXX
+  data->extras += 2;
+  return 0;
+}
+
+int pn_data_put_described(pn_data_t *data)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_DESCRIPTOR;
+  return 0;
+}
+
+int pn_data_put_null(pn_data_t *data)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom = (pn_atom_t) {.type=PN_NULL};
+  return 0;
+}
+
+int pn_data_put_bool(pn_data_t *data, bool b)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_BOOL;
+  node->atom.u.as_bool = b;
+  return 0;
+}
+
+int pn_data_put_ubyte(pn_data_t *data, uint8_t ub)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_UBYTE;
+  node->atom.u.as_ubyte = ub;
+  return 0;
+}
+
+int pn_data_put_byte(pn_data_t *data, int8_t b)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_BYTE;
+  node->atom.u.as_byte = b;
+  return 0;
+}
+
+int pn_data_put_ushort(pn_data_t *data, uint16_t us)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_USHORT;
+  node->atom.u.as_ushort = us;
+  return 0;
+}
+
+int pn_data_put_short(pn_data_t *data, int16_t s)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_SHORT;
+  node->atom.u.as_short = s;
+  return 0;
+}
+
+int pn_data_put_uint(pn_data_t *data, uint32_t ui)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_UINT;
+  node->atom.u.as_uint = ui;
+  return 0;
+}
+
+int pn_data_put_int(pn_data_t *data, int32_t i)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_INT;
+  node->atom.u.as_int = i;
+  return 0;
+}
+
+int pn_data_put_ulong(pn_data_t *data, uint64_t ul)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_ULONG;
+  node->atom.u.as_ulong = ul;
+  return 0;
+}
+
+int pn_data_put_long(pn_data_t *data, int64_t l)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_LONG;
+  node->atom.u.as_long = l;
+  return 0;
+}
+
+int pn_data_put_float(pn_data_t *data, float f)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_FLOAT;
+  node->atom.u.as_float = f;
+  return 0;
+}
+
+int pn_data_put_double(pn_data_t *data, double d)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_DOUBLE;
+  node->atom.u.as_double = d;
+  return 0;
+}
+
+int pn_data_put_binary(pn_data_t *data, pn_bytes_t bytes)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_BINARY;
+  node->atom.u.as_binary = bytes;
+  return pn_data_intern_node(data, node);
+}
+
+int pn_data_put_string(pn_data_t *data, pn_bytes_t string)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_STRING;
+  node->atom.u.as_string = string;
+  return pn_data_intern_node(data, node);
+}
+
+int pn_data_put_symbol(pn_data_t *data, pn_bytes_t symbol)
+{
+  pn_node_t *node = pn_data_add(data);
+  node->atom.type = PN_SYMBOL;
+  node->atom.u.as_symbol = symbol;
+  return pn_data_intern_node(data, node);
+}
+
+int pn_data_get_list(pn_data_t *data, size_t *count)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_LIST) {
+    *count = node->children;
+    return 0;
+  } else {
+    *count = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_map(pn_data_t *data, size_t *count)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_MAP) {
+    *count = node->children;
+    return 0;
+  } else {
+    *count = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_array(pn_data_t *data, size_t *count, bool *described, pn_type_t *type)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_ARRAY) {
+    if (node->described) {
+      *count = node->children - 1;
+      *described = true;
+    } else {
+      *count = node->children;
+      *described = false;
+    }
+    *type = node->type;
+    return 0;
+  } else {
+    *count = 0;
+    return PN_ERR;
+  }
+  return PN_ERR;
+}
+
+int pn_data_get_described(pn_data_t *data)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_DESCRIPTOR) {
+    return 0;
+  } else {
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_null(pn_data_t *data)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_NULL) {
+    return 0;
+  } else {
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_bool(pn_data_t *data, bool *b)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_BOOL) {
+    *b = node->atom.u.as_bool;
+    return 0;
+  } else {
+    *b = false;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_ubyte(pn_data_t *data, uint8_t *ub)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_UBYTE) {
+    *ub = node->atom.u.as_ubyte;
+    return 0;
+  } else {
+    *ub = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_byte(pn_data_t *data, int8_t *b)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_BYTE) {
+    *b = node->atom.u.as_byte;
+    return 0;
+  } else {
+    *b = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_ushort(pn_data_t *data, uint16_t *us)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_USHORT) {
+    *us = node->atom.u.as_ushort;
+    return 0;
+  } else {
+    *us = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_short(pn_data_t *data, int16_t *s)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_SHORT) {
+    *s = node->atom.u.as_short;
+    return 0;
+  } else {
+    *s = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_uint(pn_data_t *data, uint32_t *ui)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node && node->atom.type == PN_UINT) {
+    *ui = node->atom.u.as_uint;
+    return 0;
+  } else {
+    *ui = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_int(pn_data_t *data, int32_t *i)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_INT) {
+    *i = node->atom.u.as_int;
+    return 0;
+  } else {
+    *i = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_ulong(pn_data_t *data, uint64_t *ul)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_ULONG) {
+    *ul = node->atom.u.as_ulong;
+    return 0;
+  } else {
+    *ul = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_long(pn_data_t *data, int64_t *l)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_LONG) {
+    *l = node->atom.u.as_long;
+    return 0;
+  } else {
+    *l = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_float(pn_data_t *data, float *f)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_FLOAT) {
+    *f = node->atom.u.as_float;
+    return 0;
+  } else {
+    *f = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_double(pn_data_t *data, double *d)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_DOUBLE) {
+    *d = node->atom.u.as_double;
+    return 0;
+  } else {
+    *d = 0;
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_binary(pn_data_t *data, pn_bytes_t *bytes)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_BINARY) {
+    *bytes = node->atom.u.as_binary;
+    return 0;
+  } else {
+    *bytes = (pn_bytes_t) {0};
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_string(pn_data_t *data, pn_bytes_t *string)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_STRING) {
+    *string = node->atom.u.as_string;
+    return 0;
+  } else {
+    *string = (pn_bytes_t) {0};
+    return PN_ERR;
+  }
+}
+
+int pn_data_get_symbol(pn_data_t *data, pn_bytes_t *symbol)
+{
+  pn_node_t *node = pn_data_current(data);
+  if (node->atom.type == PN_SYMBOL) {
+    *symbol = node->atom.u.as_symbol;
+    return 0;
+  } else {
+    *symbol = (pn_bytes_t) {0};
+    return PN_ERR;
+  }
+}

Modified: qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c (original)
+++ qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c Mon Sep 24 17:13:28 2012
@@ -112,21 +112,24 @@ ssize_t pn_dispatcher_input(pn_dispatche
     pn_frame_t frame;
     size_t n = pn_read_frame(&frame, bytes + read, available);
     if (n) {
-      size_t dsize = frame.size;
-      int e = pn_data_decode(disp->args, frame.payload, &dsize);
-      if (e) {
-        fprintf(stderr, "Error decoding frame: %s\n", pn_code(e));
+      ssize_t dsize = pn_data_decode(disp->args, frame.payload, frame.size);
+      if (dsize < 0) {
+        fprintf(stderr, "Error decoding frame: %s %s\n", pn_code(dsize),
+                pn_data_error(disp->args));
         pn_fprint_data(stderr, frame.payload, frame.size);
         fprintf(stderr, "\n");
-        return e;
+        return dsize;
       }
 
       disp->channel = frame.channel;
       // XXX: assuming numeric
       uint64_t lcode;
       bool scanned;
-      e = pn_data_scan(disp->args, "D?L.", &scanned, &lcode);
-      if (e) return e;
+      int e = pn_data_scan(disp->args, "D?L.", &scanned, &lcode);
+      if (e) {
+        fprintf(stderr, "Scan error\n");
+        return e;
+      }
       if (!scanned) {
         fprintf(stderr, "Error dispatching frame\n");
         return PN_ERR;
@@ -168,6 +171,7 @@ int pn_scan_args(pn_dispatcher_t *disp, 
   va_start(ap, fmt);
   int err = pn_data_vscan(disp->args, fmt, ap);
   va_end(ap);
+  if (err) printf("scan error: %s\n", fmt);
   return err;
 }
 
@@ -185,7 +189,7 @@ int pn_post_frame(pn_dispatcher_t *disp,
   int err = pn_data_vfill(disp->output_args, fmt, ap);
   va_end(ap);
   if (err) {
-    fprintf(stderr, "error posting frame: %s, %s\n", fmt, pn_code(err));
+    fprintf(stderr, "error posting frame: %s, %s: %s\n", fmt, pn_code(err), pn_data_error(disp->output_args));
     return PN_ERR;
   }
 
@@ -195,15 +199,14 @@ int pn_post_frame(pn_dispatcher_t *disp,
 
   while (true) {
     char buf[size];
-    size_t wr = size;
-    err = pn_data_encode(disp->output_args, buf, &wr);
-    if (err)
+    ssize_t wr = pn_data_encode(disp->output_args, buf, size);
+    if (wr < 0)
     {
-      if (err == PN_OVERFLOW) {
+      if (wr == PN_OVERFLOW) {
         size *= 2;
         continue;
       } else {
-        fprintf(stderr, "error posting frame: %s", pn_code(err));
+        fprintf(stderr, "error posting frame: %s", pn_code(wr));
         return PN_ERR;
       }
     } else if (size - wr < disp->output_size) {

Modified: qpid/proton/trunk/proton-c/src/message/message.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/message/message.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/message/message.c (original)
+++ qpid/proton/trunk/proton-c/src/message/message.c Mon Sep 24 17:13:28 2012
@@ -32,15 +32,16 @@
 
 ssize_t pn_message_data(char *dst, size_t available, const char *src, size_t size)
 {
-  pn_bytes_t bytes = pn_bytes(available, dst);
-  pn_atom_t buf[16];
-  pn_atoms_t atoms = {16, buf};
-
-  int err = pn_fill_atoms(&atoms, "DLz", 0x75, size, src);
-  if (err) return err;
-  err = pn_encode_atoms(&bytes, &atoms);
-  if (err) return err;
-  return bytes.size;
+  pn_data_t *data = pn_data(16);
+  pn_data_put_described(data);
+  pn_data_enter(data);
+  pn_data_put_long(data, 0x75);
+  pn_data_put_binary(data, pn_bytes(size, (char *)src));
+  pn_data_exit(data);
+  pn_data_rewind(data);
+  int err = pn_data_encode(data, dst, available);
+  pn_data_free(data);
+  return err;
 }
 
 // message
@@ -242,8 +243,7 @@ static int pn_buffer_set_bytes(pn_buffer
     *buf = pn_buffer(64);
   }
 
-  int err = pn_buffer_clear(*buf);
-  if (err) return err;
+  pn_buffer_clear(*buf);
 
   return pn_buffer_append(*buf, bytes.start, bytes.size);
 }
@@ -266,9 +266,8 @@ static int pn_buffer_set_strn(pn_buffer_
     *buf = pn_buffer(64);
   }
 
-  int err = pn_buffer_clear(*buf);
-  if (err) return err;
-  err = pn_buffer_append(*buf, str, size);
+  pn_buffer_clear(*buf);
+  int err = pn_buffer_append(*buf, str, size);
   if (err) return err;
   if (str && str[size-1]) {
     return pn_buffer_append(*buf, "\0", 1);
@@ -422,15 +421,14 @@ int pn_message_decode(pn_message_t *msg,
   pn_data_clear(msg->body);
 
   while (size) {
-    size_t copy = size;
     pn_data_clear(msg->data);
-    int err = pn_data_decode(msg->data, (char *) bytes, &copy);
-    if (err) return err;
-    size -= copy;
-    bytes += copy;
+    ssize_t used = pn_data_decode(msg->data, (char *) bytes, size);
+    if (used < 0) return used;
+    size -= used;
+    bytes += used;
     bool scanned;
     uint64_t desc;
-    err = pn_data_scan(msg->data, "D?L.", &scanned, &desc);
+    int err = pn_data_scan(msg->data, "D?L.", &scanned, &desc);
     if (err) return err;
     if (!scanned){
       desc = 0;
@@ -478,8 +476,6 @@ int pn_message_decode(pn_message_t *msg,
         pn_data_t *data = msg->body;
         msg->body = msg->data;
         msg->data = data;
-        err = pn_data_intern(msg->body);
-        if (err) return err;
       }
       break;
     }
@@ -521,17 +517,14 @@ int pn_message_encode(pn_message_t *msg,
   if (err) return err;
 
   size_t remaining = *size;
-  size_t encoded = remaining;
-
-  err = pn_data_encode(msg->data, bytes, &encoded);
-  if (err) return err;
+  ssize_t encoded = pn_data_encode(msg->data, bytes, remaining);
+  if (encoded < 0) return encoded;
 
   bytes += encoded;
   remaining -= encoded;
 
-  encoded = remaining;
-  err = pn_data_encode(msg->body, bytes, &encoded);
-  if (err) return err;
+  encoded = pn_data_encode(msg->body, bytes, remaining);
+  if (encoded < 0) return encoded;
   bytes += encoded;
   remaining -= encoded;
 
@@ -574,9 +567,8 @@ int pn_message_load_data(pn_message_t *m
     msg->body = pn_data(64);
   }
 
-  int err = pn_data_fill(msg->body, "DLz", DATA, size, data);
-  if (err) return err;
-  return pn_data_intern(msg->body);
+  pn_data_clear(msg->body);
+  return pn_data_fill(msg->body, "DLz", DATA, size, data);
 }
 
 int pn_message_load_text(pn_message_t *msg, const char *data, size_t size)
@@ -586,9 +578,8 @@ int pn_message_load_text(pn_message_t *m
     msg->body = pn_data(64);
   }
 
-  int err = pn_data_fill(msg->body, "DLS", AMQP_VALUE, data);
-  if (err) return err;
-  return pn_data_intern(msg->body);
+  pn_data_clear(msg->body);
+  return pn_data_fill(msg->body, "DLS", AMQP_VALUE, data);
 }
 
 int pn_message_load_amqp(pn_message_t *msg, const char *data, size_t size)
@@ -601,20 +592,8 @@ int pn_message_load_amqp(pn_message_t *m
 
   pn_parser_t *parser = pn_message_parser(msg);
 
-  while (true) {
-    pn_data_clear(msg->body);
-    pn_atoms_t atoms = pn_data_available(msg->body);
-    int err = pn_parser_parse(parser, data, &atoms);
-    if (err == PN_OVERFLOW) {
-      err = pn_data_grow(msg->body);
-      if (err) return err;
-      continue;
-    } else if (err) {
-      return err;
-    } else {
-      return pn_data_resize(msg->body, atoms.size);
-    }
-  }
+  pn_data_clear(msg->body);
+  return pn_parser_parse(parser, data, msg->body);
 }
 
 int pn_message_load_json(pn_message_t *msg, const char *data, size_t size)

Modified: qpid/proton/trunk/proton-c/src/parser.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/parser.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/parser.c (original)
+++ qpid/proton/trunk/proton-c/src/parser.c Mon Sep 24 17:13:28 2012
@@ -95,44 +95,43 @@ pn_token_t pn_parser_token(pn_parser_t *
   return pn_scanner_token(parser->scanner);
 }
 
-int pn_parser_value(pn_parser_t *parser, pn_atoms_t *atoms);
+int pn_parser_value(pn_parser_t *parser, pn_data_t *data);
 
-int pn_parser_descriptor(pn_parser_t *parser, pn_atoms_t *atoms)
+int pn_parser_descriptor(pn_parser_t *parser, pn_data_t *data)
 {
   if (pn_parser_token(parser).type == PN_TOK_AT) {
     int err = pn_parser_shift(parser);
     if (err) return err;
 
-    pn_atom_t *desc = atoms->start;
-    err = pn_ifill_atoms(atoms, "n");
-    if (err) return pn_parser_err(parser, err,
-                                  "error writing descriptor atoms");
-    desc->type = PN_DESCRIPTOR;
-    err = pn_parser_value(parser, atoms);
-    if (err) return err;
-    return pn_parser_value(parser, atoms);
+    err = pn_data_put_described(data);
+    if (err) return pn_parser_err(parser, err, "error writing described");
+    pn_data_enter(data);
+    for (int i = 0; i < 2; i++) {
+      err = pn_parser_value(parser, data);
+      if (err) return err;
+    }
+    pn_data_exit(data);
+    return 0;
   } else {
     return pn_parser_err(parser, PN_ERR, "expecting '@'");
   }
 }
 
-int pn_parser_map(pn_parser_t *parser, pn_atoms_t *atoms)
+int pn_parser_map(pn_parser_t *parser, pn_data_t *data)
 {
   if (pn_parser_token(parser).type == PN_TOK_LBRACE) {
     int err = pn_parser_shift(parser);
     if (err) return err;
 
-    pn_atom_t *map = atoms->start;
-    err = pn_ifill_atoms(atoms, "{}");
-    if (err) return pn_parser_err(parser, err, "error writing map atoms");
+    err = pn_data_put_map(data);
+    if (err) return pn_parser_err(parser, err, "error writing map");
 
-    int count = 0;
+    pn_data_enter(data);
 
     if (pn_parser_token(parser).type != PN_TOK_RBRACE) {
       while (true) {
-        err = pn_parser_value(parser, atoms);
+        err = pn_parser_value(parser, data);
         if (err) return err;
-        count++;
 
         if (pn_parser_token(parser).type == PN_TOK_EQUAL) {
           err = pn_parser_shift(parser);
@@ -141,9 +140,8 @@ int pn_parser_map(pn_parser_t *parser, p
           return pn_parser_err(parser, PN_ERR, "expecting '='");
         }
 
-        err = pn_parser_value(parser, atoms);
+        err = pn_parser_value(parser, data);
         if (err) return err;
-        count++;
 
         if (pn_parser_token(parser).type == PN_TOK_COMMA) {
           err = pn_parser_shift(parser);
@@ -154,7 +152,7 @@ int pn_parser_map(pn_parser_t *parser, p
       }
     }
 
-    map->u.count = count;
+    pn_data_exit(data);
 
     if (pn_parser_token(parser).type == PN_TOK_RBRACE) {
       return pn_parser_shift(parser);
@@ -166,7 +164,7 @@ int pn_parser_map(pn_parser_t *parser, p
   }
 }
 
-int pn_parser_list(pn_parser_t *parser, pn_atoms_t *atoms)
+int pn_parser_list(pn_parser_t *parser, pn_data_t *data)
 {
   int err;
 
@@ -174,17 +172,15 @@ int pn_parser_list(pn_parser_t *parser, 
     err = pn_parser_shift(parser);
     if (err) return err;
 
-    pn_atom_t *list = atoms->start;
-    int err = pn_ifill_atoms(atoms, "[]");
-    if (err) return pn_parser_err(parser, err, "error writing list atoms");
+    err = pn_data_put_list(data);
+    if (err) return pn_parser_err(parser, err, "error writing list");
 
-    int count = 0;
+    pn_data_enter(data);
 
     if (pn_parser_token(parser).type != PN_TOK_RBRACKET) {
       while (true) {
-        err = pn_parser_value(parser, atoms);
+        err = pn_parser_value(parser, data);
         if (err) return err;
-        count++;
 
         if (pn_parser_token(parser).type == PN_TOK_COMMA) {
           err = pn_parser_shift(parser);
@@ -195,7 +191,7 @@ int pn_parser_list(pn_parser_t *parser, 
       }
     }
 
-    list->u.count = count;
+    pn_data_exit(data);
 
     if (pn_parser_token(parser).type == PN_TOK_RBRACKET) {
       return pn_parser_shift(parser);
@@ -213,7 +209,7 @@ void pn_parser_append_tok(pn_parser_t *p
   *idx += pn_parser_token(parser).size;
 }
 
-int pn_parser_number(pn_parser_t *parser, pn_atoms_t *atoms)
+int pn_parser_number(pn_parser_t *parser, pn_data_t *data)
 {
   bool dbl = false;
   char number[1024];
@@ -245,15 +241,15 @@ int pn_parser_number(pn_parser_t *parser
     if (negate) {
       value = -value;
     }
-    err = pn_ifill_atoms(atoms, "d", value);
-    if (err) return pn_parser_err(parser, err, "error writing double atoms");
+    err = pn_data_put_double(data, value);
+    if (err) return pn_parser_err(parser, err, "error writing double");
   } else {
     int64_t value = atoll(number);
     if (negate) {
       value = -value;
     }
-    err = pn_ifill_atoms(atoms, "l", value);
-    if (err) return pn_parser_err(parser, err, "error writing long atoms");
+    err = pn_data_put_long(data, value);
+    if (err) return pn_parser_err(parser, err, "error writing long");
   }
 
   return 0;
@@ -337,7 +333,7 @@ int pn_parser_unquote(pn_parser_t *parse
   return 0;
 }
 
-int pn_parser_value(pn_parser_t *parser, pn_atoms_t *atoms)
+int pn_parser_value(pn_parser_t *parser, pn_data_t *data)
 {
   int err;
   size_t n;
@@ -348,11 +344,11 @@ int pn_parser_value(pn_parser_t *parser,
   switch (tok.type)
   {
   case PN_TOK_AT:
-    return pn_parser_descriptor(parser, atoms);
+    return pn_parser_descriptor(parser, data);
   case PN_TOK_LBRACE:
-    return pn_parser_map(parser, atoms);
+    return pn_parser_map(parser, data);
   case PN_TOK_LBRACKET:
-    return pn_parser_list(parser, atoms);
+    return pn_parser_list(parser, data);
   case PN_TOK_BINARY:
   case PN_TOK_SYMBOL:
   case PN_TOK_STRING:
@@ -364,35 +360,35 @@ int pn_parser_value(pn_parser_t *parser,
     parser->size += n;
     switch (tok.type) {
     case PN_TOK_BINARY:
-      err = pn_ifill_atoms(atoms, "z", n - 1, dst);
+      err = pn_data_put_binary(data, pn_bytes(n - 1, dst));
       break;
     case PN_TOK_STRING:
-      err = pn_ifill_atoms(atoms, "S", dst);
+      err = pn_data_put_string(data, pn_bytes(n - 1, dst));
       break;
     case PN_TOK_SYMBOL:
-      err = pn_ifill_atoms(atoms, "s", dst);
+      err = pn_data_put_symbol(data, pn_bytes(n - 1, dst));
       break;
     default:
       return pn_parser_err(parser, PN_ERR, "internal error");
     }
-    if (err) return pn_parser_err(parser, err, "error writing string atoms");
+    if (err) return pn_parser_err(parser, err, "error writing string/binary/symbol");
     return pn_parser_shift(parser);
   case PN_TOK_POS:
   case PN_TOK_NEG:
   case PN_TOK_FLOAT:
   case PN_TOK_INT:
-    return pn_parser_number(parser, atoms);
+    return pn_parser_number(parser, data);
   case PN_TOK_TRUE:
-    err = pn_ifill_atoms(atoms, "o", true);
-    if (err) return pn_parser_err(parser, err, "error writing boolean atoms");
+    err = pn_data_put_bool(data, true);
+    if (err) return pn_parser_err(parser, err, "error writing boolean");
     return pn_parser_shift(parser);
   case PN_TOK_FALSE:
-    err = pn_ifill_atoms(atoms, "o", false);
-    if (err) return pn_parser_err(parser, err, "error writing boolean atoms");
+    err = pn_data_put_bool(data, false);
+    if (err) return pn_parser_err(parser, err, "error writing boolean");
     return pn_parser_shift(parser);
   case PN_TOK_NULL:
-    err = pn_ifill_atoms(atoms, "n");
-    if (err) return pn_parser_err(parser, err, "error writing null atoms");
+    err = pn_data_put_null(data);
+    if (err) return pn_parser_err(parser, err, "error writing null");
     return pn_parser_shift(parser);
   default:
     return pn_parser_err(parser, PN_ERR, "expecting one of '[', '{', STRING, "
@@ -400,7 +396,7 @@ int pn_parser_value(pn_parser_t *parser,
   }
 }
 
-int pn_parser_parse_r(pn_parser_t *parser, pn_atoms_t *atoms)
+int pn_parser_parse_r(pn_parser_t *parser, pn_data_t *data)
 {
   while (true) {
     int err;
@@ -411,20 +407,16 @@ int pn_parser_parse_r(pn_parser_t *parse
     case PN_TOK_ERR:
       return PN_ERR;
     default:
-      err = pn_parser_value(parser, atoms);
+      err = pn_parser_value(parser, data);
       if (err) return err;
     }
   }
 }
 
-int pn_parser_parse(pn_parser_t *parser, const char *str, pn_atoms_t *atoms)
+int pn_parser_parse(pn_parser_t *parser, const char *str, pn_data_t *data)
 {
-  pn_atoms_t copy = *atoms;
   int err = pn_scanner_start(parser->scanner, str);
   if (err) return err;
   parser->size = 0;
-  err = pn_parser_parse_r(parser, &copy);
-  if (err) return err;
-  atoms->size -= copy.size;
-  return 0;
+  return pn_parser_parse_r(parser, data);
 }

Modified: qpid/proton/trunk/proton-c/src/proton-dump.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/proton-dump.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/proton-dump.c (original)
+++ qpid/proton/trunk/proton-c/src/proton-dump.c Mon Sep 24 17:13:28 2012
@@ -59,10 +59,9 @@ int dump(const char *file)
       pn_frame_t frame;
       size_t consumed = pn_read_frame(&frame, available.start, available.size);
       if (consumed) {
-        size_t dsize = frame.size;
         pn_data_clear(data);
-        err = pn_data_decode(data, frame.payload, &dsize);
-        if (err) {
+        ssize_t dsize = pn_data_decode(data, frame.payload, frame.size);
+        if (dsize < 0) {
           fprintf(stderr, "Error decoding frame: %s\n", pn_code(err));
           pn_fprint_data(stderr, frame.payload, frame.size);
           fprintf(stderr, "\n");

Modified: qpid/proton/trunk/proton-c/src/proton.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/proton.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/proton.c (original)
+++ qpid/proton/trunk/proton-c/src/proton.c Mon Sep 24 17:13:28 2012
@@ -87,93 +87,6 @@ int buffer(int argc, char **argv)
   return 0;
 }
 
-int value(int argc, char **argv)
-{
-  pn_atom_t data[1024];
-  pn_atoms_t atoms = {1024, data};
-
-  int err = pn_fill_atoms(&atoms, "DDsL[i[i]i]{sfsf}@DLT[sss]", "blam", 21, 1, 2, 3,
-                          "pi", 3.14159265359, "e", 2.7,
-                          (uint64_t) 42, PN_SYMBOL, "one", "two", "three");
-  if (err) {
-    printf("err = %s\n", pn_code(err));
-  } else {
-    pn_print_atoms(&atoms);
-    printf("\n");
-  }
-
-  pn_bytes_t blam;
-  uint64_t n;
-  int32_t one, two, three;
-
-  pn_bytes_t key1;
-  float val1;
-
-  pn_bytes_t key2;
-  float val2;
-
-  uint64_t al;
-  pn_type_t type;
-
-  bool threeq;
-
-  pn_bytes_t sym;
-
-  err = pn_scan_atoms(&atoms, "DDsL[i[i]?i]{sfsf}@DLT[.s.]", &blam, &n, &one, &two, &threeq, &three,
-                      &key1, &val1, &key2, &val2, &al, &type, &sym);
-  if (err) {
-    printf("err = %s\n", pn_code(err));
-  } else {
-    printf("scan=%.*s %" PRIu64 " %i %i %i %.*s %f %.*s %f %" PRIu64 " %i %.*s\n", (int) blam.size,
-	   blam.start, n, one, two, three, (int) key1.size, key1.start, val1, (int) key2.size,
-	   key2.start, val2, al, threeq, (int) sym.size, sym.start);
-  }
-
-  char str[1024*10];
-  int ch, idx = 0;
-  while ((ch = getchar()) != EOF) {
-    str[idx++] = ch;
-  }
-  str[idx] = '\0';
-
-  /*  str[0] = '\0';
-  for (int i = 2; i < argc; i++) {
-    strcat(str, argv[i]);
-    if (i < argc - 1)
-      strcat(str, " ");
-      }*/
-
-  printf("JSON: %s\n", str);
-
-  pn_atom_t parserdata[1024];
-  pn_atoms_t parserd = {1024, parserdata};
-
-  printf("\n");
-
-  pn_parser_t *parser = pn_parser();
-
-  err = pn_parser_parse(parser, str, &parserd);
-  if (err) {
-    printf("parse err=%s, %s\n", pn_code(err), pn_parser_error(parser));
-  } else {
-    printf("--\n");
-    for (int i = 0; i < parserd.size; i++) {
-      printf("%s: ", pn_type_str(parserd.start[i].type));
-      err = pn_print_atom(parserd.start[i]);
-      if (err) printf("err=%s", pn_code(err));
-      printf("\n");
-    }
-    printf("--\n");
-    err = pn_print_atoms(&parserd);
-    if (err) printf("print err=%s", pn_code(err));
-    printf("\n");
-  }
-
-  pn_parser_free(parser);
-
-  return 0;
-}
-
 struct server_context {
   int count;
   bool quiet;
@@ -507,9 +420,6 @@ int main(int argc, char **argv)
     case 'V':
       printf("proton version %i.%i\n", PN_VERSION_MAJOR, PN_VERSION_MINOR);
       exit(EXIT_SUCCESS);
-    case 'X':
-      value(argc, argv);
-      exit(EXIT_SUCCESS);
     case 'Y':
       buffer(argc, argv);
       exit(EXIT_SUCCESS);

Modified: qpid/proton/trunk/proton-c/src/util.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/util.c?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/util.c (original)
+++ qpid/proton/trunk/proton-c/src/util.c Mon Sep 24 17:13:28 2012
@@ -136,7 +136,7 @@ char *pn_strndup(const char *src, size_t
 {
   if (src) {
     int size = 0;
-    for (const char *c = src; *c && size < n; c++) {
+    for (const char *c = src; size < n && *c; c++) {
       size++;
     }
 

Modified: qpid/proton/trunk/tests/proton_tests/__init__.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/__init__.py?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/__init__.py (original)
+++ qpid/proton/trunk/tests/proton_tests/__init__.py Mon Sep 24 17:13:28 2012
@@ -17,6 +17,7 @@
 # under the License.
 #
 
+import proton_tests.codec
 import proton_tests.engine
 import proton_tests.message
 import proton_tests.messenger

Added: qpid/proton/trunk/tests/proton_tests/codec.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/codec.py?rev=1389489&view=auto
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/codec.py (added)
+++ qpid/proton/trunk/tests/proton_tests/codec.py Mon Sep 24 17:13:28 2012
@@ -0,0 +1,173 @@
+#
+# 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.
+#
+
+import os, common, xproton
+from proton import *
+
+class Test(common.Test):
+
+  def setup(self):
+    self.data = Data()
+
+  def teardown(self):
+    self.data = None
+
+class DataTest(Test):
+
+  def testTopLevelNext(self):
+    assert self.data.next() is None
+    self.data.put_null()
+    self.data.put_bool(False)
+    self.data.put_int(0)
+    assert self.data.next() is None
+    self.data.rewind()
+    assert self.data.next() == Data.NULL
+    assert self.data.next() == Data.BOOL
+    assert self.data.next() == Data.INT
+    assert self.data.next() is None
+
+  def testNestedNext(self):
+    assert self.data.next() is None
+    self.data.put_null()
+    assert self.data.next() is None
+    self.data.put_list()
+    assert self.data.next() is None
+    self.data.put_bool(False)
+    assert self.data.next() is None
+    self.data.rewind()
+    assert self.data.next() is Data.NULL
+    assert self.data.next() is Data.LIST
+    self.data.enter()
+    assert self.data.next() is None
+    self.data.put_ubyte(0)
+    assert self.data.next() is None
+    self.data.put_uint(0)
+    assert self.data.next() is None
+    self.data.put_int(0)
+    assert self.data.next() is None
+    self.data.exit()
+    assert self.data.next() is Data.BOOL
+    assert self.data.next() is None
+
+    self.data.rewind()
+    assert self.data.next() is Data.NULL
+    assert self.data.next() is Data.LIST
+    assert self.data.enter()
+    assert self.data.next() is Data.UBYTE
+    assert self.data.next() is Data.UINT
+    assert self.data.next() is Data.INT
+    assert self.data.next() is None
+    assert self.data.exit()
+    assert self.data.next() is Data.BOOL
+    assert self.data.next() is None
+
+  def testEnterExit(self):
+    assert self.data.next() is None
+    assert not self.data.enter()
+    self.data.put_list()
+    assert self.data.enter()
+    assert self.data.next() is None
+    self.data.put_list()
+    assert self.data.enter()
+    self.data.put_list()
+    assert self.data.enter()
+    assert self.data.exit()
+    assert self.data.get_list() == 0
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert not self.data.exit()
+    assert self.data.get_list() == 1
+    assert self.data.next() is None
+
+    self.data.rewind()
+    assert self.data.next() is Data.LIST
+    assert self.data.get_list() == 1
+    assert self.data.enter()
+    assert self.data.next() is Data.LIST
+    assert self.data.get_list() == 1
+    assert self.data.enter()
+    assert self.data.next() is Data.LIST
+    assert self.data.get_list() == 0
+    assert self.data.enter()
+    assert self.data.next() is None
+    assert self.data.exit()
+    assert self.data.get_list() == 0
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert self.data.exit()
+    assert self.data.get_list() == 1
+    assert not self.data.exit()
+
+  def _test(self, dtype, *values, **kwargs):
+    eq=kwargs.get("eq", lambda x, y: x == y)
+    ntype = getattr(Data, dtype.upper())
+    putter = getattr(self.data, "put_%s" % dtype)
+    getter = getattr(self.data, "get_%s" % dtype)
+
+    for v in values:
+      putter(v)
+      gotten = getter()
+      assert eq(gotten, v), (gotten, v)
+
+    self.data.rewind()
+
+    for v in values:
+      vtype = self.data.next()
+      assert vtype == ntype, vtype
+      gotten = getter()
+      assert eq(gotten, v), (gotten, v)
+
+    encoded = self.data.encode()
+    copy = Data(0)
+    while encoded:
+      n = copy.decode(encoded)
+      encoded = encoded[n:]
+    copy.rewind()
+
+    cgetter = getattr(copy, "get_%s" % dtype)
+
+    for v in values:
+      vtype = copy.next()
+      assert vtype == ntype, vtype
+      gotten = cgetter()
+      assert eq(gotten, v), (gotten, v)
+
+  def testInt(self):
+    self._test("int", 1, 2, 3, -1, -2, -3)
+
+  def testString(self):
+    self._test("string", "one", "two", "three", "this is a test", "")
+
+  def testFloat(self):
+    # we have to use a special comparison here because python
+    # internaly only uses doubles and converting between floats and
+    # doubles is imprecise
+    self._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3,
+               eq=lambda x, y: x - y < 0.000001)
+
+  def testDouble(self):
+    self._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3)
+
+  def testBinary(self):
+    self._test("binary", "this", "is", "a", "test", "of" "b\x00inary")
+
+  def testSymbol(self):
+    self._test("symbol", "this is a symbol test", "bleh", "blah")

Modified: qpid/proton/trunk/tests/proton_tests/engine.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/engine.py?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/engine.py (original)
+++ qpid/proton/trunk/tests/proton_tests/engine.py Mon Sep 24 17:13:28 2012
@@ -39,10 +39,12 @@ def pump(t1, t2):
     if out1 or out2:
       if out1:
         cd = pn_input(t2, out1)
-        assert cd == PN_EOS or cd == len(out1), (cd, out1, len(out1))
+        assert cd == PN_EOS or cd == len(out1), \
+            (cd, out1, len(out1), pn_error_text(pn_transport_error(t2)))
       if out2:
         cd = pn_input(t1, out2)
-        assert cd == PN_EOS or cd == len(out2), (cd, out2, len(out2))
+        assert cd == PN_EOS or cd == len(out2), \
+            (cd, out2, len(out2), pn_error_text(pn_transport_error(t1)))
     else:
       return
 

Modified: qpid/proton/trunk/tests/proton_tests/message.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/message.py?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/message.py (original)
+++ qpid/proton/trunk/tests/proton_tests/message.py Mon Sep 24 17:13:28 2012
@@ -119,9 +119,11 @@ class CodecTest(Test):
     cd = pn_message_decode(msg2, data, len(data))
     assert cd == 0, (cd, data)
 
-    assert pn_message_get_ttl(self.msg) == pn_message_get_ttl(msg2)
+    assert pn_message_get_ttl(self.msg) == pn_message_get_ttl(msg2), \
+        (pn_message_get_ttl(self.msg), pn_message_get_ttl(msg2))
     assert pn_message_get_priority(self.msg) == pn_message_get_priority(msg2)
-    assert pn_message_get_address(self.msg) == pn_message_get_address(msg2)
+    assert pn_message_get_address(self.msg) == pn_message_get_address(msg2), \
+        (pn_message_get_address(self.msg), pn_message_get_address(msg2))
     assert pn_message_get_subject(self.msg) == pn_message_get_subject(msg2)
     cd, saved = pn_message_save(self.msg, 1024)
     assert not cd, cd

Modified: qpid/proton/trunk/tests/proton_tests/messenger.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/messenger.py?rev=1389489&r1=1389488&r2=1389489&view=diff
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/messenger.py (original)
+++ qpid/proton/trunk/tests/proton_tests/messenger.py Mon Sep 24 17:13:28 2012
@@ -84,7 +84,7 @@ class MessengerTest(Test):
     assert pn_message_get_subject(reply) == "Hello World!"
     cd, rbod = pn_message_save(reply, 1024)
     assert not cd
-    assert rbod == body
+    assert rbod == body, (rbod, body)
 
     pn_message_free(msg)
     pn_message_free(reply)



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org