XMMS2
src/lib/xmmstypes/value_serialize.c
Go to the documentation of this file.
00001 /*  XMMS2 - X Music Multiplexer System
00002  *  Copyright (C) 2003-2011 XMMS2 Team
00003  *
00004  *  PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2.1 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  */
00016 
00017 #include <string.h>
00018 
00019 #include "xmmsc/xmmsc_stdbool.h"
00020 #include "xmmsc/xmmsc_util.h"
00021 #include "xmmsc/xmmsv.h"
00022 #include "xmmsclientpriv/xmmsclient_util.h"
00023 
00024 static bool _internal_put_on_bb_bin (xmmsv_t *bb, const unsigned char *data, unsigned int len);
00025 static bool _internal_put_on_bb_error (xmmsv_t *bb, const char *errmsg);
00026 static bool _internal_put_on_bb_int32 (xmmsv_t *bb, int32_t v);
00027 static bool _internal_put_on_bb_string (xmmsv_t *bb, const char *str);
00028 static bool _internal_put_on_bb_collection (xmmsv_t *bb, xmmsv_coll_t *coll);
00029 static bool _internal_put_on_bb_value_list (xmmsv_t *bb, xmmsv_t *v);
00030 static bool _internal_put_on_bb_value_dict (xmmsv_t *bb, xmmsv_t *v);
00031 
00032 static bool _internal_get_from_bb_error_alloc (xmmsv_t *bb, char **buf, unsigned int *len);
00033 static bool _internal_get_from_bb_int32 (xmmsv_t *bb, int32_t *v);
00034 static bool _internal_get_from_bb_int32_positive (xmmsv_t *bb, int32_t *v);
00035 static bool _internal_get_from_bb_string_alloc (xmmsv_t *bb, char **buf, unsigned int *len);
00036 static bool _internal_get_from_bb_collection_alloc (xmmsv_t *bb, xmmsv_coll_t **coll);
00037 static bool _internal_get_from_bb_bin_alloc (xmmsv_t *bb, unsigned char **buf, unsigned int *len);
00038 
00039 static bool _internal_get_from_bb_value_of_type_alloc (xmmsv_t *bb, xmmsv_type_t type, xmmsv_t **val);
00040 
00041 
00042 static void
00043 _internal_put_on_bb_append_coll_attr (const char *key, xmmsv_t *value, void *userdata)
00044 {
00045     xmmsv_t *bb = (xmmsv_t *)userdata;
00046     const char *s;
00047     int r;
00048 
00049     r = xmmsv_get_string (value, &s);
00050     x_return_if_fail (r);
00051 
00052     _internal_put_on_bb_string (bb, key);
00053     _internal_put_on_bb_string (bb, s);
00054 }
00055 
00056 static void
00057 _internal_put_on_bb_count_coll_attr (const char *key, xmmsv_t *value, void *userdata)
00058 {
00059     int *n = (int *)userdata;
00060     ++(*n);
00061 }
00062 
00063 static bool
00064 _internal_put_on_bb_bin (xmmsv_t *bb,
00065                          const unsigned char *data,
00066                          unsigned int len)
00067 {
00068     if (!xmmsv_bitbuffer_put_bits (bb, 32, len))
00069         return false;
00070 
00071     return xmmsv_bitbuffer_put_data (bb, data, len);
00072 }
00073 
00074 static bool
00075 _internal_put_on_bb_error (xmmsv_t *bb, const char *errmsg)
00076 {
00077     if (!bb) {
00078         return -1;
00079     }
00080 
00081     if (!errmsg) {
00082         return xmmsv_bitbuffer_put_bits (bb, 32, 0);
00083     }
00084 
00085     if (!xmmsv_bitbuffer_put_bits (bb, 32, strlen (errmsg) + 1))
00086         return false;
00087 
00088     return xmmsv_bitbuffer_put_data (bb, (const unsigned char *) errmsg, strlen (errmsg) + 1);
00089 }
00090 
00091 static bool
00092 _internal_put_on_bb_int32 (xmmsv_t *bb, int32_t v)
00093 {
00094     return xmmsv_bitbuffer_put_bits (bb, 32, v);
00095 }
00096 
00097 static bool
00098 _internal_put_on_bb_string (xmmsv_t *bb, const char *str)
00099 {
00100     if (!bb) {
00101         return false;
00102     }
00103 
00104     if (!str) {
00105         return xmmsv_bitbuffer_put_bits (bb, 32, 0);
00106     }
00107 
00108     if (!xmmsv_bitbuffer_put_bits (bb, 32, strlen (str) + 1))
00109         return false;
00110 
00111     return xmmsv_bitbuffer_put_data (bb, (const unsigned char *) str, strlen (str) + 1);
00112 }
00113 
00114 static bool
00115 _internal_put_on_bb_collection (xmmsv_t *bb, xmmsv_coll_t *coll)
00116 {
00117     xmmsv_list_iter_t *it;
00118     xmmsv_t *v, *attrs;
00119     int n;
00120     uint32_t ret;
00121     int32_t entry;
00122     xmmsv_coll_t *op;
00123 
00124     if (!bb || !coll) {
00125         return false;
00126     }
00127 
00128     /* push type */
00129     if (!xmmsv_bitbuffer_put_bits (bb, 32, xmmsv_coll_get_type (coll)))
00130         return false;
00131 
00132     /* attribute counter and values */
00133     attrs = xmmsv_coll_attributes_get (coll);
00134     n = 0;
00135 
00136     xmmsv_dict_foreach (attrs, _internal_put_on_bb_count_coll_attr, &n);
00137     if (!xmmsv_bitbuffer_put_bits (bb, 32, n))
00138         return false;
00139 
00140     /* needs error checking! */
00141     xmmsv_dict_foreach (attrs, _internal_put_on_bb_append_coll_attr, bb);
00142 
00143     attrs = NULL; /* no unref needed. */
00144 
00145     /* idlist counter and content */
00146     xmmsv_bitbuffer_put_bits (bb, 32, xmmsv_coll_idlist_get_size (coll));
00147 
00148     xmmsv_get_list_iter (xmmsv_coll_idlist_get (coll), &it);
00149     for (xmmsv_list_iter_first (it);
00150          xmmsv_list_iter_valid (it);
00151          xmmsv_list_iter_next (it)) {
00152 
00153         if (!xmmsv_list_iter_entry_int (it, &entry)) {
00154             x_api_error ("Non integer in idlist", 0);
00155         }
00156         xmmsv_bitbuffer_put_bits (bb, 32, entry);
00157     }
00158     xmmsv_list_iter_explicit_destroy (it);
00159 
00160     /* operands counter and objects */
00161     n = 0;
00162     if (xmmsv_coll_get_type (coll) != XMMS_COLLECTION_TYPE_REFERENCE) {
00163         n = xmmsv_list_get_size (xmmsv_coll_operands_get (coll));
00164     }
00165 
00166     ret = xmmsv_bitbuffer_pos (bb);
00167     xmmsv_bitbuffer_put_bits (bb, 32, n);
00168 
00169     if (n > 0) {
00170         xmmsv_get_list_iter (xmmsv_coll_operands_get (coll), &it);
00171 
00172         while (xmmsv_list_iter_entry (it, &v)) {
00173             if (!xmmsv_get_coll (v, &op)) {
00174                 x_api_error ("Non collection operand", 0);
00175             }
00176 
00177             _internal_put_on_bb_int32 (bb, XMMSV_TYPE_COLL);
00178 
00179             ret = _internal_put_on_bb_collection (bb, op);
00180             xmmsv_list_iter_next (it);
00181         }
00182     }
00183 
00184     return ret;
00185 }
00186 
00187 static bool
00188 _internal_put_on_bb_value_list (xmmsv_t *bb, xmmsv_t *v)
00189 {
00190     xmmsv_list_iter_t *it;
00191     xmmsv_t *entry;
00192     uint32_t offset, count;
00193     bool ret = true;
00194 
00195     if (!xmmsv_get_list_iter (v, &it)) {
00196         return false;
00197     }
00198 
00199     /* store a dummy value, store the real count once it's known */
00200     offset = xmmsv_bitbuffer_pos (bb);
00201     xmmsv_bitbuffer_put_bits (bb, 32, 0);
00202 
00203     count = 0;
00204     while (xmmsv_list_iter_valid (it)) {
00205         xmmsv_list_iter_entry (it, &entry);
00206         ret = xmmsv_bitbuffer_serialize_value (bb, entry);
00207         xmmsv_list_iter_next (it);
00208         count++;
00209     }
00210 
00211     /* overwrite with real size */
00212     xmmsv_bitbuffer_put_bits_at (bb, 32, count, offset);
00213 
00214     return ret;
00215 }
00216 
00217 static bool
00218 _internal_put_on_bb_value_dict (xmmsv_t *bb, xmmsv_t *v)
00219 {
00220     xmmsv_dict_iter_t *it;
00221     const char *key;
00222     xmmsv_t *entry;
00223     uint32_t ret, offset, count;
00224 
00225     if (!xmmsv_get_dict_iter (v, &it)) {
00226         return false;
00227     }
00228 
00229     /* store a dummy value, store the real count once it's known */
00230     offset = xmmsv_bitbuffer_pos (bb);
00231     xmmsv_bitbuffer_put_bits (bb, 32, 0);
00232 
00233     count = 0;
00234     while (xmmsv_dict_iter_valid (it)) {
00235         xmmsv_dict_iter_pair (it, &key, &entry);
00236         ret = _internal_put_on_bb_string (bb, key);
00237         ret = xmmsv_bitbuffer_serialize_value (bb, entry);
00238         xmmsv_dict_iter_next (it);
00239         count++;
00240     }
00241 
00242     /* overwrite with real size */
00243     xmmsv_bitbuffer_put_bits_at (bb, 32, count, offset);
00244 
00245     return ret;
00246 }
00247 
00248 static bool
00249 _internal_get_from_bb_data (xmmsv_t *bb, void *buf, unsigned int len)
00250 {
00251     if (!bb)
00252         return false;
00253 
00254     return xmmsv_bitbuffer_get_data (bb, buf, len);
00255 }
00256 
00257 static bool
00258 _internal_get_from_bb_error_alloc (xmmsv_t *bb, char **buf,
00259                                    unsigned int *len)
00260 {
00261     /* currently, an error is just a string, so reuse that */
00262     return _internal_get_from_bb_string_alloc (bb, buf, len);
00263 }
00264 
00265 static bool
00266 _internal_get_from_bb_int32 (xmmsv_t *bb, int32_t *v)
00267 {
00268     return xmmsv_bitbuffer_get_bits (bb, 32, v);
00269 }
00270 
00271 static bool
00272 _internal_get_from_bb_int32_positive (xmmsv_t *bb, int32_t *v)
00273 {
00274     bool ret;
00275     ret = _internal_get_from_bb_int32 (bb, v);
00276     if (ret && *v < 0)
00277         ret = false;
00278     return ret;
00279 }
00280 static bool
00281 _internal_get_from_bb_string_alloc (xmmsv_t *bb, char **buf,
00282                                     unsigned int *len)
00283 {
00284     char *str;
00285     int32_t l;
00286 
00287     if (!_internal_get_from_bb_int32_positive (bb, &l)) {
00288         return false;
00289     }
00290 
00291     str = x_malloc (l + 1);
00292     if (!str) {
00293         return false;
00294     }
00295 
00296     if (!_internal_get_from_bb_data (bb, str, l)) {
00297         free (str);
00298         return false;
00299     }
00300 
00301     str[l] = '\0';
00302 
00303     *buf = str;
00304     *len = l;
00305 
00306     return true;
00307 }
00308 
00309 static bool
00310 _internal_get_from_bb_bin_alloc (xmmsv_t *bb,
00311                                  unsigned char **buf,
00312                                  unsigned int *len)
00313 {
00314     unsigned char *b;
00315     int32_t l;
00316 
00317     if (!_internal_get_from_bb_int32_positive (bb, &l)) {
00318         return false;
00319     }
00320 
00321     b = x_malloc (l);
00322     if (!b) {
00323         return false;
00324     }
00325 
00326     if (!_internal_get_from_bb_data (bb, b, l)) {
00327         free (b);
00328         return false;
00329     }
00330 
00331     *buf = b;
00332     *len = l;
00333 
00334     return true;
00335 }
00336 
00337 static bool
00338 _internal_get_from_bb_collection_alloc (xmmsv_t *bb, xmmsv_coll_t **coll)
00339 {
00340     int i;
00341     int32_t type;
00342     int32_t n_items;
00343     int id;
00344     int32_t *idlist = NULL;
00345     char *key, *val;
00346 
00347     /* Get the type and create the collection */
00348     if (!_internal_get_from_bb_int32_positive (bb, &type)) {
00349         return false;
00350     }
00351 
00352     *coll = xmmsv_coll_new (type);
00353 
00354     /* Get the list of attributes */
00355     if (!_internal_get_from_bb_int32_positive (bb, &n_items)) {
00356         goto err;
00357     }
00358 
00359     for (i = 0; i < n_items; i++) {
00360         unsigned int len;
00361         if (!_internal_get_from_bb_string_alloc (bb, &key, &len)) {
00362             goto err;
00363         }
00364         if (!_internal_get_from_bb_string_alloc (bb, &val, &len)) {
00365             free (key);
00366             goto err;
00367         }
00368 
00369         xmmsv_coll_attribute_set (*coll, key, val);
00370         free (key);
00371         free (val);
00372     }
00373 
00374     /* Get the idlist */
00375     if (!_internal_get_from_bb_int32_positive (bb, &n_items)) {
00376         goto err;
00377     }
00378 
00379     if (!(idlist = x_new (int32_t, n_items + 1))) {
00380         goto err;
00381     }
00382 
00383     for (i = 0; i < n_items; i++) {
00384         if (!_internal_get_from_bb_int32 (bb, &id)) {
00385             goto err;
00386         }
00387 
00388         idlist[i] = id;
00389     }
00390 
00391     idlist[i] = 0;
00392     xmmsv_coll_set_idlist (*coll, idlist);
00393     free (idlist);
00394     idlist = NULL;
00395 
00396     /* Get the operands */
00397     if (!_internal_get_from_bb_int32_positive (bb, &n_items)) {
00398         goto err;
00399     }
00400 
00401     for (i = 0; i < n_items; i++) {
00402         xmmsv_coll_t *operand;
00403 
00404         if (!_internal_get_from_bb_int32_positive (bb, &type) ||
00405             type != XMMSV_TYPE_COLL ||
00406             !_internal_get_from_bb_collection_alloc (bb, &operand)) {
00407             goto err;
00408         }
00409 
00410         xmmsv_coll_add_operand (*coll, operand);
00411         xmmsv_coll_unref (operand);
00412     }
00413 
00414     return true;
00415 
00416 err:
00417     if (idlist != NULL) {
00418         free (idlist);
00419     }
00420 
00421     xmmsv_coll_unref (*coll);
00422 
00423     return false;
00424 }
00425 
00426 
00427 static int
00428 xmmsc_deserialize_dict (xmmsv_t *bb, xmmsv_t **val)
00429 {
00430     xmmsv_t *dict;
00431     int32_t len;
00432     unsigned int ignore;
00433     char *key;
00434 
00435     dict = xmmsv_new_dict ();
00436 
00437     if (!_internal_get_from_bb_int32_positive (bb, &len)) {
00438         goto err;
00439     }
00440 
00441     while (len--) {
00442         xmmsv_t *v;
00443 
00444         if (!_internal_get_from_bb_string_alloc (bb, &key, &ignore)) {
00445             goto err;
00446         }
00447 
00448         if (!xmmsv_bitbuffer_deserialize_value (bb, &v)) {
00449             free (key);
00450             goto err;
00451         }
00452 
00453         xmmsv_dict_set (dict, key, v);
00454         free (key);
00455         xmmsv_unref (v);
00456     }
00457 
00458     *val = dict;
00459 
00460     return true;
00461 
00462 err:
00463     x_internal_error ("Message from server did not parse correctly!");
00464     xmmsv_unref (dict);
00465     return false;
00466 }
00467 
00468 static int
00469 xmmsc_deserialize_list (xmmsv_t *bb, xmmsv_t **val)
00470 {
00471     xmmsv_t *list;
00472     int32_t len;
00473 
00474     list = xmmsv_new_list ();
00475 
00476     if (!_internal_get_from_bb_int32_positive (bb, &len)) {
00477         goto err;
00478     }
00479 
00480     while (len--) {
00481         xmmsv_t *v;
00482         if (xmmsv_bitbuffer_deserialize_value (bb, &v)) {
00483             xmmsv_list_append (list, v);
00484         } else {
00485             goto err;
00486         }
00487         xmmsv_unref (v);
00488     }
00489 
00490     *val = list;
00491 
00492     return true;
00493 
00494 err:
00495     x_internal_error ("Message from server did not parse correctly!");
00496     xmmsv_unref (list);
00497     return false;
00498 }
00499 
00500 static bool
00501 _internal_get_from_bb_value_of_type_alloc (xmmsv_t *bb, xmmsv_type_t type,
00502                                            xmmsv_t **val)
00503 {
00504     int32_t i;
00505     uint32_t len;
00506     char *s;
00507     xmmsv_coll_t *c;
00508     unsigned char *d;
00509 
00510     switch (type) {
00511         case XMMSV_TYPE_ERROR:
00512             if (!_internal_get_from_bb_error_alloc (bb, &s, &len)) {
00513                 return false;
00514             }
00515             *val = xmmsv_new_error (s);
00516             free (s);
00517             break;
00518         case XMMSV_TYPE_INT32:
00519             if (!_internal_get_from_bb_int32 (bb, &i)) {
00520                 return false;
00521             }
00522             *val = xmmsv_new_int (i);
00523             break;
00524         case XMMSV_TYPE_STRING:
00525             if (!_internal_get_from_bb_string_alloc (bb, &s, &len)) {
00526                 return false;
00527             }
00528             *val = xmmsv_new_string (s);
00529             free (s);
00530             break;
00531         case XMMSV_TYPE_DICT:
00532             if (!xmmsc_deserialize_dict (bb, val)) {
00533                 return false;
00534             }
00535             break;
00536 
00537         case XMMSV_TYPE_LIST :
00538             if (!xmmsc_deserialize_list (bb, val)) {
00539                 return false;
00540             }
00541             break;
00542 
00543         case XMMSV_TYPE_COLL:
00544             if (!_internal_get_from_bb_collection_alloc (bb, &c)) {
00545                 return false;
00546             }
00547             *val = xmmsv_new_coll (c);
00548             xmmsv_coll_unref (c);
00549             break;
00550 
00551         case XMMSV_TYPE_BIN:
00552             if (!_internal_get_from_bb_bin_alloc (bb, &d, &len)) {
00553                 return false;
00554             }
00555             *val = xmmsv_new_bin (d, len);
00556             free (d);
00557             break;
00558 
00559         case XMMSV_TYPE_NONE:
00560             *val = xmmsv_new_none ();
00561             break;
00562         default:
00563             x_internal_error ("Got message of unknown type!");
00564             return false;
00565     }
00566 
00567     return true;
00568 }
00569 
00570 
00571 
00572 int
00573 xmmsv_bitbuffer_serialize_value (xmmsv_t *bb, xmmsv_t *v)
00574 {
00575     bool ret;
00576     int32_t i;
00577     const char *s;
00578     xmmsv_coll_t *c;
00579     const unsigned char *bc;
00580     unsigned int bl;
00581     xmmsv_type_t type;
00582 
00583     type = xmmsv_get_type (v);
00584     ret = _internal_put_on_bb_int32 (bb, type);
00585     if (!ret)
00586         return ret;
00587 
00588     switch (type) {
00589     case XMMSV_TYPE_ERROR:
00590         if (!xmmsv_get_error (v, &s)) {
00591             return false;
00592         }
00593         ret = _internal_put_on_bb_error (bb, s);
00594         break;
00595     case XMMSV_TYPE_INT32:
00596         if (!xmmsv_get_int (v, &i)) {
00597             return false;
00598         }
00599         ret = _internal_put_on_bb_int32 (bb, i);
00600         break;
00601     case XMMSV_TYPE_STRING:
00602         if (!xmmsv_get_string (v, &s)) {
00603             return false;
00604         }
00605         ret = _internal_put_on_bb_string (bb, s);
00606         break;
00607     case XMMSV_TYPE_COLL:
00608         if (!xmmsv_get_coll (v, &c)) {
00609             return false;
00610         }
00611         ret = _internal_put_on_bb_collection (bb, c);
00612         break;
00613     case XMMSV_TYPE_BIN:
00614         if (!xmmsv_get_bin (v, &bc, &bl)) {
00615             return false;
00616         }
00617         ret = _internal_put_on_bb_bin (bb, bc, bl);
00618         break;
00619     case XMMSV_TYPE_LIST:
00620         ret = _internal_put_on_bb_value_list (bb, v);
00621         break;
00622     case XMMSV_TYPE_DICT:
00623         ret = _internal_put_on_bb_value_dict (bb, v);
00624         break;
00625 
00626     case XMMSV_TYPE_NONE:
00627         break;
00628     default:
00629         x_internal_error ("Tried to serialize value of unsupported type");
00630         return false;
00631     }
00632 
00633     return ret;
00634 }
00635 
00636 int
00637 xmmsv_bitbuffer_deserialize_value (xmmsv_t *bb, xmmsv_t **val)
00638 {
00639     int32_t type;
00640 
00641     if (!_internal_get_from_bb_int32 (bb, &type)) {
00642         return false;
00643     }
00644 
00645     return _internal_get_from_bb_value_of_type_alloc (bb, type, val);
00646 }
00647 
00648 
00649 xmmsv_t *
00650 xmmsv_serialize (xmmsv_t *v)
00651 {
00652     xmmsv_t *bb, *res;
00653 
00654     if (!v)
00655         return NULL;
00656 
00657     bb = xmmsv_bitbuffer_new ();
00658 
00659     if (!xmmsv_bitbuffer_serialize_value (bb, v)) {
00660         xmmsv_unref (bb);
00661         return NULL;
00662     }
00663 
00664     /* this is internally in xmmsv implementation,
00665        so we could just switch the type,
00666        but thats for later */
00667     res = xmmsv_new_bin (xmmsv_bitbuffer_buffer (bb), xmmsv_bitbuffer_len (bb) / 8);
00668     xmmsv_unref (bb);
00669     return res;
00670 }
00671 
00672 xmmsv_t *
00673 xmmsv_deserialize (xmmsv_t *v)
00674 {
00675     xmmsv_t *bb;
00676     xmmsv_t *res;
00677     const unsigned char *data;
00678     uint32_t len;
00679 
00680 
00681     if (!xmmsv_get_bin (v, &data, &len))
00682         return NULL;
00683 
00684 
00685     bb = xmmsv_bitbuffer_new_ro (data, len);
00686 
00687     if (!xmmsv_bitbuffer_deserialize_value (bb, &res)) {
00688         xmmsv_unref (bb);
00689         return NULL;
00690     }
00691     xmmsv_unref (bb);
00692     return res;
00693 }