<commit_before>/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and
 * limitations under the License.
 *
 * The Original Code is librabbitmq.
 *
 * The Initial Developer of the Original Code is VMware, Inc.
 * Portions created by VMware are Copyright (c) 2007-2011 VMware, Inc.
 *
 * Portions created by <NAME> are Copyright (c) 2009-2010
 * VMware, Inc. and <NAME>.
 *
 * All rights reserved.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU General Public License Version 2 or later (the "GPL"), in
 * which case the provisions of the GPL are applicable instead of those
 * above. If you wish to allow use of your version of this file only
 * under the terms of the GPL, and not to allow others to use your
 * version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the
 * notice and other provisions required by the GPL. If you do not
 * delete the provisions above, a recipient may use your version of
 * this file under the terms of any one of the MPL or the GPL.
 *
 * ***** END LICENSE BLOCK *****
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <inttypes.h>

#include <amqp.h>

#include <math.h>

#define M_PI 3.14159265358979323846264338327

static void dump_indent(int indent) {
  int i;
  for (i = 0; i < indent; i++) { putchar(' '); }
}

static void dump_value(int indent, amqp_field_value_t v) {
  dump_indent(indent);
  putchar(v.kind);
  putchar(' ');
  switch (v.kind) {
    case AMQP_FIELD_KIND_BOOLEAN: puts(v.value.boolean ? "true" : "false"); break;
    case AMQP_FIELD_KIND_I8: printf("%"PRId8"\n", v.value.i8); break;
    case AMQP_FIELD_KIND_U8: printf("%"PRIu8"\n", v.value.u8); break;
    case AMQP_FIELD_KIND_I16: printf("%"PRId16"\n", v.value.i16); break;
    case AMQP_FIELD_KIND_U16: printf("%"PRIu16"\n", v.value.u16); break;
    case AMQP_FIELD_KIND_I32: printf("%"PRId32"\n", v.value.i32); break;
    case AMQP_FIELD_KIND_U32: printf("%"PRIu32"\n", v.value.u32); break;
    case AMQP_FIELD_KIND_I64: printf("%"PRId64"\n", v.value.i64); break;
    case AMQP_FIELD_KIND_F32: printf("%g\n", (double) v.value.f32); break;
    case AMQP_FIELD_KIND_F64: printf("%g\n", v.value.f64); break;
    case AMQP_FIELD_KIND_DECIMAL:
      printf("%d:::%u\n", v.value.decimal.decimals, v.value.decimal.value); break;
    case AMQP_FIELD_KIND_UTF8:
      printf("%.*s\n", (int) v.value.bytes.len, (char *) v.value.bytes.bytes); break;
    case AMQP_FIELD_KIND_BYTES:
      {
	int i;
	for (i = 0; i < v.value.bytes.len; i++) {
	  printf("%02x", ((char *) v.value.bytes.bytes)[i]);
	}
	putchar('\n');
      }
      break;
    case AMQP_FIELD_KIND_ARRAY:
      putchar('\n');
      {
	int i;
	for (i = 0; i < v.value.array.num_entries; i++) {
	  dump_value(indent + 2, v.value.array.entries[i]);
	}
      }
      break;
    case AMQP_FIELD_KIND_TIMESTAMP: printf("%"PRIu64"\n", v.value.u64); break;
    case AMQP_FIELD_KIND_TABLE:
      putchar('\n');
      {
	int i;
	for (i = 0; i < v.value.table.num_entries; i++) {
	  dump_indent(indent + 2);
	  printf("%.*s ->\n",
		 (int) v.value.table.entries[i].key.len,
		 (char *) v.value.table.entries[i].key.bytes);
	  dump_value(indent + 4, v.value.table.entries[i].value);
	}
      }
      break;
    case AMQP_FIELD_KIND_VOID: putchar('\n'); break;
    default:
      printf("???\n");
      break;
  }
}

static uint8_t pre_encoded_table[] = {
  0x00, 0x00, 0x00, 0xff, 0x07, 0x6c, 0x6f, 0x6e,
  0x67, 0x73, 0x74, 0x72, 0x53, 0x00, 0x00, 0x00,
  0x15, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73,
  0x20, 0x61, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20,
  0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x09, 0x73,
  0x69, 0x67, 0x6e, 0x65, 0x64, 0x69, 0x6e, 0x74,
  0x49, 0x00, 0x00, 0x30, 0x39, 0x07, 0x64, 0x65,
  0x63, 0x69, 0x6d, 0x61, 0x6c, 0x44, 0x03, 0x00,
  0x01, 0xe2, 0x40, 0x09, 0x74, 0x69, 0x6d, 0x65,
  0x73, 0x74, 0x61, 0x6d, 0x70, 0x54, 0x00, 0x00,
  0x63, 0xee, 0xa0, 0x53, 0xc1, 0x94, 0x05, 0x74,
  0x61, 0x62, 0x6c, 0x65, 0x46, 0x00, 0x00, 0x00,
  0x1f, 0x03, 0x6f, 0x6e, 0x65, 0x49, 0x00, 0x00,
  0xd4, 0x31, 0x03, 0x74, 0x77, 0x6f, 0x53, 0x00,
  0x00, 0x00, 0x0d, 0x41, 0x20, 0x6c, 0x6f, 0x6e,
  0x67, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
  0x04, 0x62, 0x79, 0x74, 0x65, 0x62, 0xff, 0x04,
  0x6c, 0x6f, 0x6e, 0x67, 0x6c, 0x00, 0x00, 0x00,
  0x00, 0x49, 0x96, 0x02, 0xd2, 0x05, 0x73, 0x68,
  0x6f, 0x72, 0x74, 0x73, 0x02, 0x8f, 0x04, 0x62,
  0x6f, 0x6f, 0x6c, 0x74, 0x01, 0x06, 0x62, 0x69,
  0x6e, 0x61, 0x72, 0x79, 0x78, 0x00, 0x00, 0x00,
  0x0f, 0x61, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72,
  0x79, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
  0x04, 0x76, 0x6f, 0x69, 0x64, 0x56, 0x05, 0x61,
  0x72, 0x72, 0x61, 0x79, 0x41, 0x00, 0x00, 0x00,
  0x17, 0x49, 0x00, 0x00, 0xd4, 0x31, 0x53, 0x00,
  0x00, 0x00, 0x0d, 0x41, 0x20, 0x6c, 0x6f, 0x6e,
  0x67, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
  0x05, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x66, 0x40,
  0x49, 0x0f, 0xdb, 0x06, 0x64, 0x6f, 0x75, 0x62,
  0x6c, 0x65, 0x64, 0x40, 0x09, 0x21, 0xfb, 0x54,
  0x44, 0x2d, 0x18
};

static void test_table_codec(void) {
  amqp_pool_t pool;
  int result;

  amqp_table_entry_t inner_entries[2];
  amqp_table_t inner_table;

  amqp_field_value_t inner_values[2];
  amqp_array_t inner_array;

  amqp_table_entry_t entries[14];
  amqp_table_t table;

  inner_entries[0].key = amqp_cstring_bytes("one");
  inner_entries[0].value.kind = AMQP_FIELD_KIND_I32;
  inner_entries[0].value.value.i32 = 54321;

  inner_entries[1].key = amqp_cstring_bytes("two");
  inner_entries[1].value.kind = AMQP_FIELD_KIND_UTF8;
  inner_entries[1].value.value.bytes = amqp_cstring_bytes("A long string");

  inner_table.num_entries = 2;
  inner_table.entries = inner_entries;

  inner_values[0].kind = AMQP_FIELD_KIND_I32;
  inner_values[0].value.i32 = 54321;

  inner_values[1].kind = AMQP_FIELD_KIND_UTF8;
  inner_values[1].value.bytes = amqp_cstring_bytes("A long string");

  inner_array.num_entries = 2;
  inner_array.entries = inner_values;

  entries[0].key = amqp_cstring_bytes("longstr");
  entries[0].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[0].value.value.bytes = amqp_cstring_bytes("Here is a long string");

  entries[1].key = amqp_cstring_bytes("signedint");
  entries[1].value.kind = AMQP_FIELD_KIND_I32;
  entries[1].value.value.i32 = 12345;

  entries[2].key = amqp_cstring_bytes("decimal");
  entries[2].value.kind = AMQP_FIELD_KIND_DECIMAL;
  entries[2].value.value.decimal.decimals = 3;
  entries[2].value.value.decimal.value = 123456;

  entries[3].key = amqp_cstring_bytes("timestamp");
  entries[3].value.kind = AMQP_FIELD_KIND_TIMESTAMP;
  entries[3].value.value.u64 = 109876543209876;

  entries[4].key = amqp_cstring_bytes("table");
  entries[4].value.kind = AMQP_FIELD_KIND_TABLE;
  entries[4].value.value.table = inner_table;

  entries[5].key = amqp_cstring_bytes("byte");
  entries[5].value.kind = AMQP_FIELD_KIND_I8;
  entries[5].value.value.i8 = (int8_t)255;

  entries[6].key = amqp_cstring_bytes("long");
  entries[6].value.kind = AMQP_FIELD_KIND_I64;
  entries[6].value.value.i64 = 1234567890;

  entries[7].key = amqp_cstring_bytes("short");
  entries[7].value.kind = AMQP_FIELD_KIND_I16;
  entries[7].value.value.i16 = 655;

  entries[8].key = amqp_cstring_bytes("bool");
  entries[8].value.kind = AMQP_FIELD_KIND_BOOLEAN;
  entries[8].value.value.boolean = 1;

  entries[9].key = amqp_cstring_bytes("binary");
  entries[9].value.kind = AMQP_FIELD_KIND_BYTES;
  entries[9].value.value.bytes = amqp_cstring_bytes("a binary string");

  entries[10].key = amqp_cstring_bytes("void");
  entries[10].value.kind = AMQP_FIELD_KIND_VOID;

  entries[11].key = amqp_cstring_bytes("array");
  entries[11].value.kind = AMQP_FIELD_KIND_ARRAY;
  entries[11].value.value.array = inner_array;

  entries[12].key = amqp_cstring_bytes("float");
  entries[12].value.kind = AMQP_FIELD_KIND_F32;
  entries[12].value.value.f32 = M_PI;

  entries[13].key = amqp_cstring_bytes("double");
  entries[13].value.kind = AMQP_FIELD_KIND_F64;
  entries[13].value.value.f64 = M_PI;

  table.num_entries = 14;
  table.entries = entries;

  printf("AAAAAAAAAA\n");

  {
    amqp_field_value_t val;
    val.kind = AMQP_FIELD_KIND_TABLE;
    val.value.table = table;
    dump_value(0, val);
  }

  init_amqp_pool(&pool, 4096);

  {
    amqp_table_t decoded;
    size_t decoding_offset = 0;
    amqp_bytes_t decoding_bytes;
    decoding_bytes.len = sizeof(pre_encoded_table);
    decoding_bytes.bytes = pre_encoded_table;

    result = amqp_decode_table(decoding_bytes, &pool, &decoded, &decoding_offset);
    if (result < 0) {
      char *errstr = amqp_error_string(-result);
      printf("Table decoding failed: %d (%s)\n", result, errstr);
      free(errstr);
      abort();
    }
    printf("BBBBBBBBBB\n");

    {
      amqp_field_value_t val;
      val.kind = AMQP_FIELD_KIND_TABLE;
      val.value.table = decoded;

      dump_value(0, val);
    }
  }

  {
    uint8_t encoding_buffer[4096];
    amqp_bytes_t encoding_result;
    size_t offset = 0;

    memset(&encoding_buffer[0], 0, sizeof(encoding_buffer));
    encoding_result.len = sizeof(encoding_buffer);
    encoding_result.bytes = &encoding_buffer[0];

    result = amqp_encode_table(encoding_result, &table, &offset);
    if (result < 0) {
      char *errstr = amqp_error_string(-result);
      printf("Table encoding failed: %d (%s)\n", result, errstr);
      free(errstr);
      abort();
    }

    if (offset != sizeof(pre_encoded_table)) {
      printf("Offset should be %d, was %d\n", (int) sizeof(pre_encoded_table), (int)offset);
      abort();
    }

    result = memcmp(pre_encoded_table, encoding_buffer, offset);
    if (result != 0) {
      printf("Table encoding differed, result = %d\n", result);
      abort();
    }
  }

  empty_amqp_pool(&pool);
}

int main(int argc, char const * const *argv) {
  amqp_table_entry_t entries[8];
  amqp_table_t table;

  union {
    uint32_t i;
    float f;
  } vi;
  union {
    uint64_t l;
    double d;
  } vl;

  entries[0].key = amqp_cstring_bytes("zebra");
  entries[0].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[0].value.value.bytes = amqp_cstring_bytes("last");

  entries[1].key = amqp_cstring_bytes("aardvark");
  entries[1].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[1].value.value.bytes = amqp_cstring_bytes("first");

  entries[2].key = amqp_cstring_bytes("middle");
  entries[2].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[2].value.value.bytes = amqp_cstring_bytes("third");

  entries[3].key = amqp_cstring_bytes("number");
  entries[3].value.kind = AMQP_FIELD_KIND_I32;
  entries[3].value.value.i32 = 1234;

  entries[4].key = amqp_cstring_bytes("decimal");
  entries[4].value.kind = AMQP_FIELD_KIND_DECIMAL;
  entries[4].value.value.decimal.decimals = 2;
  entries[4].value.value.decimal.value = 1234;

  entries[5].key = amqp_cstring_bytes("time");
  entries[5].value.kind = AMQP_FIELD_KIND_TIMESTAMP;
  entries[5].value.value.u64 = 1234123412341234;

  entries[6].key = amqp_cstring_bytes("beta");
  entries[6].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[6].value.value.bytes = amqp_cstring_bytes("second");

  entries[7].key = amqp_cstring_bytes("wombat");
  entries[7].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[7].value.value.bytes = amqp_cstring_bytes("fourth");

  table.num_entries = 8;
  table.entries = entries;

  vi.f = M_PI;
  if ((sizeof(float) != 4) || (vi.i != 0x40490fdb)) {
    printf("*** ERROR: single floating point encoding does not work as expected\n");
    printf("sizeof float is %lu, float is %g, u32 is 0x%08lx\n",
	   (unsigned long)sizeof(float),
	   vi.f,
	   (unsigned long) vi.i);
  }

  vl.d = M_PI;
  if ((sizeof(double) != 8) || (vl.l != 0x400921fb54442d18L)) {
    printf("*** ERROR: double floating point encoding does not work as expected\n");
    printf("sizeof double is %lu, double is %g, u64 is 0x%16"PRIx64"\n",
	   (unsigned long)sizeof(double),
	   vl.d, vl.l);
  }

  test_table_codec();

  qsort(table.entries, table.num_entries, sizeof(amqp_table_entry_t), &amqp_table_entry_cmp);

  printf("----------\n");

  {
    amqp_field_value_t val;
    val.kind = AMQP_FIELD_KIND_TABLE;
    val.value.table = table;

    dump_value(0, val);
  }

  return 0;
}
<commit_msg>Don't emit trailing spaces in test_tables.c<commit_after>/*
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and
 * limitations under the License.
 *
 * The Original Code is librabbitmq.
 *
 * The Initial Developer of the Original Code is VMware, Inc.
 * Portions created by VMware are Copyright (c) 2007-2011 VMware, Inc.
 *
 * Portions created by <NAME> are Copyright (c) 2009-2010
 * VMware, Inc. and <NAME>.
 *
 * All rights reserved.
 *
 * Alternatively, the contents of this file may be used under the terms
 * of the GNU General Public License Version 2 or later (the "GPL"), in
 * which case the provisions of the GPL are applicable instead of those
 * above. If you wish to allow use of your version of this file only
 * under the terms of the GPL, and not to allow others to use your
 * version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the
 * notice and other provisions required by the GPL. If you do not
 * delete the provisions above, a recipient may use your version of
 * this file under the terms of any one of the MPL or the GPL.
 *
 * ***** END LICENSE BLOCK *****
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <inttypes.h>

#include <amqp.h>

#include <math.h>

#define M_PI 3.14159265358979323846264338327

static void dump_indent(int indent) {
  int i;
  for (i = 0; i < indent; i++) { putchar(' '); }
}

static void dump_value(int indent, amqp_field_value_t v) {
  dump_indent(indent);
  putchar(v.kind);
  switch (v.kind) {
    case AMQP_FIELD_KIND_BOOLEAN: puts(v.value.boolean ? " true" : " false"); break;
    case AMQP_FIELD_KIND_I8: printf(" %"PRId8"\n", v.value.i8); break;
    case AMQP_FIELD_KIND_U8: printf(" %"PRIu8"\n", v.value.u8); break;
    case AMQP_FIELD_KIND_I16: printf(" %"PRId16"\n", v.value.i16); break;
    case AMQP_FIELD_KIND_U16: printf(" %"PRIu16"\n", v.value.u16); break;
    case AMQP_FIELD_KIND_I32: printf(" %"PRId32"\n", v.value.i32); break;
    case AMQP_FIELD_KIND_U32: printf(" %"PRIu32"\n", v.value.u32); break;
    case AMQP_FIELD_KIND_I64: printf(" %"PRId64"\n", v.value.i64); break;
    case AMQP_FIELD_KIND_F32: printf(" %g\n", (double) v.value.f32); break;
    case AMQP_FIELD_KIND_F64: printf(" %g\n", v.value.f64); break;
    case AMQP_FIELD_KIND_DECIMAL:
      printf(" %d:::%u\n", v.value.decimal.decimals, v.value.decimal.value); break;
    case AMQP_FIELD_KIND_UTF8:
      printf(" %.*s\n", (int) v.value.bytes.len, (char *) v.value.bytes.bytes); break;
    case AMQP_FIELD_KIND_BYTES:
      {
	int i;
	putchar(' ');
	for (i = 0; i < v.value.bytes.len; i++) {
	  printf("%02x", ((char *) v.value.bytes.bytes)[i]);
	}
	putchar('\n');
      }
      break;
    case AMQP_FIELD_KIND_ARRAY:
      putchar('\n');
      {
	int i;
	for (i = 0; i < v.value.array.num_entries; i++) {
	  dump_value(indent + 2, v.value.array.entries[i]);
	}
      }
      break;
    case AMQP_FIELD_KIND_TIMESTAMP: printf(" %"PRIu64"\n", v.value.u64); break;
    case AMQP_FIELD_KIND_TABLE:
      putchar('\n');
      {
	int i;
	for (i = 0; i < v.value.table.num_entries; i++) {
	  dump_indent(indent + 2);
	  printf("%.*s ->\n",
		 (int) v.value.table.entries[i].key.len,
		 (char *) v.value.table.entries[i].key.bytes);
	  dump_value(indent + 4, v.value.table.entries[i].value);
	}
      }
      break;
    case AMQP_FIELD_KIND_VOID: putchar('\n'); break;
    default:
      printf("???\n");
      break;
  }
}

static uint8_t pre_encoded_table[] = {
  0x00, 0x00, 0x00, 0xff, 0x07, 0x6c, 0x6f, 0x6e,
  0x67, 0x73, 0x74, 0x72, 0x53, 0x00, 0x00, 0x00,
  0x15, 0x48, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73,
  0x20, 0x61, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20,
  0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x09, 0x73,
  0x69, 0x67, 0x6e, 0x65, 0x64, 0x69, 0x6e, 0x74,
  0x49, 0x00, 0x00, 0x30, 0x39, 0x07, 0x64, 0x65,
  0x63, 0x69, 0x6d, 0x61, 0x6c, 0x44, 0x03, 0x00,
  0x01, 0xe2, 0x40, 0x09, 0x74, 0x69, 0x6d, 0x65,
  0x73, 0x74, 0x61, 0x6d, 0x70, 0x54, 0x00, 0x00,
  0x63, 0xee, 0xa0, 0x53, 0xc1, 0x94, 0x05, 0x74,
  0x61, 0x62, 0x6c, 0x65, 0x46, 0x00, 0x00, 0x00,
  0x1f, 0x03, 0x6f, 0x6e, 0x65, 0x49, 0x00, 0x00,
  0xd4, 0x31, 0x03, 0x74, 0x77, 0x6f, 0x53, 0x00,
  0x00, 0x00, 0x0d, 0x41, 0x20, 0x6c, 0x6f, 0x6e,
  0x67, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
  0x04, 0x62, 0x79, 0x74, 0x65, 0x62, 0xff, 0x04,
  0x6c, 0x6f, 0x6e, 0x67, 0x6c, 0x00, 0x00, 0x00,
  0x00, 0x49, 0x96, 0x02, 0xd2, 0x05, 0x73, 0x68,
  0x6f, 0x72, 0x74, 0x73, 0x02, 0x8f, 0x04, 0x62,
  0x6f, 0x6f, 0x6c, 0x74, 0x01, 0x06, 0x62, 0x69,
  0x6e, 0x61, 0x72, 0x79, 0x78, 0x00, 0x00, 0x00,
  0x0f, 0x61, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72,
  0x79, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
  0x04, 0x76, 0x6f, 0x69, 0x64, 0x56, 0x05, 0x61,
  0x72, 0x72, 0x61, 0x79, 0x41, 0x00, 0x00, 0x00,
  0x17, 0x49, 0x00, 0x00, 0xd4, 0x31, 0x53, 0x00,
  0x00, 0x00, 0x0d, 0x41, 0x20, 0x6c, 0x6f, 0x6e,
  0x67, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
  0x05, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x66, 0x40,
  0x49, 0x0f, 0xdb, 0x06, 0x64, 0x6f, 0x75, 0x62,
  0x6c, 0x65, 0x64, 0x40, 0x09, 0x21, 0xfb, 0x54,
  0x44, 0x2d, 0x18
};

static void test_table_codec(void) {
  amqp_pool_t pool;
  int result;

  amqp_table_entry_t inner_entries[2];
  amqp_table_t inner_table;

  amqp_field_value_t inner_values[2];
  amqp_array_t inner_array;

  amqp_table_entry_t entries[14];
  amqp_table_t table;

  inner_entries[0].key = amqp_cstring_bytes("one");
  inner_entries[0].value.kind = AMQP_FIELD_KIND_I32;
  inner_entries[0].value.value.i32 = 54321;

  inner_entries[1].key = amqp_cstring_bytes("two");
  inner_entries[1].value.kind = AMQP_FIELD_KIND_UTF8;
  inner_entries[1].value.value.bytes = amqp_cstring_bytes("A long string");

  inner_table.num_entries = 2;
  inner_table.entries = inner_entries;

  inner_values[0].kind = AMQP_FIELD_KIND_I32;
  inner_values[0].value.i32 = 54321;

  inner_values[1].kind = AMQP_FIELD_KIND_UTF8;
  inner_values[1].value.bytes = amqp_cstring_bytes("A long string");

  inner_array.num_entries = 2;
  inner_array.entries = inner_values;

  entries[0].key = amqp_cstring_bytes("longstr");
  entries[0].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[0].value.value.bytes = amqp_cstring_bytes("Here is a long string");

  entries[1].key = amqp_cstring_bytes("signedint");
  entries[1].value.kind = AMQP_FIELD_KIND_I32;
  entries[1].value.value.i32 = 12345;

  entries[2].key = amqp_cstring_bytes("decimal");
  entries[2].value.kind = AMQP_FIELD_KIND_DECIMAL;
  entries[2].value.value.decimal.decimals = 3;
  entries[2].value.value.decimal.value = 123456;

  entries[3].key = amqp_cstring_bytes("timestamp");
  entries[3].value.kind = AMQP_FIELD_KIND_TIMESTAMP;
  entries[3].value.value.u64 = 109876543209876;

  entries[4].key = amqp_cstring_bytes("table");
  entries[4].value.kind = AMQP_FIELD_KIND_TABLE;
  entries[4].value.value.table = inner_table;

  entries[5].key = amqp_cstring_bytes("byte");
  entries[5].value.kind = AMQP_FIELD_KIND_I8;
  entries[5].value.value.i8 = (int8_t)255;

  entries[6].key = amqp_cstring_bytes("long");
  entries[6].value.kind = AMQP_FIELD_KIND_I64;
  entries[6].value.value.i64 = 1234567890;

  entries[7].key = amqp_cstring_bytes("short");
  entries[7].value.kind = AMQP_FIELD_KIND_I16;
  entries[7].value.value.i16 = 655;

  entries[8].key = amqp_cstring_bytes("bool");
  entries[8].value.kind = AMQP_FIELD_KIND_BOOLEAN;
  entries[8].value.value.boolean = 1;

  entries[9].key = amqp_cstring_bytes("binary");
  entries[9].value.kind = AMQP_FIELD_KIND_BYTES;
  entries[9].value.value.bytes = amqp_cstring_bytes("a binary string");

  entries[10].key = amqp_cstring_bytes("void");
  entries[10].value.kind = AMQP_FIELD_KIND_VOID;

  entries[11].key = amqp_cstring_bytes("array");
  entries[11].value.kind = AMQP_FIELD_KIND_ARRAY;
  entries[11].value.value.array = inner_array;

  entries[12].key = amqp_cstring_bytes("float");
  entries[12].value.kind = AMQP_FIELD_KIND_F32;
  entries[12].value.value.f32 = M_PI;

  entries[13].key = amqp_cstring_bytes("double");
  entries[13].value.kind = AMQP_FIELD_KIND_F64;
  entries[13].value.value.f64 = M_PI;

  table.num_entries = 14;
  table.entries = entries;

  printf("AAAAAAAAAA\n");

  {
    amqp_field_value_t val;
    val.kind = AMQP_FIELD_KIND_TABLE;
    val.value.table = table;
    dump_value(0, val);
  }

  init_amqp_pool(&pool, 4096);

  {
    amqp_table_t decoded;
    size_t decoding_offset = 0;
    amqp_bytes_t decoding_bytes;
    decoding_bytes.len = sizeof(pre_encoded_table);
    decoding_bytes.bytes = pre_encoded_table;

    result = amqp_decode_table(decoding_bytes, &pool, &decoded, &decoding_offset);
    if (result < 0) {
      char *errstr = amqp_error_string(-result);
      printf("Table decoding failed: %d (%s)\n", result, errstr);
      free(errstr);
      abort();
    }
    printf("BBBBBBBBBB\n");

    {
      amqp_field_value_t val;
      val.kind = AMQP_FIELD_KIND_TABLE;
      val.value.table = decoded;

      dump_value(0, val);
    }
  }

  {
    uint8_t encoding_buffer[4096];
    amqp_bytes_t encoding_result;
    size_t offset = 0;

    memset(&encoding_buffer[0], 0, sizeof(encoding_buffer));
    encoding_result.len = sizeof(encoding_buffer);
    encoding_result.bytes = &encoding_buffer[0];

    result = amqp_encode_table(encoding_result, &table, &offset);
    if (result < 0) {
      char *errstr = amqp_error_string(-result);
      printf("Table encoding failed: %d (%s)\n", result, errstr);
      free(errstr);
      abort();
    }

    if (offset != sizeof(pre_encoded_table)) {
      printf("Offset should be %d, was %d\n", (int) sizeof(pre_encoded_table), (int)offset);
      abort();
    }

    result = memcmp(pre_encoded_table, encoding_buffer, offset);
    if (result != 0) {
      printf("Table encoding differed, result = %d\n", result);
      abort();
    }
  }

  empty_amqp_pool(&pool);
}

int main(int argc, char const * const *argv) {
  amqp_table_entry_t entries[8];
  amqp_table_t table;

  union {
    uint32_t i;
    float f;
  } vi;
  union {
    uint64_t l;
    double d;
  } vl;

  entries[0].key = amqp_cstring_bytes("zebra");
  entries[0].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[0].value.value.bytes = amqp_cstring_bytes("last");

  entries[1].key = amqp_cstring_bytes("aardvark");
  entries[1].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[1].value.value.bytes = amqp_cstring_bytes("first");

  entries[2].key = amqp_cstring_bytes("middle");
  entries[2].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[2].value.value.bytes = amqp_cstring_bytes("third");

  entries[3].key = amqp_cstring_bytes("number");
  entries[3].value.kind = AMQP_FIELD_KIND_I32;
  entries[3].value.value.i32 = 1234;

  entries[4].key = amqp_cstring_bytes("decimal");
  entries[4].value.kind = AMQP_FIELD_KIND_DECIMAL;
  entries[4].value.value.decimal.decimals = 2;
  entries[4].value.value.decimal.value = 1234;

  entries[5].key = amqp_cstring_bytes("time");
  entries[5].value.kind = AMQP_FIELD_KIND_TIMESTAMP;
  entries[5].value.value.u64 = 1234123412341234;

  entries[6].key = amqp_cstring_bytes("beta");
  entries[6].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[6].value.value.bytes = amqp_cstring_bytes("second");

  entries[7].key = amqp_cstring_bytes("wombat");
  entries[7].value.kind = AMQP_FIELD_KIND_UTF8;
  entries[7].value.value.bytes = amqp_cstring_bytes("fourth");

  table.num_entries = 8;
  table.entries = entries;

  vi.f = M_PI;
  if ((sizeof(float) != 4) || (vi.i != 0x40490fdb)) {
    printf("*** ERROR: single floating point encoding does not work as expected\n");
    printf("sizeof float is %lu, float is %g, u32 is 0x%08lx\n",
	   (unsigned long)sizeof(float),
	   vi.f,
	   (unsigned long) vi.i);
  }

  vl.d = M_PI;
  if ((sizeof(double) != 8) || (vl.l != 0x400921fb54442d18L)) {
    printf("*** ERROR: double floating point encoding does not work as expected\n");
    printf("sizeof double is %lu, double is %g, u64 is 0x%16"PRIx64"\n",
	   (unsigned long)sizeof(double),
	   vl.d, vl.l);
  }

  test_table_codec();

  qsort(table.entries, table.num_entries, sizeof(amqp_table_entry_t), &amqp_table_entry_cmp);

  printf("----------\n");

  {
    amqp_field_value_t val;
    val.kind = AMQP_FIELD_KIND_TABLE;
    val.value.table = table;

    dump_value(0, val);
  }

  return 0;
}

{'fraction_non_alphanumeric': 0.14523556500177118, 'fraction_numerical': 0.08722005746447829, 'mean_word_length': 3.9663799843627836, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1636626', 'n_tokens_mistral': 12052, 'n_tokens_neox': 10548, 'n_words': 2211}