XMMS2
|
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 }