1/* 2 * MessagePack for C dynamic typing routine 3 * 4 * Copyright (C) 2008-2009 FURUHASHI Sadayuki 5 * 6 * Distributed under the Boost Software License, Version 1.0. 7 * (See accompanying file LICENSE_1_0.txt or copy at 8 * http://www.boost.org/LICENSE_1_0.txt) 9 */ 10#include "msgpack/object.h" 11#include "msgpack/pack.h" 12#include <stdio.h> 13#include <string.h> 14 15#if defined(_MSC_VER) 16#if _MSC_VER >= 1800 17#include <inttypes.h> 18#else 19#define PRIu64 "I64u" 20#define PRIi64 "I64i" 21#define PRIi8 "i" 22#endif 23#else 24#include <inttypes.h> 25#endif 26 27 28int msgpack_pack_object(msgpack_packer* pk, msgpack_object d) 29{ 30 switch(d.type) { 31 case MSGPACK_OBJECT_NIL: 32 return msgpack_pack_nil(pk); 33 34 case MSGPACK_OBJECT_BOOLEAN: 35 if(d.via.boolean) { 36 return msgpack_pack_true(pk); 37 } else { 38 return msgpack_pack_false(pk); 39 } 40 41 case MSGPACK_OBJECT_POSITIVE_INTEGER: 42 return msgpack_pack_uint64(pk, d.via.u64); 43 44 case MSGPACK_OBJECT_NEGATIVE_INTEGER: 45 return msgpack_pack_int64(pk, d.via.i64); 46 47 case MSGPACK_OBJECT_FLOAT: 48 return msgpack_pack_double(pk, d.via.f64); 49 50 case MSGPACK_OBJECT_STR: 51 { 52 int ret = msgpack_pack_str(pk, d.via.str.size); 53 if(ret < 0) { return ret; } 54 return msgpack_pack_str_body(pk, d.via.str.ptr, d.via.str.size); 55 } 56 57 case MSGPACK_OBJECT_BIN: 58 { 59 int ret = msgpack_pack_bin(pk, d.via.bin.size); 60 if(ret < 0) { return ret; } 61 return msgpack_pack_bin_body(pk, d.via.bin.ptr, d.via.bin.size); 62 } 63 64 case MSGPACK_OBJECT_EXT: 65 { 66 int ret = msgpack_pack_ext(pk, d.via.ext.size, d.via.ext.type); 67 if(ret < 0) { return ret; } 68 return msgpack_pack_ext_body(pk, d.via.ext.ptr, d.via.ext.size); 69 } 70 71 case MSGPACK_OBJECT_ARRAY: 72 { 73 int ret = msgpack_pack_array(pk, d.via.array.size); 74 if(ret < 0) { 75 return ret; 76 } 77 else { 78 msgpack_object* o = d.via.array.ptr; 79 msgpack_object* const oend = d.via.array.ptr + d.via.array.size; 80 for(; o != oend; ++o) { 81 ret = msgpack_pack_object(pk, *o); 82 if(ret < 0) { return ret; } 83 } 84 85 return 0; 86 } 87 } 88 89 case MSGPACK_OBJECT_MAP: 90 { 91 int ret = msgpack_pack_map(pk, d.via.map.size); 92 if(ret < 0) { 93 return ret; 94 } 95 else { 96 msgpack_object_kv* kv = d.via.map.ptr; 97 msgpack_object_kv* const kvend = d.via.map.ptr + d.via.map.size; 98 for(; kv != kvend; ++kv) { 99 ret = msgpack_pack_object(pk, kv->key); 100 if(ret < 0) { return ret; } 101 ret = msgpack_pack_object(pk, kv->val); 102 if(ret < 0) { return ret; } 103 } 104 105 return 0; 106 } 107 } 108 109 default: 110 return -1; 111 } 112} 113 114 115void msgpack_object_print(FILE* out, msgpack_object o) 116{ 117 switch(o.type) { 118 case MSGPACK_OBJECT_NIL: 119 fprintf(out, "nil"); 120 break; 121 122 case MSGPACK_OBJECT_BOOLEAN: 123 fprintf(out, (o.via.boolean ? "true" : "false")); 124 break; 125 126 case MSGPACK_OBJECT_POSITIVE_INTEGER: 127#if defined(PRIu64) 128 fprintf(out, "%" PRIu64, o.via.u64); 129#else 130 if (o.via.u64 > ULONG_MAX) 131 fprintf(out, "over 4294967295"); 132 else 133 fprintf(out, "%lu", (unsigned long)o.via.u64); 134#endif 135 break; 136 137 case MSGPACK_OBJECT_NEGATIVE_INTEGER: 138#if defined(PRIi64) 139 fprintf(out, "%" PRIi64, o.via.i64); 140#else 141 if (o.via.i64 > LONG_MAX) 142 fprintf(out, "over +2147483647"); 143 else if (o.via.i64 < LONG_MIN) 144 fprintf(out, "under -2147483648"); 145 else 146 fprintf(out, "%ld", (signed long)o.via.i64); 147#endif 148 break; 149 150 case MSGPACK_OBJECT_FLOAT: 151 fprintf(out, "%f", o.via.f64); 152 break; 153 154 case MSGPACK_OBJECT_STR: 155 fprintf(out, "\""); 156 fwrite(o.via.str.ptr, o.via.str.size, 1, out); 157 fprintf(out, "\""); 158 break; 159 160 case MSGPACK_OBJECT_BIN: 161 fprintf(out, "\""); 162 fwrite(o.via.bin.ptr, o.via.bin.size, 1, out); 163 fprintf(out, "\""); 164 break; 165 166 case MSGPACK_OBJECT_EXT: 167#if defined(PRIi8) 168 fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type); 169#else 170 fprintf(out, "(ext: %d)", (int)o.via.ext.type); 171#endif 172 fprintf(out, "\""); 173 fwrite(o.via.ext.ptr, o.via.ext.size, 1, out); 174 fprintf(out, "\""); 175 break; 176 177 case MSGPACK_OBJECT_ARRAY: 178 fprintf(out, "["); 179 if(o.via.array.size != 0) { 180 msgpack_object* p = o.via.array.ptr; 181 msgpack_object* const pend = o.via.array.ptr + o.via.array.size; 182 msgpack_object_print(out, *p); 183 ++p; 184 for(; p < pend; ++p) { 185 fprintf(out, ", "); 186 msgpack_object_print(out, *p); 187 } 188 } 189 fprintf(out, "]"); 190 break; 191 192 case MSGPACK_OBJECT_MAP: 193 fprintf(out, "{"); 194 if(o.via.map.size != 0) { 195 msgpack_object_kv* p = o.via.map.ptr; 196 msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size; 197 msgpack_object_print(out, p->key); 198 fprintf(out, "=>"); 199 msgpack_object_print(out, p->val); 200 ++p; 201 for(; p < pend; ++p) { 202 fprintf(out, ", "); 203 msgpack_object_print(out, p->key); 204 fprintf(out, "=>"); 205 msgpack_object_print(out, p->val); 206 } 207 } 208 fprintf(out, "}"); 209 break; 210 211 default: 212 // FIXME 213#if defined(PRIu64) 214 fprintf(out, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64); 215#else 216 if (o.via.u64 > ULONG_MAX) 217 fprintf(out, "#<UNKNOWN %i over 4294967295>", o.type); 218 else 219 fprintf(out, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64); 220#endif 221 222 } 223} 224 225bool msgpack_object_equal(const msgpack_object x, const msgpack_object y) 226{ 227 if(x.type != y.type) { return false; } 228 229 switch(x.type) { 230 case MSGPACK_OBJECT_NIL: 231 return true; 232 233 case MSGPACK_OBJECT_BOOLEAN: 234 return x.via.boolean == y.via.boolean; 235 236 case MSGPACK_OBJECT_POSITIVE_INTEGER: 237 return x.via.u64 == y.via.u64; 238 239 case MSGPACK_OBJECT_NEGATIVE_INTEGER: 240 return x.via.i64 == y.via.i64; 241 242 case MSGPACK_OBJECT_FLOAT: 243 return x.via.f64 == y.via.f64; 244 245 case MSGPACK_OBJECT_STR: 246 return x.via.str.size == y.via.str.size && 247 memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0; 248 249 case MSGPACK_OBJECT_BIN: 250 return x.via.bin.size == y.via.bin.size && 251 memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0; 252 253 case MSGPACK_OBJECT_EXT: 254 return x.via.ext.size == y.via.ext.size && 255 x.via.ext.type == y.via.ext.type && 256 memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0; 257 258 case MSGPACK_OBJECT_ARRAY: 259 if(x.via.array.size != y.via.array.size) { 260 return false; 261 } else if(x.via.array.size == 0) { 262 return true; 263 } else { 264 msgpack_object* px = x.via.array.ptr; 265 msgpack_object* const pxend = x.via.array.ptr + x.via.array.size; 266 msgpack_object* py = y.via.array.ptr; 267 do { 268 if(!msgpack_object_equal(*px, *py)) { 269 return false; 270 } 271 ++px; 272 ++py; 273 } while(px < pxend); 274 return true; 275 } 276 277 case MSGPACK_OBJECT_MAP: 278 if(x.via.map.size != y.via.map.size) { 279 return false; 280 } else if(x.via.map.size == 0) { 281 return true; 282 } else { 283 msgpack_object_kv* px = x.via.map.ptr; 284 msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size; 285 msgpack_object_kv* py = y.via.map.ptr; 286 do { 287 if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) { 288 return false; 289 } 290 ++px; 291 ++py; 292 } while(px < pxend); 293 return true; 294 } 295 296 default: 297 return false; 298 } 299} 300