messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers objectc.c Source File

objectc.c

00001 /*
00002  * MessagePack for C dynamic typing routine
00003  *
00004  * Copyright (C) 2008-2009 FURUHASHI Sadayuki
00005  *
00006  *    Distributed under the Boost Software License, Version 1.0.
00007  *    (See accompanying file LICENSE_1_0.txt or copy at
00008  *    http://www.boost.org/LICENSE_1_0.txt)
00009  */
00010 #include "include/object.h"
00011 #include "include/pack.h"
00012 #include <stdio.h>
00013 #include <string.h>
00014 
00015 #if defined(_MSC_VER)
00016 #if _MSC_VER >= 1800
00017 #include <inttypes.h>
00018 #else
00019 #define PRIu64 "I64u"
00020 #define PRIi64 "I64i"
00021 #define PRIi8 "i"
00022 #endif
00023 #else
00024 #include <inttypes.h>
00025 #endif
00026 
00027 
00028 int msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
00029 {
00030     switch(d.type) {
00031     case MSGPACK_OBJECT_NIL:
00032         return msgpack_pack_nil(pk);
00033 
00034     case MSGPACK_OBJECT_BOOLEAN:
00035         if(d.via.boolean) {
00036             return msgpack_pack_true(pk);
00037         } else {
00038             return msgpack_pack_false(pk);
00039         }
00040 
00041     case MSGPACK_OBJECT_POSITIVE_INTEGER:
00042         return msgpack_pack_uint64(pk, d.via.u64);
00043 
00044     case MSGPACK_OBJECT_NEGATIVE_INTEGER:
00045         return msgpack_pack_int64(pk, d.via.i64);
00046 
00047     case MSGPACK_OBJECT_FLOAT:
00048         return msgpack_pack_double(pk, d.via.f64);
00049 
00050     case MSGPACK_OBJECT_STR:
00051         {
00052             int ret = msgpack_pack_str(pk, d.via.str.size);
00053             if(ret < 0) { return ret; }
00054             return msgpack_pack_str_body(pk, d.via.str.ptr, d.via.str.size);
00055         }
00056 
00057     case MSGPACK_OBJECT_BIN:
00058         {
00059             int ret = msgpack_pack_bin(pk, d.via.bin.size);
00060             if(ret < 0) { return ret; }
00061             return msgpack_pack_bin_body(pk, d.via.bin.ptr, d.via.bin.size);
00062         }
00063 
00064     case MSGPACK_OBJECT_EXT:
00065         {
00066             int ret = msgpack_pack_ext(pk, d.via.ext.size, d.via.ext.type);
00067             if(ret < 0) { return ret; }
00068             return msgpack_pack_ext_body(pk, d.via.ext.ptr, d.via.ext.size);
00069         }
00070 
00071     case MSGPACK_OBJECT_ARRAY:
00072         {
00073             int ret = msgpack_pack_array(pk, d.via.array.size);
00074             if(ret < 0) {
00075                 return ret;
00076             }
00077             else {
00078                 msgpack_object* o = d.via.array.ptr;
00079                 msgpack_object* const oend = d.via.array.ptr + d.via.array.size;
00080                 for(; o != oend; ++o) {
00081                     ret = msgpack_pack_object(pk, *o);
00082                     if(ret < 0) { return ret; }
00083                 }
00084 
00085                 return 0;
00086             }
00087         }
00088 
00089     case MSGPACK_OBJECT_MAP:
00090         {
00091             int ret = msgpack_pack_map(pk, d.via.map.size);
00092             if(ret < 0) {
00093                 return ret;
00094             }
00095             else {
00096                 msgpack_object_kv* kv = d.via.map.ptr;
00097                 msgpack_object_kv* const kvend = d.via.map.ptr + d.via.map.size;
00098                 for(; kv != kvend; ++kv) {
00099                     ret = msgpack_pack_object(pk, kv->key);
00100                     if(ret < 0) { return ret; }
00101                     ret = msgpack_pack_object(pk, kv->val);
00102                     if(ret < 0) { return ret; }
00103                 }
00104 
00105                 return 0;
00106             }
00107         }
00108 
00109     default:
00110         return -1;
00111     }
00112 }
00113 
00114 
00115 void msgpack_object_print(FILE* out, msgpack_object o)
00116 {
00117     switch(o.type) {
00118     case MSGPACK_OBJECT_NIL:
00119         fprintf(out, "nil");
00120         break;
00121 
00122     case MSGPACK_OBJECT_BOOLEAN:
00123         fprintf(out, (o.via.boolean ? "true" : "false"));
00124         break;
00125 
00126     case MSGPACK_OBJECT_POSITIVE_INTEGER:
00127 #if defined(PRIu64)
00128         fprintf(out, "%" PRIu64, o.via.u64);
00129 #else
00130         if (o.via.u64 > ULONG_MAX)
00131             fprintf(out, "over 4294967295");
00132         else
00133             fprintf(out, "%lu", (unsigned long)o.via.u64);
00134 #endif
00135         break;
00136 
00137     case MSGPACK_OBJECT_NEGATIVE_INTEGER:
00138 #if defined(PRIi64)
00139         fprintf(out, "%" PRIi64, o.via.i64);
00140 #else
00141         if (o.via.i64 > LONG_MAX)
00142             fprintf(out, "over +2147483647");
00143         else if (o.via.i64 < LONG_MIN)
00144             fprintf(out, "under -2147483648");
00145         else
00146             fprintf(out, "%ld", (signed long)o.via.i64);
00147 #endif
00148         break;
00149 
00150     case MSGPACK_OBJECT_FLOAT:
00151         fprintf(out, "%f", o.via.f64);
00152         break;
00153 
00154     case MSGPACK_OBJECT_STR:
00155         fprintf(out, "\"");
00156         fwrite(o.via.str.ptr, o.via.str.size, 1, out);
00157         fprintf(out, "\"");
00158         break;
00159 
00160     case MSGPACK_OBJECT_BIN:
00161         fprintf(out, "\"");
00162         fwrite(o.via.bin.ptr, o.via.bin.size, 1, out);
00163         fprintf(out, "\"");
00164         break;
00165 
00166     case MSGPACK_OBJECT_EXT:
00167 #if defined(PRIi8)
00168         fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type);
00169 #else
00170         fprintf(out, "(ext: %d)", (int)o.via.ext.type);
00171 #endif
00172         fprintf(out, "\"");
00173         fwrite(o.via.ext.ptr, o.via.ext.size, 1, out);
00174         fprintf(out, "\"");
00175         break;
00176 
00177     case MSGPACK_OBJECT_ARRAY:
00178         fprintf(out, "[");
00179         if(o.via.array.size != 0) {
00180             msgpack_object* p = o.via.array.ptr;
00181             msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
00182             msgpack_object_print(out, *p);
00183             ++p;
00184             for(; p < pend; ++p) {
00185                 fprintf(out, ", ");
00186                 msgpack_object_print(out, *p);
00187             }
00188         }
00189         fprintf(out, "]");
00190         break;
00191 
00192     case MSGPACK_OBJECT_MAP:
00193         fprintf(out, "{");
00194         if(o.via.map.size != 0) {
00195             msgpack_object_kv* p = o.via.map.ptr;
00196             msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
00197             msgpack_object_print(out, p->key);
00198             fprintf(out, "=>");
00199             msgpack_object_print(out, p->val);
00200             ++p;
00201             for(; p < pend; ++p) {
00202                 fprintf(out, ", ");
00203                 msgpack_object_print(out, p->key);
00204                 fprintf(out, "=>");
00205                 msgpack_object_print(out, p->val);
00206             }
00207         }
00208         fprintf(out, "}");
00209         break;
00210 
00211     default:
00212         // FIXME
00213 #if defined(PRIu64)
00214         fprintf(out, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64);
00215 #else
00216         if (o.via.u64 > ULONG_MAX)
00217             fprintf(out, "#<UNKNOWN %i over 4294967295>", o.type);
00218         else
00219             fprintf(out, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64);
00220 #endif
00221 
00222     }
00223 }
00224 
00225 bool msgpack_object_equal(const msgpack_object x, const msgpack_object y)
00226 {
00227     if(x.type != y.type) { return false; }
00228 
00229     switch(x.type) {
00230     case MSGPACK_OBJECT_NIL:
00231         return true;
00232 
00233     case MSGPACK_OBJECT_BOOLEAN:
00234         return x.via.boolean == y.via.boolean;
00235 
00236     case MSGPACK_OBJECT_POSITIVE_INTEGER:
00237         return x.via.u64 == y.via.u64;
00238 
00239     case MSGPACK_OBJECT_NEGATIVE_INTEGER:
00240         return x.via.i64 == y.via.i64;
00241 
00242     case MSGPACK_OBJECT_FLOAT:
00243         return x.via.f64 == y.via.f64;
00244 
00245     case MSGPACK_OBJECT_STR:
00246         return x.via.str.size == y.via.str.size &&
00247             memcmp(x.via.str.ptr, y.via.str.ptr, x.via.str.size) == 0;
00248 
00249     case MSGPACK_OBJECT_BIN:
00250         return x.via.bin.size == y.via.bin.size &&
00251             memcmp(x.via.bin.ptr, y.via.bin.ptr, x.via.bin.size) == 0;
00252 
00253     case MSGPACK_OBJECT_EXT:
00254         return x.via.ext.size == y.via.ext.size &&
00255             x.via.ext.type == y.via.ext.type &&
00256             memcmp(x.via.ext.ptr, y.via.ext.ptr, x.via.ext.size) == 0;
00257 
00258     case MSGPACK_OBJECT_ARRAY:
00259         if(x.via.array.size != y.via.array.size) {
00260             return false;
00261         } else if(x.via.array.size == 0) {
00262             return true;
00263         } else {
00264             msgpack_object* px = x.via.array.ptr;
00265             msgpack_object* const pxend = x.via.array.ptr + x.via.array.size;
00266             msgpack_object* py = y.via.array.ptr;
00267             do {
00268                 if(!msgpack_object_equal(*px, *py)) {
00269                     return false;
00270                 }
00271                 ++px;
00272                 ++py;
00273             } while(px < pxend);
00274             return true;
00275         }
00276 
00277     case MSGPACK_OBJECT_MAP:
00278         if(x.via.map.size != y.via.map.size) {
00279             return false;
00280         } else if(x.via.map.size == 0) {
00281             return true;
00282         } else {
00283             msgpack_object_kv* px = x.via.map.ptr;
00284             msgpack_object_kv* const pxend = x.via.map.ptr + x.via.map.size;
00285             msgpack_object_kv* py = y.via.map.ptr;
00286             do {
00287                 if(!msgpack_object_equal(px->key, py->key) || !msgpack_object_equal(px->val, py->val)) {
00288                     return false;
00289                 }
00290                 ++px;
00291                 ++py;
00292             } while(px < pxend);
00293             return true;
00294         }
00295 
00296     default:
00297         return false;
00298     }
00299 }