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/03/08 19:33:47 UTC

svn commit: r1298498 [3/3] - in /qpid/proton/proton-c: ./ include/ include/proton/ mllib/ src/ src/codec/ src/engine/ src/framing/ src/types/

Added: qpid/proton/proton-c/src/types/array.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/array.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/array.c (added)
+++ qpid/proton/proton-c/src/types/array.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,156 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/util.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include "../codec/encodings.h"
+#include "value-internal.h"
+
+static char type_to_code(enum TYPE type)
+{
+  switch (type)
+  {
+  case EMPTY: return 'n';
+  case BYTE: return 'b';
+  case UBYTE: return 'B';
+  case SHORT: return 'h';
+  case USHORT: return 'H';
+  case INT: return 'i';
+  case UINT: return 'I';
+  case LONG: return 'l';
+  case ULONG: return 'L';
+  case FLOAT: return 'f';
+  case DOUBLE: return 'd';
+  case CHAR: return 'C';
+  case STRING: return 'S';
+  case BINARY: return 'z';
+  case LIST: return 't';
+  case MAP: return 'm';
+  default: return -1;
+  }
+}
+
+static uint8_t type_to_amqp_code(enum TYPE type)
+{
+  switch (type)
+  {
+  case EMPTY: return PNE_NULL;
+  case BOOLEAN: return PNE_BOOLEAN;
+  case BYTE: return PNE_BYTE;
+  case UBYTE: return PNE_UBYTE;
+  case SHORT: return PNE_SHORT;
+  case USHORT: return PNE_USHORT;
+  case INT: return PNE_INT;
+  case UINT: return PNE_UINT;
+  case CHAR: return PNE_UTF32;
+  case LONG: return PNE_LONG;
+  case ULONG: return PNE_ULONG;
+  case FLOAT: return PNE_FLOAT;
+  case DOUBLE: return PNE_DOUBLE;
+  case STRING: return PNE_STR32_UTF8;
+  case BINARY: return PNE_VBIN32;
+  case LIST: return PNE_LIST32;
+  case MAP: return PNE_MAP32;
+  case ARRAY: return PNE_ARRAY32;
+  default:
+    pn_fatal("no amqp code for type: %i", type);
+    return -1;
+  }
+}
+
+pn_array_t *pn_array(enum TYPE type, int capacity)
+{
+  pn_array_t *l = malloc(sizeof(pn_array_t) + capacity*sizeof(pn_value_t));
+  if (l) {
+    l->type = type;
+    l->capacity = capacity;
+    l->size = 0;
+  }
+  return l;
+}
+
+void pn_free_array(pn_array_t *a)
+{
+  free(a);
+}
+
+void pn_visit_array(pn_array_t *a, void (*visitor)(pn_value_t))
+{
+  for (int i = 0; i < a->size; i++)
+  {
+    pn_visit(a->values[i], visitor);
+  }
+}
+
+size_t pn_format_sizeof_array(pn_array_t *array)
+{
+  size_t result = 4;
+  for (int i = 0; i < array->size; i++)
+  {
+    result += pn_format_sizeof(array->values[i]) + 2;
+  }
+  return result;
+}
+
+int pn_format_array(char **pos, char *limit, pn_array_t *array)
+{
+  int e;
+  if ((e = pn_fmt(pos, limit, "@%c[", type_to_code(array->type)))) return e;
+  if ((e = pn_format_value(pos, limit, array->values, array->size))) return e;
+  if ((e = pn_fmt(pos, limit, "]"))) return e;
+  return 0;
+}
+
+size_t pn_encode_sizeof_array(pn_array_t *array)
+{
+  size_t result = 9;
+  for (int i = 0; i < array->size; i++)
+  {
+    // XXX: this is wrong, need to compensate for code
+    result += pn_encode_sizeof(array->values[i]);
+  }
+  return result;
+}
+
+size_t pn_encode_array(pn_array_t *array, char *out)
+{
+  // code
+  out[0] = (uint8_t) PNE_ARRAY32;
+  // size will be backfilled
+  // count
+  *((uint32_t *) (out + 5)) = htonl(array->size);
+  // element code
+  out[9] = (uint8_t) type_to_amqp_code(array->type);
+
+  char *vout = out + 10;
+  for (int i = 0; i < array->size; i++)
+  {
+    char *codeptr = vout - 1;
+    char codeval = *codeptr;
+    vout += pn_encode(array->values[i], vout-1) - 1;
+    *codeptr = codeval;
+  }
+
+  // backfill size
+  *((uint32_t *) (out + 1)) = htonl(vout - out - 5);
+  return vout - out;
+}

Added: qpid/proton/proton-c/src/types/binary.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/binary.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/binary.c (added)
+++ qpid/proton/proton-c/src/types/binary.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,101 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/codec.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "value-internal.h"
+
+pn_binary_t *pn_binary(char *bytes, size_t size)
+{
+  pn_binary_t *bin = malloc(sizeof(pn_binary_t) + size);
+  bin->size = size;
+  memmove(bin->bytes, bytes, size);
+  return bin;
+}
+
+void pn_free_binary(pn_binary_t *b)
+{
+  free(b);
+}
+
+size_t pn_binary_size(pn_binary_t *b)
+{
+  return b->size;
+}
+
+char *pn_binary_bytes(pn_binary_t *b)
+{
+  return b->bytes;
+}
+
+uintptr_t pn_hash_binary(pn_binary_t *b)
+{
+  uintptr_t hash = 0;
+  for (int i = 0; i < b->size; i++)
+  {
+    hash = 31*hash + b->bytes[i];
+  }
+  return hash;
+}
+
+int pn_compare_binary(pn_binary_t *a, pn_binary_t *b)
+{
+  if (a->size == b->size)
+    return memcmp(a->bytes, b->bytes, a->size);
+  else
+    return b->size - a->size;
+}
+
+pn_binary_t *pn_binary_dup(pn_binary_t *b)
+{
+  return pn_binary(b->bytes, b->size);
+}
+
+int pn_format_binary(char **pos, char *limit, pn_binary_t *binary)
+{
+  if (!binary) return pn_fmt(pos, limit, "(null)");
+
+  for (int i = 0; i < binary->size; i++)
+  {
+    uint8_t b = binary->bytes[i];
+    if (isprint(b)) {
+      if (*pos < limit) {
+        **pos = b;
+        *pos += 1;
+      } else {
+        return -1;
+      }
+    } else {
+      if (limit - *pos > 4)
+      {
+        sprintf(*pos, "\\x%.2x", b);
+        *pos += 4;
+      } else {
+        return -1;
+      }
+    }
+  }
+
+  return 0;
+}

Added: qpid/proton/proton-c/src/types/decode.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/decode.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/decode.c (added)
+++ qpid/proton/proton-c/src/types/decode.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,272 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/codec.h>
+#include <iconv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "../codec/encodings.h"
+#include "value-internal.h"
+
+static enum TYPE amqp_code_to_type(uint8_t code)
+{
+  switch (code)
+  {
+  case PNE_NULL: return EMPTY;
+    //  case PNE_TRUE:
+    //  case PNE_FALSE:
+    //  case PNE_BOOLEAN: return BOOLEAN;
+  case PNE_UBYTE: return UBYTE;
+  case PNE_BYTE: return BYTE;
+  case PNE_USHORT: return USHORT;
+  case PNE_SHORT: return SHORT;
+  case PNE_UINT:
+  case PNE_UINT0: return UINT;
+  case PNE_INT: return INT;
+  case PNE_FLOAT: return FLOAT;
+  case PNE_ULONG0:
+  case PNE_ULONG: return ULONG;
+  case PNE_LONG: return LONG;
+  case PNE_DOUBLE: return DOUBLE;
+  case PNE_VBIN8:
+  case PNE_VBIN32: return BINARY;
+  case PNE_STR8_UTF8:
+  case PNE_STR32_UTF8: return STRING;
+    //  case PNE_SYM8:
+    //  case PNE_SYM32: return SYMBOL;
+  case PNE_LIST0:
+  case PNE_LIST8:
+  case PNE_LIST32: return LIST;
+  case PNE_ARRAY8:
+  case PNE_ARRAY32: return ARRAY;
+  case PNE_MAP8:
+  case PNE_MAP32: return MAP;
+  }
+  return -1;
+}
+
+struct pn_decode_context_frame_st {
+  size_t count;
+  size_t limit;
+  pn_value_t *values;
+};
+
+struct pn_decode_context_st {
+  size_t depth;
+  struct pn_decode_context_frame_st frames[1024];
+};
+
+#define CTX_CAST(ctx) ((struct pn_decode_context_st *) (ctx))
+
+static void push_frame(void *ptr, pn_value_t *values, size_t limit)
+{
+  struct pn_decode_context_st *ctx = CTX_CAST(ptr);
+  struct pn_decode_context_frame_st *frm = &ctx->frames[ctx->depth++];
+  frm->count = 0;
+  frm->limit = limit;
+  frm->values = values;
+}
+
+static struct pn_decode_context_frame_st *frame(void *ptr)
+{
+  struct pn_decode_context_st *ctx = CTX_CAST(ptr);
+  return &ctx->frames[ctx->depth-1];
+}
+
+static void autopop(void *ptr)
+{
+  struct pn_decode_context_st *ctx = CTX_CAST(ptr);
+  struct pn_decode_context_frame_st *frm = frame(ptr);
+  while (frm->limit && frm->count == frm->limit) {
+    ctx->depth--;
+    frm = frame(ptr);
+  }
+}
+
+static void pop_frame(void *ptr)
+{
+  autopop(ptr);
+  struct pn_decode_context_st *ctx = CTX_CAST(ptr);
+  ctx->depth--;
+}
+
+static pn_value_t *next_value(void *ptr)
+{
+  autopop(ptr);
+  struct pn_decode_context_frame_st *frm = frame(ptr);
+  pn_value_t *result = &frm->values[frm->count++];
+  return result;
+}
+
+static pn_value_t *curr_value(void *ptr)
+{
+  struct pn_decode_context_st *ctx = CTX_CAST(ptr);
+  struct pn_decode_context_frame_st *frm = &ctx->frames[ctx->depth-1];
+  return &frm->values[frm->count - 1];
+}
+
+void pn_decode_null(void *ctx) {
+  pn_value_t *value = next_value(ctx);
+  value->type = EMPTY;
+}
+void pn_decode_bool(void *ctx, bool v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = BOOLEAN;
+  value->u.as_boolean = v;
+}
+void pn_decode_ubyte(void *ctx, uint8_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = UBYTE;
+  value->u.as_ubyte = v;
+}
+void pn_decode_byte(void *ctx, int8_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = BYTE;
+  value->u.as_byte = v;
+}
+void pn_decode_ushort(void *ctx, uint16_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = USHORT;
+  value->u.as_ushort = v;
+}
+void pn_decode_short(void *ctx, int16_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = SHORT;
+  value->u.as_short = v;
+}
+void pn_decode_uint(void *ctx, uint32_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = UINT;
+  value->u.as_uint = v;
+}
+void pn_decode_int(void *ctx, int32_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = INT;
+  value->u.as_int = v;
+}
+void pn_decode_float(void *ctx, float f) {
+  pn_value_t *value = next_value(ctx);
+  value->type = FLOAT;
+  value->u.as_float = f;
+}
+void pn_decode_ulong(void *ctx, uint64_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = ULONG;
+  value->u.as_ulong = v;
+}
+void pn_decode_long(void *ctx, int64_t v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = LONG;
+  value->u.as_long = v;
+}
+void pn_decode_double(void *ctx, double v) {
+  pn_value_t *value = next_value(ctx);
+  value->type = DOUBLE;
+  value->u.as_double = v;
+}
+void pn_decode_binary(void *ctx, size_t size, char *bytes) {
+  pn_value_t *value = next_value(ctx);
+  value->type = BINARY;
+  value->u.as_binary = pn_binary(bytes, size);
+}
+void pn_decode_utf8(void *ctx, size_t size, char *bytes) {
+  pn_value_t *value = next_value(ctx);
+  value->type = STRING;
+  size_t remaining = (size+1)*sizeof(wchar_t);
+  wchar_t buf[size+1];
+  iconv_t cd = iconv_open("WCHAR_T", "UTF-8");
+  wchar_t *out = buf;
+  size_t n = iconv(cd, &bytes, &size, (char **)&out, &remaining);
+  if (n == -1)
+  {
+    perror("pn_decode_utf8");
+  }
+  *out = L'\0';
+  iconv_close(cd);
+  value->u.as_string = pn_string(buf);
+}
+void pn_decode_symbol(void *ctx, size_t size, char *bytes) {
+  //  pn_value_t *value = next_value(ctx);
+  //  value->type = SYMBOL;
+  //  value->u.as_symbol = {.size = size, .bytes = bytes};
+}
+
+void pn_decode_start_array(void *ctx, size_t count, uint8_t code) {
+  pn_value_t *value = next_value(ctx);
+  value->type = ARRAY;
+  value->u.as_array = pn_array(amqp_code_to_type(code), count);
+  push_frame(ctx, value->u.as_array->values, 0);
+}
+void pn_decode_stop_array(void *ctx, size_t count, uint8_t code) {
+  pop_frame(ctx);
+  pn_value_t *value = curr_value(ctx);
+  value->u.as_array->size = count;
+}
+
+void pn_decode_start_list(void *ctx, size_t count) {
+  pn_value_t *value = next_value(ctx);
+  value->type = LIST;
+  value->u.as_list = pn_list(count);
+  push_frame(ctx, value->u.as_list->values, 0);
+}
+
+void pn_decode_stop_list(void *ctx, size_t count) {
+  pop_frame(ctx);
+  pn_value_t *value = curr_value(ctx);
+  value->u.as_list->size = count;
+}
+
+void pn_decode_start_map(void *ctx, size_t count) {
+  pn_value_t *value = next_value(ctx);
+  value->type = MAP;
+  value->u.as_map = pn_map(count/2);
+  push_frame(ctx, value->u.as_map->pairs, 0);
+}
+
+void pn_decode_stop_map(void *ctx, size_t count) {
+  pop_frame(ctx);
+  pn_value_t *value = curr_value(ctx);
+  value->u.as_map->size = count/2;
+}
+
+void pn_decode_start_descriptor(void *ctx) {
+  pn_value_t *value = next_value(ctx);
+  value->type = TAG;
+  value->u.as_tag = pn_tag(EMPTY_VALUE, EMPTY_VALUE);
+  push_frame(ctx, &value->u.as_tag->descriptor, 0);
+}
+
+void pn_decode_stop_descriptor(void *ctx) {
+  pop_frame(ctx);
+  pn_value_t *value = curr_value(ctx);
+  push_frame(ctx, &value->u.as_tag->value, 1);
+}
+
+pn_data_callbacks_t *pn_decoder = &PN_DATA_CALLBACKS(pn_decode);
+
+ssize_t pn_decode(pn_value_t *v, char *bytes, size_t n)
+{
+  struct pn_decode_context_st ctx = {.depth = 0};
+  push_frame(&ctx, v, 0);
+  ssize_t read = pn_read_datum(bytes, n, pn_decoder, &ctx);
+  return read;
+}

Added: qpid/proton/proton-c/src/types/list.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/list.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/list.c (added)
+++ qpid/proton/proton-c/src/types/list.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,212 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/codec.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "value-internal.h"
+
+pn_list_t *pn_list(int capacity)
+{
+  pn_list_t *l = malloc(sizeof(pn_list_t) + capacity*sizeof(pn_value_t));
+  if (l) {
+    l->capacity = capacity;
+    l->size = 0;
+  }
+  return l;
+}
+
+void pn_free_list(pn_list_t *l)
+{
+  free(l);
+}
+
+void pn_visit_list(pn_list_t *l, void (*visitor)(pn_value_t))
+{
+  for (int i = 0; i < l->size; i++)
+  {
+    pn_visit(l->values[i], visitor);
+  }
+}
+
+int pn_list_size(pn_list_t *l)
+{
+  return l->size;
+}
+
+pn_value_t pn_list_get(pn_list_t *l, int index)
+{
+  if (index < l->size)
+    return l->values[index];
+  else
+    return EMPTY_VALUE;
+}
+
+pn_value_t pn_list_set(pn_list_t *l, int index, pn_value_t v)
+{
+  pn_value_t r = l->values[index];
+  l->values[index] = v;
+  return r;
+}
+
+pn_value_t pn_list_pop(pn_list_t *l, int index)
+{
+  int i, n = l->size;
+  pn_value_t v = l->values[index];
+  for (i = index; i < n - 1; i++)
+    l->values[i] = l->values[i+1];
+  l->size--;
+  return v;
+}
+
+int pn_list_add(pn_list_t *l, pn_value_t v)
+{
+  if (l->capacity <= l->size) {
+    fprintf(stderr, "wah!\n");
+    return -1;
+  }
+
+  l->values[l->size++] = v;
+  return 0;
+}
+
+int pn_list_extend(pn_list_t *l, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  int n = pn_vscan(l->values + l->size, fmt, ap);
+  va_end(ap);
+  if (n > 0) l->size += n;
+  return n;
+}
+
+int pn_list_index(pn_list_t *l, pn_value_t v)
+{
+  int i, n = l->size;
+  for (i = 0; i < n; i++)
+    if (pn_compare_value(v, l->values[i]) == 0)
+      return i;
+  return -1;
+}
+
+bool pn_list_remove(pn_list_t *l, pn_value_t v)
+{
+  int i = pn_list_index(l, v);
+  if (i >= 0) {
+    pn_list_pop(l, i);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+int pn_list_fill(pn_list_t *l, pn_value_t v, int n)
+{
+  int i, e;
+
+  for (i = 0; i < n; i++)
+    if ((e = pn_list_add(l, v))) return e;
+
+  return 0;
+}
+
+void pn_list_clear(pn_list_t *l)
+{
+  l->size = 0;
+}
+
+static int min(int a, int b)
+{
+  if (a < b)
+    return a;
+  else
+    return b;
+}
+
+size_t pn_format_sizeof_list(pn_list_t *list)
+{
+  size_t result = 2;
+  for (int i = 0; i < list->size; i++) {
+    result += pn_format_sizeof(list->values[i]) + 2;
+  }
+  return result;
+}
+
+int pn_format_list(char **pos, char *limit, pn_list_t *list)
+{
+  int e;
+  if ((e = pn_fmt(pos, limit, "["))) return e;
+  if ((e = pn_format_value(pos, limit, list->values, list->size))) return e;
+  if ((e = pn_fmt(pos, limit, "]"))) return e;
+  return 0;
+}
+
+uintptr_t pn_hash_list(pn_list_t *list)
+{
+  int i, n = list->size;
+  uintptr_t hash = 1;
+
+  for (i = 0; i < n; i++)
+  {
+    hash = 31*hash + pn_hash_value(pn_list_get(list, i));
+  }
+
+  return hash;
+}
+
+int pn_compare_list(pn_list_t *a, pn_list_t *b)
+{
+  int i, n = min(a->size, b->size);
+  int c;
+
+  for (i = 0; i < n; i++)
+  {
+    c = pn_compare_value(pn_list_get(a, i), pn_list_get(b, i));
+    if (!c)
+      return c;
+  }
+
+  return 0;
+}
+
+size_t pn_encode_sizeof_list(pn_list_t *l)
+{
+  size_t result = 9;
+  for (int i = 0; i < l->size; i++)
+  {
+    result += pn_encode_sizeof(l->values[i]);
+  }
+  return result;
+}
+
+size_t pn_encode_list(pn_list_t *l, char *out)
+{
+  char *old = out;
+  char *start;
+  // XXX
+  pn_write_start(&out, out + 1024, &start);
+  for (int i = 0; i < l->size; i++)
+  {
+    out += pn_encode(l->values[i], out);
+  }
+  pn_write_list(&out, out + 1024, start, l->size);
+  return out - old;
+}

Added: qpid/proton/proton-c/src/types/map.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/map.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/map.c (added)
+++ qpid/proton/proton-c/src/types/map.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,229 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/codec.h>
+#include <string.h>
+#include <stdlib.h>
+#include "value-internal.h"
+
+pn_map_t *pn_map(int capacity)
+{
+  pn_map_t *map = malloc(sizeof(pn_map_t) + 2*capacity*sizeof(pn_value_t));
+  map->capacity = capacity;
+  map->size = 0;
+  return map;
+}
+
+void pn_free_map(pn_map_t *m)
+{
+  free(m);
+}
+
+pn_value_t pn_map_key(pn_map_t *map, int index)
+{
+  return map->pairs[2*index];
+}
+
+pn_value_t pn_map_value(pn_map_t *map, int index)
+{
+  return map->pairs[2*index+1];
+}
+
+void pn_visit_map(pn_map_t *m, void (*visitor)(pn_value_t))
+{
+  for (int i = 0; i < m->size; i++)
+  {
+    pn_visit(pn_map_key(m, i), visitor);
+    pn_visit(pn_map_value(m, i), visitor);
+  }
+}
+
+size_t pn_format_sizeof_map(pn_map_t *map)
+{
+  size_t result = 2;
+  for (int i = 0; i < map->size; i++)
+  {
+    pn_value_t key = pn_map_key(map, i);
+    pn_value_t value = pn_map_value(map, i);
+    result += pn_format_sizeof(key) + 2 + pn_format_sizeof(value) + 2;
+  }
+  return result;
+}
+
+int pn_format_map(char **pos, char *limit, pn_map_t *map)
+{
+  bool first = true;
+  int i, e;
+  if ((e = pn_fmt(pos, limit, "{"))) return e;
+  for (i = 0; i < map->size; i++)
+  {
+    pn_value_t key = pn_map_key(map, i);
+    pn_value_t value = pn_map_value(map, i);
+    if (first) first = false;
+    else if ((e = pn_fmt(pos, limit, ", "))) return e;
+    if ((e = pn_format_value(pos, limit, &key, 1))) return e;
+    if ((e = pn_fmt(pos, limit, ": "))) return e;
+    if ((e = pn_format_value(pos, limit, &value, 1))) return e;
+  }
+  if ((e = pn_fmt(pos, limit, "}"))) return e;
+  return 0;
+}
+
+uintptr_t pn_hash_map(pn_map_t *map)
+{
+  uintptr_t hash = 0;
+  int i;
+  for (i = 0; i < map->size; i++)
+  {
+    hash += (pn_hash_value(pn_map_key(map, i)) ^
+             pn_hash_value(pn_map_value(map, i)));
+  }
+  return hash;
+}
+
+static bool has_entry(pn_map_t *m, pn_value_t key, pn_value_t value)
+{
+  int i;
+  for (i = 0; i < m->size; i++)
+  {
+    if (!pn_compare_value(pn_map_key(m, i), key) &&
+        !pn_compare_value(pn_map_value(m, i), value))
+      return true;
+  }
+
+  return false;
+}
+
+int pn_compare_map(pn_map_t *a, pn_map_t *b)
+{
+  int i;
+
+  if (a->size != b->size)
+    return b->size - a->size;
+
+  for (i = 0; i < a->size; i++)
+    if (!has_entry(b, pn_map_key(a, i), pn_map_value(a, i)))
+      return -1;
+
+  for (i = 0; i < b->size; i++)
+    if (!has_entry(a, pn_map_key(b, i), pn_map_value(b, i)))
+      return -1;
+
+  return 0;
+}
+
+bool pn_map_has(pn_map_t *map, pn_value_t key)
+{
+  for (int i = 0; i < map->size; i++)
+  {
+    if (!pn_compare_value(key, pn_map_key(map, i)))
+      return true;
+  }
+
+  return false;
+}
+
+pn_value_t pn_map_get(pn_map_t *map, pn_value_t key)
+{
+  for (int i = 0; i < map->size; i++)
+  {
+    if (!pn_compare_value(key, pn_map_key(map, i)))
+      return pn_map_value(map, i);
+  }
+
+  return EMPTY_VALUE;
+}
+
+int pn_map_set(pn_map_t *map, pn_value_t key, pn_value_t value)
+{
+  for (int i = 0; i < map->size; i++)
+  {
+    if (!pn_compare_value(key, pn_map_key(map, i)))
+    {
+      map->pairs[2*i + 1] = value;
+      return 0;
+    }
+  }
+
+  if (map->size < map->capacity)
+  {
+    map->pairs[2*map->size] = key;
+    map->pairs[2*map->size+1] = value;
+    map->size++;
+    return 0;
+  }
+  else
+  {
+    return -1;
+  }
+}
+
+pn_value_t pn_map_pop(pn_map_t *map, pn_value_t key)
+{
+  for (int i = 0; i < map->size; i++)
+  {
+    if (!pn_compare_value(key, pn_map_key(map, i)))
+    {
+      pn_value_t result = pn_map_value(map, i);
+      memmove(&map->pairs[2*i], &map->pairs[2*(i+1)],
+              (map->size - i - 1)*2*sizeof(pn_value_t));
+      map->size--;
+      return result;
+    }
+  }
+
+  return EMPTY_VALUE;
+}
+
+int pn_map_size(pn_map_t *map)
+{
+  return map->size;
+}
+
+int pn_map_capacity(pn_map_t *map)
+{
+  return map->capacity;
+}
+
+size_t pn_encode_sizeof_map(pn_map_t *m)
+{
+  size_t result = 0;
+  for (int i = 0; i < 2*m->size; i++)
+  {
+    result += pn_encode_sizeof(m->pairs[i]);
+  }
+  return result;
+}
+
+size_t pn_encode_map(pn_map_t *m, char *out)
+{
+  char *old = out;
+  char *start;
+  int count = 2*m->size;
+  // XXX
+  pn_write_start(&out, out + 1024, &start);
+  for (int i = 0; i < count; i++)
+  {
+    out += pn_encode(m->pairs[i], out);
+  }
+  pn_write_map(&out, out + 1024, start, m->size);
+  return out - old;
+}

Added: qpid/proton/proton-c/src/types/string.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/string.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/string.c (added)
+++ qpid/proton/proton-c/src/types/string.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,68 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/codec.h>
+#include <string.h>
+#include <stdlib.h>
+#include "value-internal.h"
+
+pn_string_t *pn_string(wchar_t *wcs)
+{
+  size_t size = wcslen(wcs);
+  pn_string_t *str = malloc(sizeof(pn_string_t) + (size+1)*sizeof(wchar_t));
+  str->size = size;
+  wcscpy(str->wcs, wcs);
+  return str;
+}
+
+void pn_free_string(pn_string_t *str)
+{
+  free(str);
+}
+
+size_t pn_string_size(pn_string_t *str)
+{
+  return str->size;
+}
+
+wchar_t *pn_string_wcs(pn_string_t *str)
+{
+  return str->wcs;
+}
+
+uintptr_t pn_hash_string(pn_string_t *s)
+{
+  wchar_t *c;
+  uintptr_t hash = 1;
+  for (c = s->wcs; *c; c++)
+  {
+    hash = 31*hash + *c;
+  }
+  return hash;
+}
+
+int pn_compare_string(pn_string_t *a, pn_string_t *b)
+{
+  if (a->size == b->size)
+    return wmemcmp(a->wcs, b->wcs, a->size);
+  else
+    return b->size - a->size;
+}

Added: qpid/proton/proton-c/src/types/value-internal.h
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/value-internal.h?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/value-internal.h (added)
+++ qpid/proton/proton-c/src/types/value-internal.h Thu Mar  8 18:33:46 2012
@@ -0,0 +1,56 @@
+#ifndef _PROTON_VALUE_INTERNAL_H
+#define _PROTON_VALUE_INTERNAL_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/value.h>
+
+struct pn_string_st {
+  size_t size;
+  wchar_t wcs[];
+};
+
+struct pn_binary_st {
+  size_t size;
+  char bytes[];
+};
+
+struct pn_array_st {
+  enum TYPE type;
+  size_t size;
+  size_t capacity;
+  pn_value_t values[];
+};
+
+struct pn_list_st {
+  size_t size;
+  size_t capacity;
+  pn_value_t values[];
+};
+
+struct pn_map_st {
+  size_t size;
+  size_t capacity;
+  pn_value_t pairs[];
+};
+
+#endif /* value-internal.h */

Added: qpid/proton/proton-c/src/types/value.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/types/value.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/types/value.c (added)
+++ qpid/proton/proton-c/src/types/value.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,810 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <proton/codec.h>
+#include <proton/util.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <iconv.h>
+#include <arpa/inet.h>
+#include "../codec/encodings.h"
+#include "value-internal.h"
+
+int pn_compare_value(pn_value_t a, pn_value_t b)
+{
+  if (a.type == b.type) {
+    switch (a.type)
+    {
+    case EMPTY:
+      return 0;
+    case BOOLEAN:
+      return b.u.as_boolean && a.u.as_boolean;
+    case UBYTE:
+      return b.u.as_ubyte - a.u.as_ubyte;
+    case USHORT:
+      return b.u.as_ushort - a.u.as_ushort;
+    case UINT:
+      return b.u.as_uint - a.u.as_uint;
+    case ULONG:
+      return b.u.as_ulong - a.u.as_ulong;
+    case BYTE:
+      return b.u.as_byte - a.u.as_byte;
+    case SHORT:
+      return b.u.as_short - a.u.as_short;
+    case INT:
+      return b.u.as_int - a.u.as_int;
+    case LONG:
+      return b.u.as_long - a.u.as_long;
+    case FLOAT:
+      return b.u.as_float - a.u.as_float;
+    case DOUBLE:
+      return b.u.as_double - a.u.as_double;
+    case CHAR:
+      return b.u.as_char - a.u.as_char;
+    case STRING:
+      return pn_compare_string(a.u.as_string, b.u.as_string);
+    case BINARY:
+      return pn_compare_binary(a.u.as_binary, b.u.as_binary);
+    case REF:
+      return (char *)b.u.as_ref - (char *)a.u.as_ref;
+    default:
+      pn_fatal("uncomparable: %s, %s", pn_aformat(a), pn_aformat(b));
+      return -1;
+    }
+  } else {
+    return b.type - a.type;
+  }
+}
+
+uintptr_t pn_hash_value(pn_value_t v)
+{
+  switch (v.type)
+  {
+  case EMPTY:
+    return 0;
+  case UBYTE:
+    return v.u.as_ubyte;
+  case USHORT:
+    return v.u.as_ushort;
+  case UINT:
+    return v.u.as_uint;
+  case ULONG:
+    return v.u.as_ulong;
+  case BYTE:
+    return v.u.as_byte;
+  case SHORT:
+    return v.u.as_short;
+  case INT:
+    return v.u.as_int;
+  case LONG:
+    return v.u.as_long;
+  case FLOAT:
+    return v.u.as_float;
+  case DOUBLE:
+    return v.u.as_double;
+  case CHAR:
+    return v.u.as_char;
+  case STRING:
+    return pn_hash_string(v.u.as_string);
+  case BINARY:
+    return pn_hash_binary(v.u.as_binary);
+  default:
+    return 0;
+  }
+}
+
+int scan_size(const char *str)
+{
+  int i, level = 0, size = 0;
+  for (i = 0; str[i]; i++)
+  {
+    switch (str[i])
+    {
+    case '@':
+      i++;
+      break;
+    case '(':
+    case '[':
+    case '{':
+      level++;
+      break;
+    case ')':
+    case ']':
+    case '}':
+      if (level == 0)
+        return size;
+      level--;
+      // fall through intentionally here
+    default:
+      if (level == 0) size++;
+      break;
+    }
+  }
+
+  return -1;
+}
+
+int pn_scan(pn_value_t *value, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  int n = pn_vscan(value, fmt, ap);
+  va_end(ap);
+  return n;
+}
+
+static enum TYPE code_to_type(char c)
+{
+  switch (c)
+  {
+  case 'n': return EMPTY;
+  case 'b': return BYTE;
+  case 'B': return UBYTE;
+  case 'h': return SHORT;
+  case 'H': return USHORT;
+  case 'i': return INT;
+  case 'I': return UINT;
+  case 'l': return LONG;
+  case 'L': return ULONG;
+  case 'f': return FLOAT;
+  case 'd': return DOUBLE;
+  case 'C': return CHAR;
+  case 'S': return STRING;
+  case 'z': return BINARY;
+  case 't': return LIST;
+  case 'm': return MAP;
+  default:
+    pn_fatal("unrecognized code: %c", c);
+    return -1;
+  }
+}
+
+typedef struct stack_frame_st {
+  pn_value_t *value;
+  int count;
+} stack_frame_t;
+
+int pn_vscan(pn_value_t *value, const char *fmt, va_list ap)
+{
+  stack_frame_t stack[strlen(fmt)];
+  int level = 0, count = 0;
+
+  for ( ; *fmt; fmt++)
+  {
+    if (level == 0)
+      count++;
+
+    switch (*fmt)
+    {
+    case 'n':
+      value->type = EMPTY;
+      break;
+    case 'b':
+      value->type = BYTE;
+      value->u.as_byte = va_arg(ap, int);
+      break;
+    case 'B':
+      value->type = UBYTE;
+      value->u.as_ubyte = va_arg(ap, unsigned int);
+      break;
+    case 'h':
+      value->type = SHORT;
+      value->u.as_short = va_arg(ap, int);
+      break;
+    case 'H':
+      value->type = USHORT;
+      value->u.as_ushort = va_arg(ap, unsigned int);
+      break;
+    case 'i':
+      value->type = INT;
+      value->u.as_int = va_arg(ap, int32_t);
+      break;
+    case 'I':
+      value->type = UINT;
+      value->u.as_uint = va_arg(ap, uint32_t);
+      break;
+    case 'l':
+      value->type = LONG;
+      value->u.as_long = va_arg(ap, int64_t);
+      break;
+    case 'L':
+      value->type = ULONG;
+      value->u.as_ulong = va_arg(ap, uint64_t);
+      break;
+    case 'f':
+      value->type = FLOAT;
+      value->u.as_float = va_arg(ap, double);
+      break;
+    case 'd':
+      value->type = DOUBLE;
+      value->u.as_double = va_arg(ap, double);
+      break;
+    case 'C':
+      value->type = CHAR;
+      value->u.as_char = va_arg(ap, wchar_t);
+      break;
+    case 'S':
+      value->type = STRING;
+      wchar_t *wcs = va_arg(ap, wchar_t *);
+      value->u.as_string = pn_string(wcs);
+      break;
+    case 'z':
+      value->type = BINARY;
+      size_t size = va_arg(ap, size_t);
+      char *bytes = va_arg(ap, char *);
+      value->u.as_binary = pn_binary(bytes, size);
+      break;
+    case '[':
+      stack[level] = (stack_frame_t) {value, scan_size(fmt+1)};
+      value->type = LIST;
+      value->u.as_list = pn_list(stack[level].count);
+      value->u.as_list->size = stack[level].count;
+      value = value->u.as_list->values;
+      level++;
+      continue;
+    case ']':
+      value = stack[--level].value;
+      break;
+    case '{':
+      stack[level] = (stack_frame_t) {value, scan_size(fmt+1)};
+      value->type = MAP;
+      value->u.as_map = pn_map(stack[level].count/2);
+      value->u.as_map->size = stack[level].count/2;
+      value = value->u.as_map->pairs;
+      level++;
+      continue;
+    case '}':
+      value = stack[--level].value;
+      break;
+    case '(':
+      // XXX: need to figure out how to detect missing descriptor value here
+      // XXX: also, decrementing count may not work when nested
+      value--;
+      count--;
+      pn_tag_t *tag = pn_tag(*value, EMPTY_VALUE);
+      value->type = TAG;
+      value->u.as_tag = tag;
+      stack[level++] = (stack_frame_t) {value, 0};
+      value = &value->u.as_tag->value;
+      continue;
+    case ')':
+      value = stack[--level].value;
+      break;
+    case '@':
+      value->type = ARRAY;
+      enum TYPE etype = code_to_type(*(++fmt));
+      stack[level] = (stack_frame_t) {value, scan_size(++fmt+1)};
+      value->u.as_array = pn_array(etype, stack[level].count);
+      value->u.as_array->size = stack[level].count;
+      value = value->u.as_array->values;
+      level++;
+      continue;
+    default:
+      fprintf(stderr, "unrecognized type: %c\n", *fmt);
+      return -1;
+    }
+
+    value++;
+  }
+
+  return count;
+}
+
+pn_value_t pn_value(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  pn_value_t value = pn_vvalue(fmt, ap);
+  va_end(ap);
+  return value;
+}
+
+pn_value_t pn_vvalue(const char *fmt, va_list ap)
+{
+  pn_value_t value;
+  pn_vscan(&value, fmt, ap);
+  return value;
+}
+
+pn_list_t *pn_to_list(pn_value_t v)
+{
+  return v.u.as_list;
+}
+
+pn_map_t *pn_to_map(pn_value_t v)
+{
+  return v.u.as_map;
+}
+
+pn_tag_t *pn_to_tag(pn_value_t v)
+{
+  return v.u.as_tag;
+}
+
+void *pn_to_ref(pn_value_t v)
+{
+  return v.u.as_ref;
+}
+
+pn_value_t pn_from_list(pn_list_t *l)
+{
+  return (pn_value_t) {.type = LIST, .u.as_list = l};
+}
+
+pn_value_t pn_from_map(pn_map_t *m)
+{
+  return (pn_value_t) {.type = MAP, .u.as_map = m};
+}
+
+pn_value_t pn_from_tag(pn_tag_t *t)
+{
+  return (pn_value_t) {.type = TAG, .u.as_tag = t};
+}
+
+pn_value_t pn_from_ref(void *r)
+{
+  return (pn_value_t) {.type = REF, .u.as_ref = r};
+}
+
+pn_value_t pn_from_binary(pn_binary_t *b)
+{
+  return (pn_value_t) {.type = BINARY, .u.as_binary = b};
+}
+
+int pn_fmt(char **pos, char *limit, const char *fmt, ...)
+{
+  va_list ap;
+  int result;
+  char *dst = *pos;
+  int n = limit - dst;
+  va_start(ap, fmt);
+  result = vsnprintf(dst, n, fmt, ap);
+  va_end(ap);
+  if (result >= n) {
+    *pos += n;
+    return -1;
+  } else if (result >= 0) {
+    *pos += result;
+    return 0;
+  } else {
+    // XXX: should convert error codes
+    return result;
+  }
+}
+
+int pn_format_value(char **pos, char *limit, pn_value_t *values, size_t n)
+{
+  int e;
+  for (int i = 0; i < n; i++)
+  {
+    if (i > 0 && (e = pn_fmt(pos, limit, ", "))) return e;
+
+    pn_value_t v = values[i];
+    switch (v.type)
+    {
+    case EMPTY:
+      if ((e = pn_fmt(pos, limit, "NULL"))) return e;
+      break;
+    case BOOLEAN:
+      if (v.u.as_boolean) {
+        if ((e = pn_fmt(pos, limit, "true"))) return e;
+      } else {
+        if ((e = pn_fmt(pos, limit, "false"))) return e;
+      }
+      break;
+    case BYTE:
+      if ((e = pn_fmt(pos, limit, "%hhi", v.u.as_byte))) return e;
+      break;
+    case UBYTE:
+      if ((e = pn_fmt(pos, limit, "%hhu", v.u.as_ubyte))) return e;
+      break;
+    case SHORT:
+      if ((e = pn_fmt(pos, limit, "%hi", v.u.as_short))) return e;
+      break;
+    case USHORT:
+      if ((e = pn_fmt(pos, limit, "%hu", v.u.as_ushort))) return e;
+      break;
+    case INT:
+      if ((e = pn_fmt(pos, limit, "%i", v.u.as_int))) return e;
+      break;
+    case UINT:
+      if ((e = pn_fmt(pos, limit, "%u", v.u.as_uint))) return e;
+      break;
+    case LONG:
+      if ((e = pn_fmt(pos, limit, "%lli", v.u.as_long))) return e;
+      break;
+    case ULONG:
+      if ((e = pn_fmt(pos, limit, "%llu", v.u.as_ulong))) return e;
+      break;
+    case FLOAT:
+      if ((e = pn_fmt(pos, limit, "%f", v.u.as_float))) return e;
+      break;
+    case DOUBLE:
+      if ((e = pn_fmt(pos, limit, "%f", v.u.as_double))) return e;
+      break;
+    case CHAR:
+      if ((e = pn_fmt(pos, limit, "%lc", v.u.as_char))) return e;
+      break;
+    case STRING:
+      if ((e = pn_fmt(pos, limit, "%ls", v.u.as_string->wcs))) return e;
+      break;
+    case BINARY:
+      if ((e = pn_format_binary(pos, limit, v.u.as_binary))) return e;
+      break;
+    case ARRAY:
+      if ((e = pn_format_array(pos, limit, v.u.as_array))) return e;
+      break;
+    case LIST:
+      if ((e = pn_format_list(pos, limit, v.u.as_list))) return e;
+      break;
+    case MAP:
+      if ((e = pn_format_map(pos, limit, v.u.as_map))) return e;
+      break;
+    case TAG:
+      if ((e = pn_format_tag(pos, limit, v.u.as_tag))) return e;
+      break;
+    case REF:
+      if ((e = pn_fmt(pos, limit, "%p", v.u.as_ref))) return e;
+      break;
+    }
+  }
+
+  return 0;
+}
+
+int pn_format(char *buf, size_t size, pn_value_t v)
+{
+  char *pos = buf;
+  int n = pn_format_value(&pos, buf + size, &v, 1);
+  if (!n) {
+    pos[0] = '\0';
+  } else {
+    if (buf + size - pos < 4) {
+      pos = buf + size - 4;
+    }
+    if (pos > buf) {
+      pn_fmt(&pos, buf + size, "...");
+      pos[0] = '\0';
+    }
+  }
+  return pos - buf;
+}
+
+char *pn_aformat(pn_value_t v)
+{
+  size_t size = pn_format_sizeof(v) + 1;
+  char *buf = malloc(size);
+  if (!buf) return NULL;
+  char *pos = buf;
+  int n = pn_format_value(&pos, buf + size, &v, 1);
+  if (!n) {
+    pos[0] = '\0';
+    return buf;
+  } else {
+    pn_fatal("bad sizeof");
+    free(buf);
+    return NULL;
+  }
+}
+
+size_t pn_format_sizeof(pn_value_t v)
+{
+  switch (v.type)
+  {
+  case EMPTY:
+    return 4;
+  case BOOLEAN:
+    return 5;
+  case BYTE:
+  case UBYTE:
+    return 8;
+  case SHORT:
+  case USHORT:
+    return 16;
+  case INT:
+  case UINT:
+  case CHAR:
+  case FLOAT:
+    return 32;
+  case LONG:
+  case ULONG:
+  case DOUBLE:
+    return 64;
+  case STRING:
+    return 4*v.u.as_string->size;
+  case BINARY:
+    return 4*v.u.as_binary->size;
+  case ARRAY:
+    return pn_format_sizeof_array(v.u.as_array);
+  case LIST:
+    return pn_format_sizeof_list(v.u.as_list);
+  case MAP:
+    return pn_format_sizeof_map(v.u.as_map);
+  case TAG:
+    return pn_format_sizeof_tag(v.u.as_tag);
+  case REF:
+    return 64;
+  default:
+    pn_fatal("xxx");
+    return 0;
+  }
+}
+
+size_t pn_encode_sizeof(pn_value_t v)
+{
+  switch (v.type)
+  {
+  case EMPTY:
+    return 1;
+  case BOOLEAN:
+  case BYTE:
+  case UBYTE:
+    return 2;
+  case SHORT:
+  case USHORT:
+    return 3;
+  case INT:
+  case UINT:
+  case CHAR:
+  case FLOAT:
+    return 5;
+  case LONG:
+  case ULONG:
+  case DOUBLE:
+    return 9;
+  case STRING:
+    return 5 + 4*v.u.as_string->size;
+  case BINARY:
+    return 5 + v.u.as_binary->size;
+  case ARRAY:
+    return pn_encode_sizeof_array(v.u.as_array);
+  case LIST:
+    return pn_encode_sizeof_list(v.u.as_list);
+  case MAP:
+    return pn_encode_sizeof_map(v.u.as_map);
+  case TAG:
+    return pn_encode_sizeof_tag(v.u.as_tag);
+  default:
+    pn_fatal("unencodable type: %s", pn_aformat(v));
+    return 0;
+  }
+}
+
+size_t pn_encode(pn_value_t v, char *out)
+{
+  char *old = out;
+  size_t size = pn_encode_sizeof(v);
+  iconv_t cd;
+  char *inbuf;
+  size_t insize;
+  char *outbuf;
+  size_t utfsize;
+
+  switch (v.type)
+  {
+  case EMPTY:
+    pn_write_null(&out, out + size);
+    return 1;
+  case BOOLEAN:
+    pn_write_boolean(&out, out + size, v.u.as_boolean);
+    return 2;
+  case BYTE:
+    pn_write_byte(&out, out + size, v.u.as_byte);
+    return 2;
+  case UBYTE:
+    pn_write_ubyte(&out, out + size, v.u.as_ubyte);
+    return 2;
+  case SHORT:
+    pn_write_short(&out, out + size, v.u.as_short);
+    return 3;
+  case USHORT:
+    pn_write_ushort(&out, out + size, v.u.as_ushort);
+    return 3;
+  case INT:
+    pn_write_int(&out, out + size, v.u.as_int);
+    return 5;
+  case UINT:
+    pn_write_uint(&out, out + size, v.u.as_uint);
+    return 5;
+  case CHAR:
+    pn_write_char(&out, out + size, v.u.as_char);
+    return 5;
+  case FLOAT:
+    pn_write_float(&out, out + size, v.u.as_float);
+    return 5;
+  case LONG:
+    pn_write_long(&out, out + size, v.u.as_long);
+    return 9;
+  case ULONG:
+    pn_write_ulong(&out, out + size, v.u.as_ulong);
+    return 9;
+  case DOUBLE:
+    pn_write_double(&out, out + size, v.u.as_double);
+    return 9;
+  case STRING:
+    cd = iconv_open("UTF-8", "WCHAR_T");
+    insize = 4*v.u.as_string->size;
+    inbuf = (char *)v.u.as_string->wcs;
+    outbuf = out + 5;
+    utfsize = iconv(cd, &inbuf, &insize, &outbuf, &size);
+    iconv_close(cd);
+    pn_write_utf8(&out, out + size, outbuf - out - 5, out + 5);
+    return out - old;
+  case BINARY:
+    pn_write_binary(&out, out + size, v.u.as_binary->size, v.u.as_binary->bytes);
+    return 5 + v.u.as_binary->size;
+  case ARRAY:
+    return pn_encode_array(v.u.as_array, out);
+  case LIST:
+    return pn_encode_list(v.u.as_list, out);
+  case MAP:
+    return pn_encode_map(v.u.as_map, out);
+  case TAG:
+    return pn_encode_tag(v.u.as_tag, out);
+  default:
+    pn_fatal("unencodable type: %s", pn_aformat(v));
+    return 0;
+  }
+}
+
+void pn_free_value(pn_value_t v)
+{
+  switch (v.type)
+  {
+  case EMPTY:
+  case BOOLEAN:
+  case BYTE:
+  case UBYTE:
+  case SHORT:
+  case USHORT:
+  case INT:
+  case UINT:
+  case CHAR:
+  case FLOAT:
+  case LONG:
+  case ULONG:
+  case DOUBLE:
+  case REF:
+    break;
+  case STRING:
+    pn_free_string(v.u.as_string);
+    break;
+  case BINARY:
+    pn_free_binary(v.u.as_binary);
+    break;
+  case ARRAY:
+    pn_free_array(v.u.as_array);
+    break;
+  case LIST:
+    pn_free_list(v.u.as_list);
+    break;
+  case MAP:
+    pn_free_map(v.u.as_map);
+    break;
+  case TAG:
+    pn_free_tag(v.u.as_tag);
+    break;
+  }
+}
+
+void pn_visit(pn_value_t v, void (*visitor)(pn_value_t))
+{
+  switch (v.type)
+  {
+  case EMPTY:
+  case BOOLEAN:
+  case BYTE:
+  case UBYTE:
+  case SHORT:
+  case USHORT:
+  case INT:
+  case UINT:
+  case CHAR:
+  case FLOAT:
+  case LONG:
+  case ULONG:
+  case DOUBLE:
+  case STRING:
+  case BINARY:
+  case REF:
+    break;
+  case ARRAY:
+    pn_visit_array(v.u.as_array, visitor);
+    break;
+  case LIST:
+    pn_visit_list(v.u.as_list, visitor);
+    break;
+  case MAP:
+    pn_visit_map(v.u.as_map, visitor);
+    break;
+  case TAG:
+    pn_visit_tag(v.u.as_tag, visitor);
+    break;
+  }
+
+  visitor(v);
+}
+
+/* tags */
+
+pn_tag_t *pn_tag(pn_value_t descriptor, pn_value_t value)
+{
+  pn_tag_t *t = malloc(sizeof(pn_tag_t));
+  t->descriptor = descriptor;
+  t->value = value;
+  return t;
+}
+
+void pn_free_tag(pn_tag_t *t)
+{
+  free(t);
+}
+
+void pn_visit_tag(pn_tag_t *t, void (*visitor)(pn_value_t))
+{
+  pn_visit(t->descriptor, visitor);
+  pn_visit(t->value, visitor);
+}
+
+pn_value_t pn_tag_descriptor(pn_tag_t *t)
+{
+  return t->descriptor;
+}
+
+pn_value_t pn_tag_value(pn_tag_t *t)
+{
+  return t->value;
+}
+
+size_t pn_format_sizeof_tag(pn_tag_t *tag)
+{
+  return pn_format_sizeof(tag->descriptor) + pn_format_sizeof(tag->value) + 2;
+}
+
+int pn_format_tag(char **pos, char *limit, pn_tag_t *tag)
+{
+  int e;
+
+  if ((e = pn_format_value(pos, limit, &tag->descriptor, 1))) return e;
+  if ((e = pn_fmt(pos, limit, "("))) return e;
+  if ((e = pn_format_value(pos, limit, &tag->value, 1))) return e;
+  if ((e = pn_fmt(pos, limit, ")"))) return e;
+
+  return 0;
+}
+
+size_t pn_encode_sizeof_tag(pn_tag_t *t)
+{
+  return 1 + pn_encode_sizeof(t->descriptor) + pn_encode_sizeof(t->value);
+}
+
+size_t pn_encode_tag(pn_tag_t *t, char *out)
+{
+  size_t size = 1;
+  pn_write_descriptor(&out, out + 1);
+  size += pn_encode(t->descriptor, out);
+  size += pn_encode(t->value, out + size - 1);
+  return size;
+}

Added: qpid/proton/proton-c/src/util.c
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/util.c?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/util.c (added)
+++ qpid/proton/proton-c/src/util.c Thu Mar  8 18:33:46 2012
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void pn_vfatal(char *fmt, va_list ap)
+{
+  vfprintf(stderr, fmt, ap);
+  exit(-1);
+}
+
+void pn_fatal(char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  pn_vfatal(fmt, ap);
+  va_end(ap);
+}

Added: qpid/proton/proton-c/src/util.h
URL: http://svn.apache.org/viewvc/qpid/proton/proton-c/src/util.h?rev=1298498&view=auto
==============================================================================
--- qpid/proton/proton-c/src/util.h (added)
+++ qpid/proton/proton-c/src/util.h Thu Mar  8 18:33:46 2012
@@ -0,0 +1,86 @@
+#ifndef _PROTON_UTIL_H
+#define _PROTON_UTIL_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define DIE_IFR(EXPR, STRERR)                                           \
+  do {                                                                  \
+    int __code__ = (EXPR);                                              \
+    if (__code__) {                                                     \
+      fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__,       \
+              #EXPR, STRERR(__code__), __code__);                       \
+      exit(-1);                                                         \
+    }                                                                   \
+  } while (0)
+
+#define DIE_IFE(EXPR)                                                   \
+  do {                                                                  \
+    if ((EXPR) == -1) {                                                 \
+      int __code__ = errno;                                             \
+      fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__,       \
+              #EXPR, strerror(__code__), __code__);                     \
+      exit(-1);                                                         \
+    }                                                                   \
+  } while (0)
+
+#define __EMPTY__next next
+#define __EMPTY__prev prev
+#define LL_ADD(HEAD, TAIL, NODE) LL_ADD_PFX(HEAD, TAIL, NODE, __EMPTY__)
+#define LL_ADD_PFX(HEAD, TAIL, NODE, PFX)    \
+  {                                          \
+    (NODE)-> PFX ## next = NULL;             \
+    (NODE)-> PFX ## prev = (TAIL);           \
+    if (TAIL) (TAIL)-> PFX ## next = (NODE); \
+    (TAIL) = (NODE);                         \
+    if (!(HEAD)) (HEAD) = NODE;              \
+  }
+
+#define LL_POP(HEAD, TAIL) LL_POP_PFX(HEAD, TAIL, __EMPTY__)
+#define LL_POP_PFX(HEAD, TAIL, PFX)  \
+  {                                  \
+    if (HEAD) {                      \
+      void *_head = (HEAD);          \
+      (HEAD) = (HEAD)-> PFX ## next; \
+      if (_head == (TAIL))           \
+        (TAIL) = NULL;               \
+    }                                \
+  }
+
+#define LL_REMOVE(HEAD, TAIL, NODE) LL_REMOVE_PFX(HEAD, TAIL, NODE, __EMPTY__)
+#define LL_REMOVE_PFX(HEAD, TAIL, NODE, PFX)                     \
+  {                                                              \
+    if ((NODE)-> PFX ## prev)                                    \
+      (NODE)-> PFX ## prev-> PFX ## next = (NODE)-> PFX ## next; \
+    if ((NODE)-> PFX ## next)                                    \
+      (NODE)-> PFX ## next-> PFX ## prev = (NODE)-> PFX ## prev; \
+    if ((NODE) == (HEAD))                                        \
+      (HEAD) = (NODE)-> PFX ## next;                             \
+    if ((NODE) == (TAIL))                                        \
+      (TAIL) = (NODE)-> PFX ## prev;                             \
+  }
+
+#endif /* util.h */



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