~verterok/+junk/postgresql-amqp

« back to all changes in this revision

Viewing changes to librabbitmq/amqp_table.c

  • Committer: Rodney Dawes
  • Date: 2010-08-19 14:35:20 UTC
  • Revision ID: rodney.dawes@canonical.com-20100819143520-25qfv1scbjt3p3xj
Tags: upstream-0.1+r180
ImportĀ upstreamĀ versionĀ 0.1+r180

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdlib.h>
 
2
#include <stdio.h>
 
3
#include <string.h>
 
4
#include <stdint.h>
 
5
#include <errno.h>
 
6
 
 
7
#include "amqp.h"
 
8
#include "amqp_private.h"
 
9
 
 
10
#include <assert.h>
 
11
 
 
12
#define INITIAL_TABLE_SIZE 16
 
13
 
 
14
int amqp_decode_table(amqp_bytes_t encoded,
 
15
                      amqp_pool_t *pool,
 
16
                      amqp_table_t *output,
 
17
                      int *offsetptr)
 
18
{
 
19
  int offset = *offsetptr;
 
20
  uint32_t tablesize = D_32(encoded, offset);
 
21
  int num_entries = 0;
 
22
  amqp_table_entry_t *entries = malloc(INITIAL_TABLE_SIZE * sizeof(amqp_table_entry_t));
 
23
  int allocated_entries = INITIAL_TABLE_SIZE;
 
24
  int limit;
 
25
 
 
26
  if (entries == NULL) {
 
27
    return -ENOMEM;
 
28
  }
 
29
 
 
30
  offset += 4;
 
31
  limit = offset + tablesize;
 
32
 
 
33
  while (offset < limit) {
 
34
    size_t keylen;
 
35
    amqp_table_entry_t *entry;
 
36
 
 
37
    keylen = D_8(encoded, offset);
 
38
    offset++;
 
39
 
 
40
    if (num_entries >= allocated_entries) {
 
41
      void *newentries;
 
42
      allocated_entries = allocated_entries * 2;
 
43
      newentries = realloc(entries, allocated_entries * sizeof(amqp_table_entry_t));
 
44
      if (newentries == NULL) {
 
45
        free(entries);
 
46
        return -ENOMEM;
 
47
      }
 
48
      entries = newentries;
 
49
    }
 
50
    entry = &entries[num_entries];
 
51
 
 
52
    entry->key.len = keylen;
 
53
    entry->key.bytes = D_BYTES(encoded, offset, keylen);
 
54
    offset += keylen;
 
55
 
 
56
    entry->kind = D_8(encoded, offset);
 
57
    offset++;
 
58
 
 
59
    switch (entry->kind) {
 
60
      case 'S':
 
61
        entry->value.bytes.len = D_32(encoded, offset);
 
62
        offset += 4;
 
63
        entry->value.bytes.bytes = D_BYTES(encoded, offset, entry->value.bytes.len);
 
64
        offset += entry->value.bytes.len;
 
65
        break;
 
66
      case 'I':
 
67
        entry->value.i32 = (int32_t) D_32(encoded, offset);
 
68
        offset += 4;
 
69
        break;
 
70
      case 'D':
 
71
        entry->value.decimal.decimals = D_8(encoded, offset);
 
72
        offset++;
 
73
        entry->value.decimal.value = D_32(encoded, offset);
 
74
        offset += 4;
 
75
        break;
 
76
      case 'T':
 
77
        entry->value.u64 = D_64(encoded, offset);
 
78
        offset += 8;
 
79
        break;
 
80
      case 'F':
 
81
        AMQP_CHECK_RESULT(amqp_decode_table(encoded, pool, &(entry->value.table), &offset));
 
82
        break;
 
83
      default:
 
84
        return -EINVAL;
 
85
    }
 
86
 
 
87
    num_entries++;
 
88
  }
 
89
 
 
90
  output->num_entries = num_entries;
 
91
  output->entries = amqp_pool_alloc(pool, num_entries * sizeof(amqp_table_entry_t));
 
92
  memcpy(output->entries, entries, num_entries * sizeof(amqp_table_entry_t));
 
93
 
 
94
  *offsetptr = offset;
 
95
  return 0;
 
96
}
 
97
 
 
98
int amqp_encode_table(amqp_bytes_t encoded,
 
99
                      amqp_table_t *input,
 
100
                      int *offsetptr)
 
101
{
 
102
  int offset = *offsetptr;
 
103
  int tablesize_offset = offset;
 
104
  int i;
 
105
 
 
106
  offset += 4; /* skip space for the size of the table to be filled in later */
 
107
 
 
108
  for (i = 0; i < input->num_entries; i++) {
 
109
    amqp_table_entry_t *entry = &(input->entries[i]);
 
110
 
 
111
    E_8(encoded, offset, entry->key.len);
 
112
    offset++;
 
113
 
 
114
    E_BYTES(encoded, offset, entry->key.len, entry->key.bytes);
 
115
    offset += entry->key.len;
 
116
 
 
117
    E_8(encoded, offset, entry->kind);
 
118
    offset++;
 
119
 
 
120
    switch (entry->kind) {
 
121
      case 'S':
 
122
        E_32(encoded, offset, entry->value.bytes.len);
 
123
        offset += 4;
 
124
        E_BYTES(encoded, offset, entry->value.bytes.len, entry->value.bytes.bytes);
 
125
        offset += entry->value.bytes.len;
 
126
        break;
 
127
      case 'I':
 
128
        E_32(encoded, offset, (uint32_t) entry->value.i32);
 
129
        offset += 4;
 
130
        break;
 
131
      case 'D':
 
132
        E_8(encoded, offset, entry->value.decimal.decimals);
 
133
        offset++;
 
134
        E_32(encoded, offset, entry->value.decimal.value);
 
135
        offset += 4;
 
136
        break;
 
137
      case 'T':
 
138
        E_64(encoded, offset, entry->value.u64);
 
139
        offset += 8;
 
140
        break;
 
141
      case 'F':
 
142
        AMQP_CHECK_RESULT(amqp_encode_table(encoded, &(entry->value.table), &offset));
 
143
        break;
 
144
      default:
 
145
        return -EINVAL;
 
146
    }
 
147
  }
 
148
 
 
149
  E_32(encoded, tablesize_offset, (offset - *offsetptr - 4));
 
150
  *offsetptr = offset;
 
151
  return 0;
 
152
}
 
153
 
 
154
int amqp_table_entry_cmp(void const *entry1, void const *entry2) {
 
155
  amqp_table_entry_t const *p1 = (amqp_table_entry_t const *) entry1;
 
156
  amqp_table_entry_t const *p2 = (amqp_table_entry_t const *) entry2;
 
157
 
 
158
  int d;
 
159
  int minlen;
 
160
 
 
161
  minlen = p1->key.len;
 
162
  if (p2->key.len < minlen) minlen = p2->key.len;
 
163
 
 
164
  d = memcmp(p1->key.bytes, p2->key.bytes, minlen);
 
165
  if (d != 0) {
 
166
    return d;
 
167
  }
 
168
 
 
169
  return p1->key.len - p2->key.len;
 
170
}