00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00129 if (!xmmsv_bitbuffer_put_bits (bb, 32, xmmsv_coll_get_type (coll)))
00130 return false;
00131
00132
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
00141 xmmsv_dict_foreach (attrs, _internal_put_on_bb_append_coll_attr, bb);
00142
00143 attrs = NULL;
00144
00145
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
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
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
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
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
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
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
00348 if (!_internal_get_from_bb_int32_positive (bb, &type)) {
00349 return false;
00350 }
00351
00352 *coll = xmmsv_coll_new (type);
00353
00354
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
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
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
00665
00666
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 }