Author: rhs
Date: Wed Nov 28 18:23:57 2012
New Revision: 1414849

URL: http://svn.apache.org/viewvc?rev=1414849&view=rev
Log:
modified encode to permit use of more efficient encodings

Modified:
    qpid/proton/trunk/proton-c/src/codec/codec.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=1414849&r1=1414848&r2=1414849&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/codec/codec.c (original)
+++ qpid/proton/trunk/proton-c/src/codec/codec.c Wed Nov 28 18:23:57 2012
@@ -72,7 +72,6 @@ typedef struct {
 } 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_iatom_t atom);
@@ -425,7 +424,6 @@ int pn_print_atoms(const pn_atoms_t *ato
 }
 
 int pn_decode_atom(pn_bytes_t *bytes, pn_atoms_t *atoms);
-int pn_encode_atom(pn_bytes_t *bytes, pn_atoms_t *atoms);
 
 int pn_decode_atoms(pn_bytes_t *bytes, pn_atoms_t *atoms)
 {
@@ -454,20 +452,6 @@ int pn_decode_one(pn_bytes_t *bytes, pn_
   return 0;
 }
 
-int pn_encode_atoms(pn_bytes_t *bytes, pn_atoms_t *atoms)
-{
-  pn_bytes_t buf = *bytes;
-  pn_atoms_t dat = *atoms;
-
-  while (dat.size) {
-    int e = pn_encode_atom(&buf, &dat);
-    if (e) return e;
-  }
-
-  bytes->size -= buf.size;
-  return 0;
-}
-
 uint8_t pn_type2code(pn_type_t type)
 {
   switch (type)
@@ -496,23 +480,13 @@ uint8_t pn_type2code(pn_type_t type)
   case PN_LIST: return PNE_LIST32;
   case PN_ARRAY: return PNE_ARRAY32;
   case PN_MAP: return PNE_MAP32;
+  case PN_DESCRIBED: return PNE_DESCRIPTOR;
   default:
     pn_fatal("not a value type: %u\n", type);
     return 0;
   }
 }
 
-int pn_encode_type(pn_bytes_t *bytes, pn_atoms_t *atoms, pn_type_t *type);
-int pn_encode_value(pn_bytes_t *bytes, pn_atoms_t *atoms, pn_type_t type);
-
-int pn_encode_atom(pn_bytes_t *bytes, pn_atoms_t *atoms)
-{
-  pn_type_t type;
-  int e = pn_encode_type(bytes, atoms, &type);
-  if (e) return e;
-  return pn_encode_value(bytes, atoms, type);
-}
-
 int pn_bytes_writef8(pn_bytes_t *bytes, uint8_t value)
 {
   if (bytes->size) {
@@ -569,12 +543,12 @@ int pn_bytes_writef128(pn_bytes_t *bytes
   }
 }
 
-int pn_bytes_writev32(pn_bytes_t *bytes, const pn_bytes_t *value)
+int pn_bytes_writev8(pn_bytes_t *bytes, const pn_bytes_t *value)
 {
-  if (bytes->size < 4 + value->size) {
+  if (bytes->size < 1 + value->size) {
     return PN_OVERFLOW;
   } else {
-    int e = pn_bytes_writef32(bytes, value->size);
+    int e = pn_bytes_writef8(bytes, value->size);
     if (e) return e;
     memmove(bytes->start, value->start, value->size);
     pn_bytes_ltrim(bytes, value->size);
@@ -582,113 +556,16 @@ int pn_bytes_writev32(pn_bytes_t *bytes,
   }
 }
 
-int pn_encode_type(pn_bytes_t *bytes, pn_atoms_t *atoms, pn_type_t *type)
+int pn_bytes_writev32(pn_bytes_t *bytes, const pn_bytes_t *value)
 {
-  if (!atoms->size) return PN_UNDERFLOW;
-
-  pn_iatom_t *atom = atoms->start;
-  if (atom->type == PN_DESCRIPTOR)
-  {
-    pn_atoms_ltrim(atoms, 1);
-    int e = pn_bytes_writef8(bytes, 0);
-    if (e) return e;
-    e = pn_encode_atom(bytes, atoms);
-    if (e) return e;
-    return pn_encode_type(bytes, atoms, type);
-  } else if (atom->type == PN_TYPE) {
-    *type = atom->u.type;
+  if (bytes->size < 4 + value->size) {
+    return PN_OVERFLOW;
   } else {
-    *type = atom->type;
-  }
-
-  return pn_bytes_writef8(bytes, pn_type2code(*type));
-}
-
-int pn_encode_value(pn_bytes_t *bytes, pn_atoms_t *atoms, pn_type_t type)
-{
-  pn_iatom_t *atom = atoms->start;
-  int e;
-  conv_t c;
-
-  if (!atoms->size) return PN_UNDERFLOW;
-  pn_atoms_ltrim(atoms, 1);
-
-  switch (type)
-  {
-  case PN_NULL: return 0;
-  case PN_BOOL: return pn_bytes_writef8(bytes, atom->u.as_bool);
-  case PN_UBYTE: return pn_bytes_writef8(bytes, atom->u.as_ubyte);
-  case PN_BYTE: return pn_bytes_writef8(bytes, atom->u.as_byte);
-  case PN_USHORT: return pn_bytes_writef16(bytes, atom->u.as_ushort);
-  case PN_SHORT: return pn_bytes_writef16(bytes, atom->u.as_short);
-  case PN_UINT: return pn_bytes_writef32(bytes, atom->u.as_uint);
-  case PN_INT: return pn_bytes_writef32(bytes, atom->u.as_int);
-  case PN_CHAR: return pn_bytes_writef32(bytes, atom->u.as_char);
-  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_TIMESTAMP: return pn_bytes_writef64(bytes, atom->u.as_timestamp);
-  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_writef64(bytes, 
c.l);
-  case PN_DECIMAL32: return pn_bytes_writef32(bytes, atom->u.as_decimal32);
-  case PN_DECIMAL64: return pn_bytes_writef64(bytes, atom->u.as_decimal64);
-  case PN_DECIMAL128: return pn_bytes_writef128(bytes, 
atom->u.as_decimal128.bytes);
-  case PN_UUID: return pn_bytes_writef128(bytes, atom->u.as_uuid.bytes);
-  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);
-  case PN_ARRAY:
-    {
-      char *start = bytes->start;
-      // we'll backfill the size later
-      if (bytes->size < 4) return PN_OVERFLOW;
-      pn_bytes_ltrim(bytes, 4);
-      size_t count = atom->u.count;
-      e = pn_bytes_writef32(bytes, count);
-      if (e) return e;
-      pn_type_t atype;
-      e = pn_encode_type(bytes, atoms, &atype);
-      if (e) return e;
-      // trim the type
-      pn_atoms_ltrim(atoms, 1);
-
-      for (int i = 0; i < count; i++)
-      {
-        e = pn_encode_value(bytes, atoms, atype);
-        if (e) return e;
-      }
-
-      // backfill size
-      size_t size = bytes->start - start - 4;
-      pn_bytes_t size_bytes = {4, start};
-      pn_bytes_writef32(&size_bytes, size);
-      return 0;
-    }
-  case PN_LIST:
-  case PN_MAP:
-    {
-      char *start = bytes->start;
-      // we'll backfill the size later
-      if (bytes->size < 4) return PN_OVERFLOW;
-      pn_bytes_ltrim(bytes, 4);
-      size_t count = atom->u.count;
-      e = pn_bytes_writef32(bytes, count);
-      if (e) return e;
-
-      for (int i = 0; i < count; i++)
-      {
-        e = pn_encode_atom(bytes, atoms);
-        if (e) return e;
-      }
-
-      // backfill size
-      size_t size = bytes->start - start - 4;
-      pn_bytes_t size_bytes = {4, start};
-      pn_bytes_writef32(&size_bytes, size);
-      return 0;
-    }
-  default:
-    pn_fatal("atom has no value: %u", atom->u.type);
-    return PN_ARG_ERR;
+    int e = pn_bytes_writef32(bytes, value->size);
+    if (e) return e;
+    memmove(bytes->start, value->start, value->size);
+    pn_bytes_ltrim(bytes, value->size);
+    return 0;
   }
 }
 
@@ -1095,6 +972,8 @@ typedef struct {
   bool data;
   size_t data_offset;
   size_t data_size;
+  char *start;
+  bool small;
 } pn_node_t;
 
 struct pn_data_t {
@@ -2153,17 +2032,195 @@ int pn_data_as_atoms(pn_data_t *data, pn
   return 0;
 }
 
-ssize_t pn_data_encode(pn_data_t *data, char *bytes, size_t size)
+static uint8_t pn_node2code(pn_node_t *node)
 {
-  pn_iatom_t atoms[data->size + data->extras];
+  switch (node->atom.type) {
+  case PN_ULONG:
+    if (node->atom.u.as_ulong < 256) {
+      return PNE_SMALLULONG;
+    } else {
+      return PNE_ULONG;
+    }
+  case PN_UINT:
+    if (node->atom.u.as_uint < 256) {
+      return PNE_SMALLUINT;
+    } else {
+      return PNE_UINT;
+    }
+  case PN_BOOL:
+    if (node->atom.u.as_bool) {
+      return PNE_TRUE;
+    } else {
+      return PNE_FALSE;
+    }
+  case PN_STRING:
+    if (node->atom.u.as_string.size < 256) {
+      return PNE_STR8_UTF8;
+    } else {
+      return PNE_STR32_UTF8;
+    }
+  case PN_SYMBOL:
+    if (node->atom.u.as_symbol.size < 256) {
+      return PNE_SYM8;
+    } else {
+      return PNE_SYM32;
+    }
+  case PN_BINARY:
+    if (node->atom.u.as_binary.size < 256) {
+      return PNE_VBIN8;
+    } else {
+      return PNE_VBIN32;
+    }
+  default:
+    return pn_type2code(node->atom.type);
+  }
+}
 
-  pn_atoms_t latoms = {.size=data->size + data->extras, .start=atoms};
-  pn_data_as_atoms(data, &latoms);
+static int pn_data_encode_node(pn_data_t *data, pn_node_t *parent, pn_node_t 
*node,
+                               pn_bytes_t *bytes)
+{
+  int err;
+  pn_iatom_t *atom = &node->atom;
+  uint8_t code;
+  conv_t c;
+
+  if (parent && parent->atom.type == PN_ARRAY) {
+    code = pn_type2code(parent->type);
+    if (!node->prev || (node->prev && parent->described && !pn_data_node(data, 
node->prev)->prev)) {
+      err = pn_bytes_writef8(bytes, code);
+      if (err) return err;
+    }
+  } else {
+    code = pn_node2code(node);
+    err = pn_bytes_writef8(bytes, code);
+    if (err) return err;
+  }
+
+  switch (code) {
+  case PNE_DESCRIPTOR:
+  case PNE_NULL:
+  case PNE_TRUE:
+  case PNE_FALSE: return 0;
+  case PNE_BOOLEAN: return pn_bytes_writef8(bytes, atom->u.as_bool);
+  case PNE_UBYTE: return pn_bytes_writef8(bytes, atom->u.as_ubyte);
+  case PNE_BYTE: return pn_bytes_writef8(bytes, atom->u.as_byte);
+  case PNE_USHORT: return pn_bytes_writef16(bytes, atom->u.as_ushort);
+  case PNE_SHORT: return pn_bytes_writef16(bytes, atom->u.as_short);
+  case PNE_UINT0: return 0;
+  case PNE_SMALLUINT: return pn_bytes_writef8(bytes, atom->u.as_uint);
+  case PNE_UINT: return pn_bytes_writef32(bytes, atom->u.as_uint);
+  case PNE_SMALLINT: pn_bytes_writef8(bytes, atom->u.as_int);
+  case PNE_INT: return pn_bytes_writef32(bytes, atom->u.as_int);
+  case PNE_UTF32: return pn_bytes_writef32(bytes, atom->u.as_char);
+  case PNE_ULONG: return pn_bytes_writef64(bytes, atom->u.as_ulong);
+  case PNE_SMALLULONG: return pn_bytes_writef8(bytes, atom->u.as_ulong);
+  case PNE_LONG: return pn_bytes_writef64(bytes, atom->u.as_long);
+  case PNE_MS64: return pn_bytes_writef64(bytes, atom->u.as_timestamp);
+  case PNE_FLOAT: c.f = atom->u.as_float; return pn_bytes_writef32(bytes, c.i);
+  case PNE_DOUBLE: c.d = atom->u.as_double; return pn_bytes_writef64(bytes, 
c.l);
+  case PNE_DECIMAL32: return pn_bytes_writef32(bytes, atom->u.as_decimal32);
+  case PNE_DECIMAL64: return pn_bytes_writef64(bytes, atom->u.as_decimal64);
+  case PNE_DECIMAL128: return pn_bytes_writef128(bytes, 
atom->u.as_decimal128.bytes);
+  case PNE_UUID: return pn_bytes_writef128(bytes, atom->u.as_uuid.bytes);
+  case PNE_VBIN8: return pn_bytes_writev8(bytes, &atom->u.as_binary);
+  case PNE_VBIN32: return pn_bytes_writev32(bytes, &atom->u.as_binary);
+  case PNE_STR8_UTF8: return pn_bytes_writev8(bytes, &atom->u.as_string);
+  case PNE_STR32_UTF8: return pn_bytes_writev32(bytes, &atom->u.as_string);
+  case PNE_SYM8: return pn_bytes_writev8(bytes, &atom->u.as_symbol);
+  case PNE_SYM32: return pn_bytes_writev32(bytes, &atom->u.as_symbol);
+  case PNE_ARRAY32:
+    node->start = bytes->start;
+    node->small = false;
+    // we'll backfill the size on exit
+    if (bytes->size < 4) return PN_OVERFLOW;
+    pn_bytes_ltrim(bytes, 4);
+
+    err = pn_bytes_writef32(bytes, node->described ? node->children - 1 : 
node->children);
+    if (err) return err;
+
+    if (node->described) {
+      err = pn_bytes_writef8(bytes, 0);
+      if (err) return err;
+    }
+    return 0;
+  case PNE_LIST32:
+  case PNE_MAP32:
+    node->start = bytes->start;
+    node->small = false;
+    // we'll backfill the size later
+    if (bytes->size < 4) return PN_OVERFLOW;
+    pn_bytes_ltrim(bytes, 4);
+    return pn_bytes_writef32(bytes, node->children);
+  default:
+    return pn_error_format(data->error, PN_ERR, "unrecognized encoding: %u", 
code);
+  }
+}
+
+static int pn_data_encode_node_exit(pn_data_t *data, pn_node_t *node,
+                                    pn_bytes_t *bytes)
+{
+  switch (node->atom.type) {
+  case PN_ARRAY:
+    if ((node->described && node->children == 1) ||
+        (!node->described && node->children == 0)) {
+      int err = pn_bytes_writef8(bytes, pn_type2code(node->type));
+      if (err) return err;
+    }
+  case PN_LIST:
+  case PN_MAP:
+    if (node->small) {
+      // backfill size
+      size_t size = bytes->start - node->start - 1;
+      pn_bytes_t size_bytes = {1, node->start};
+      return pn_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_bytes_writef32(&size_bytes, size);
+    }
+  default:
+    return 0;
+  }
+}
+
+ssize_t pn_data_encode(pn_data_t *data, char *bytes, size_t size)
+{
   pn_bytes_t lbytes = pn_bytes(size, bytes);
 
-  int err = pn_encode_atoms(&lbytes, &latoms);
-  if (err) return err;
-  return lbytes.size;
+  pn_node_t *node = data->size ? pn_data_node(data, 1) : NULL;
+  while (node) {
+    pn_node_t *parent = pn_data_node(data, node->parent);
+
+    int err = pn_data_encode_node(data, parent, node, &lbytes);
+    if (err) return err;
+
+    size_t next = 0;
+    if (node->down) {
+      next = node->down;
+    } else if (node->next) {
+      err = pn_data_encode_node_exit(data, node, &lbytes);
+      if (err) return err;
+      next = node->next;
+    } else {
+      err = pn_data_encode_node_exit(data, node, &lbytes);
+      if (err) return err;
+      while (parent) {
+        err = pn_data_encode_node_exit(data, parent, &lbytes);
+        if (err) return err;
+        if (parent->next) {
+          next = parent->next;
+          break;
+        } else {
+          parent = pn_data_node(data, parent->parent);
+        }
+      }
+    }
+
+    node = pn_data_node(data, next);
+  }
+
+  return size - lbytes.size;
 }
 
 int pn_data_parse_atoms(pn_data_t *data, pn_atoms_t atoms, int offset, int 
limit)



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to