xmlrpc_struct.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
  2. **
  3. ** Redistribution and use in source and binary forms, with or without
  4. ** modification, are permitted provided that the following conditions
  5. ** are met:
  6. ** 1. Redistributions of source code must retain the above copyright
  7. ** notice, this list of conditions and the following disclaimer.
  8. ** 2. Redistributions in binary form must reproduce the above copyright
  9. ** notice, this list of conditions and the following disclaimer in the
  10. ** documentation and/or other materials provided with the distribution.
  11. ** 3. The name of the author may not be used to endorse or promote products
  12. ** derived from this software without specific prior written permission.
  13. **
  14. ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. ** SUCH DAMAGE. */
  25. #include "xmlrpc_config.h"
  26. #include <stddef.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "xmlrpc.h"
  30. #include "xmlrpc_int.h"
  31. #define KEY_ERROR_BUFFER_SZ (32)
  32. void
  33. xmlrpc_destroyStruct(xmlrpc_value * const structP) {
  34. _struct_member * const members =
  35. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  36. size_t const size =
  37. XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block);
  38. unsigned int i;
  39. for (i = 0; i < size; ++i) {
  40. xmlrpc_DECREF(members[i].key);
  41. xmlrpc_DECREF(members[i].value);
  42. }
  43. XMLRPC_MEMBLOCK_CLEAN(_struct_member, &structP->_block);
  44. }
  45. /*=========================================================================
  46. ** xmlrpc_struct_new
  47. **=========================================================================
  48. ** Create a new <struct> value. The corresponding destructor code
  49. ** currently lives in xmlrpc_DECREF.
  50. **
  51. ** We store the individual members in an array of _struct_member. This
  52. ** contains a key, a hash code, and a value. We look up keys by doing
  53. ** a linear search of the hash codes.
  54. */
  55. xmlrpc_value *
  56. xmlrpc_struct_new(xmlrpc_env* env)
  57. {
  58. xmlrpc_value *strct;
  59. int strct_valid;
  60. XMLRPC_ASSERT_ENV_OK(env);
  61. /* Set up error handling preconditions. */
  62. strct = NULL;
  63. strct_valid = 0;
  64. /* Allocate and fill out an empty structure. */
  65. strct = (xmlrpc_value*) malloc(sizeof(xmlrpc_value));
  66. XMLRPC_FAIL_IF_NULL(strct, env, XMLRPC_INTERNAL_ERROR,
  67. "Could not allocate memory for struct");
  68. strct->_refcount = 1;
  69. strct->_type = XMLRPC_TYPE_STRUCT;
  70. XMLRPC_MEMBLOCK_INIT(_struct_member, env, &strct->_block, 0);
  71. XMLRPC_FAIL_IF_FAULT(env);
  72. strct_valid = 1;
  73. cleanup:
  74. if (env->fault_occurred) {
  75. if (strct) {
  76. if (strct_valid)
  77. xmlrpc_DECREF(strct);
  78. else
  79. free(strct);
  80. }
  81. return NULL;
  82. }
  83. return strct;
  84. }
  85. /*=========================================================================
  86. ** xmlrpc_struct_size
  87. **=========================================================================
  88. ** Return the number of key-value pairs contained in the struct. If the
  89. ** value is not a struct, return -1 and set a fault.
  90. */
  91. int
  92. xmlrpc_struct_size(xmlrpc_env* env, xmlrpc_value* strct)
  93. {
  94. int retval;
  95. /* Suppress a compiler warning about uninitialized variables. */
  96. retval = 0;
  97. XMLRPC_ASSERT_ENV_OK(env);
  98. XMLRPC_ASSERT_VALUE_OK(strct);
  99. XMLRPC_TYPE_CHECK(env, strct, XMLRPC_TYPE_STRUCT);
  100. retval = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strct->_block);
  101. cleanup:
  102. if (env->fault_occurred)
  103. return -1;
  104. return retval;
  105. }
  106. /*=========================================================================
  107. ** get_hash
  108. **=========================================================================
  109. ** A mindlessly simple hash function. Please feel free to write something
  110. ** more clever if this produces bad results.
  111. */
  112. static unsigned char
  113. get_hash(const char * const key,
  114. size_t const key_len) {
  115. unsigned char retval;
  116. size_t i;
  117. XMLRPC_ASSERT(key != NULL);
  118. retval = 0;
  119. for (i = 0; i < key_len; i++)
  120. retval += key[i];
  121. return retval;
  122. }
  123. /*=========================================================================
  124. ** find_member
  125. **=========================================================================
  126. ** Get the index of the member with the specified key, or -1 if no such
  127. ** member exists.
  128. */
  129. static int
  130. find_member(xmlrpc_value * const strctP,
  131. const char * const key,
  132. size_t const key_len) {
  133. size_t size, i;
  134. unsigned char hash;
  135. _struct_member *contents;
  136. xmlrpc_value *keyval;
  137. char *keystr;
  138. size_t keystr_size;
  139. XMLRPC_ASSERT_VALUE_OK(strctP);
  140. XMLRPC_ASSERT(key != NULL);
  141. /* Look for our key. */
  142. hash = get_hash(key, key_len);
  143. size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strctP->_block);
  144. contents = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
  145. for (i = 0; i < size; i++) {
  146. if (contents[i].key_hash == hash) {
  147. keyval = contents[i].key;
  148. keystr = XMLRPC_MEMBLOCK_CONTENTS(char, &keyval->_block);
  149. keystr_size = XMLRPC_MEMBLOCK_SIZE(char, &keyval->_block)-1;
  150. if (key_len == keystr_size && memcmp(key, keystr, key_len) == 0)
  151. return i;
  152. }
  153. }
  154. return -1;
  155. }
  156. /*=========================================================================
  157. ** xmlrpc_struct_has_key
  158. **=========================================================================
  159. */
  160. int
  161. xmlrpc_struct_has_key(xmlrpc_env * const envP,
  162. xmlrpc_value * const strctP,
  163. const char * const key) {
  164. XMLRPC_ASSERT(key != NULL);
  165. return xmlrpc_struct_has_key_n(envP, strctP, key, strlen(key));
  166. }
  167. int
  168. xmlrpc_struct_has_key_n(xmlrpc_env * const envP,
  169. xmlrpc_value * const strctP,
  170. const char * const key,
  171. size_t const key_len) {
  172. int xmIndex;
  173. /* Suppress a compiler warning about uninitialized variables. */
  174. xmIndex = 0;
  175. XMLRPC_ASSERT_ENV_OK(envP);
  176. XMLRPC_ASSERT_VALUE_OK(strctP);
  177. XMLRPC_ASSERT(key != NULL);
  178. XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
  179. xmIndex = find_member(strctP, key, key_len);
  180. cleanup:
  181. if (envP->fault_occurred)
  182. return 0;
  183. return (xmIndex >= 0);
  184. }
  185. /*=========================================================================
  186. ** xmlrpc_struct_find_value...
  187. **=========================================================================
  188. ** These functions look up a specified key value in a specified struct.
  189. ** If it exists, they return the value of the struct member. If not,
  190. ** they return a NULL to indicate such.
  191. */
  192. /* It would be a nice extension to be able to look up a key that is
  193. not a text string.
  194. */
  195. void
  196. xmlrpc_struct_find_value(xmlrpc_env * const envP,
  197. xmlrpc_value * const structP,
  198. const char * const key,
  199. xmlrpc_value ** const valuePP) {
  200. /*----------------------------------------------------------------------------
  201. Given a key, retrieve a value from the struct. If the key is not
  202. present, return NULL as *valuePP.
  203. -----------------------------------------------------------------------------*/
  204. XMLRPC_ASSERT_ENV_OK(envP);
  205. XMLRPC_ASSERT_VALUE_OK(structP);
  206. XMLRPC_ASSERT_PTR_OK(key);
  207. if (structP->_type != XMLRPC_TYPE_STRUCT)
  208. xmlrpc_env_set_fault_formatted(
  209. envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d",
  210. structP->_type);
  211. else {
  212. int xmIndex;
  213. /* Get our member index. */
  214. xmIndex = find_member(structP, key, strlen(key));
  215. if (xmIndex < 0)
  216. *valuePP = NULL;
  217. else {
  218. _struct_member * const members =
  219. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  220. *valuePP = members[xmIndex].value;
  221. XMLRPC_ASSERT_VALUE_OK(*valuePP);
  222. xmlrpc_INCREF(*valuePP);
  223. }
  224. }
  225. }
  226. void
  227. xmlrpc_struct_find_value_v(xmlrpc_env * const envP,
  228. xmlrpc_value * const structP,
  229. xmlrpc_value * const keyP,
  230. xmlrpc_value ** const valuePP) {
  231. /*----------------------------------------------------------------------------
  232. Given a key, retrieve a value from the struct. If the key is not
  233. present, return NULL as *valuePP.
  234. -----------------------------------------------------------------------------*/
  235. XMLRPC_ASSERT_ENV_OK(envP);
  236. XMLRPC_ASSERT_VALUE_OK(structP);
  237. XMLRPC_ASSERT_VALUE_OK(keyP);
  238. if (structP->_type != XMLRPC_TYPE_STRUCT)
  239. xmlrpc_env_set_fault_formatted(
  240. envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d",
  241. structP->_type);
  242. else {
  243. if (keyP->_type != XMLRPC_TYPE_STRING)
  244. xmlrpc_env_set_fault_formatted(
  245. envP, XMLRPC_TYPE_ERROR, "Key value is not a string. "
  246. "It is type #%d",
  247. keyP->_type);
  248. else {
  249. int xmIndex;
  250. /* Get our member index. */
  251. xmIndex = find_member(structP,
  252. XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block),
  253. XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block)-1);
  254. if (xmIndex < 0)
  255. *valuePP = NULL;
  256. else {
  257. _struct_member * const members =
  258. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  259. *valuePP = members[xmIndex].value;
  260. XMLRPC_ASSERT_VALUE_OK(*valuePP);
  261. xmlrpc_INCREF(*valuePP);
  262. }
  263. }
  264. }
  265. }
  266. /*=========================================================================
  267. ** xmlrpc_struct_read_value...
  268. **=========================================================================
  269. ** These fail if no member with the specified key exists.
  270. ** Otherwise, they are the same as xmlrpc_struct_find_value...
  271. */
  272. void
  273. xmlrpc_struct_read_value_v(xmlrpc_env * const envP,
  274. xmlrpc_value * const structP,
  275. xmlrpc_value * const keyP,
  276. xmlrpc_value ** const valuePP) {
  277. xmlrpc_struct_find_value_v(envP, structP, keyP, valuePP);
  278. if (!envP->fault_occurred) {
  279. if (*valuePP == NULL) {
  280. xmlrpc_env_set_fault_formatted(
  281. envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%.*s'",
  282. XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block),
  283. XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block));
  284. }
  285. }
  286. }
  287. void
  288. xmlrpc_struct_read_value(xmlrpc_env * const envP,
  289. xmlrpc_value * const structP,
  290. const char * const key,
  291. xmlrpc_value ** const valuePP) {
  292. xmlrpc_struct_find_value(envP, structP, key, valuePP);
  293. if (!envP->fault_occurred) {
  294. if (*valuePP == NULL) {
  295. xmlrpc_env_set_fault_formatted(
  296. envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%s'",
  297. key);
  298. /* We should fix the error message to format the key for display */
  299. }
  300. }
  301. }
  302. /*=========================================================================
  303. ** xmlrpc_struct_get_value...
  304. **=========================================================================
  305. ** These are for backward compatibility. They used to be the only ones.
  306. ** They're deprecated because they don't acquire a reference to the
  307. ** value they return.
  308. */
  309. xmlrpc_value *
  310. xmlrpc_struct_get_value_n(xmlrpc_env * const envP,
  311. xmlrpc_value * const structP,
  312. const char * const key,
  313. size_t const keyLen) {
  314. xmlrpc_value * retval;
  315. xmlrpc_value * keyP;
  316. keyP = xmlrpc_build_value(envP, "s#", key, keyLen);
  317. if (!envP->fault_occurred) {
  318. xmlrpc_struct_find_value_v(envP, structP, keyP, &retval);
  319. if (!envP->fault_occurred) {
  320. if (retval == NULL) {
  321. xmlrpc_env_set_fault_formatted(
  322. envP, XMLRPC_INDEX_ERROR,
  323. "No member of struct has key '%.*s'",
  324. keyLen, key);
  325. /* We should fix the error message to format the key
  326. for display */
  327. } else
  328. /* For backward compatibility. */
  329. xmlrpc_DECREF(retval);
  330. }
  331. xmlrpc_DECREF(keyP);
  332. }
  333. return retval;
  334. }
  335. xmlrpc_value *
  336. xmlrpc_struct_get_value(xmlrpc_env * const envP,
  337. xmlrpc_value * const strctP,
  338. const char * const key) {
  339. XMLRPC_ASSERT(key != NULL);
  340. return xmlrpc_struct_get_value_n(envP, strctP, key, strlen(key));
  341. }
  342. /*=========================================================================
  343. ** xmlrpc_struct_set_value
  344. **=========================================================================
  345. */
  346. void
  347. xmlrpc_struct_set_value(xmlrpc_env * const envP,
  348. xmlrpc_value * const strctP,
  349. const char * const key,
  350. xmlrpc_value * const valueP) {
  351. XMLRPC_ASSERT(key != NULL);
  352. xmlrpc_struct_set_value_n(envP, strctP, key, strlen(key), valueP);
  353. }
  354. void
  355. xmlrpc_struct_set_value_n(xmlrpc_env * const envP,
  356. xmlrpc_value * const strctP,
  357. const char * const key,
  358. size_t const key_len,
  359. xmlrpc_value * const valueP) {
  360. xmlrpc_value *keyval;
  361. XMLRPC_ASSERT_ENV_OK(envP);
  362. XMLRPC_ASSERT(key != NULL);
  363. /* Set up error handling preconditions. */
  364. keyval = NULL;
  365. XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
  366. /* Build an xmlrpc_value from our string. */
  367. keyval = xmlrpc_build_value(envP, "s#", key, key_len);
  368. XMLRPC_FAIL_IF_FAULT(envP);
  369. /* Do the actual work. */
  370. xmlrpc_struct_set_value_v(envP, strctP, keyval, valueP);
  371. cleanup:
  372. if (keyval)
  373. xmlrpc_DECREF(keyval);
  374. }
  375. void
  376. xmlrpc_struct_set_value_v(xmlrpc_env * const envP,
  377. xmlrpc_value * const strctP,
  378. xmlrpc_value * const keyvalP,
  379. xmlrpc_value * const valueP) {
  380. char *key;
  381. size_t key_len;
  382. int xmIndex;
  383. _struct_member *members, *member, new_member;
  384. xmlrpc_value *old_value;
  385. XMLRPC_ASSERT_ENV_OK(envP);
  386. XMLRPC_ASSERT_VALUE_OK(strctP);
  387. XMLRPC_ASSERT_VALUE_OK(keyvalP);
  388. XMLRPC_ASSERT_VALUE_OK(valueP);
  389. XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
  390. XMLRPC_TYPE_CHECK(envP, keyvalP, XMLRPC_TYPE_STRING);
  391. key = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block);
  392. key_len = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block) - 1;
  393. xmIndex = find_member(strctP, key, key_len);
  394. if (xmIndex >= 0) {
  395. /* Change the value of an existing member. (But be careful--the
  396. ** original and new values might be the same object, so watch
  397. ** the order of INCREF and DECREF calls!) */
  398. members = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
  399. member = &members[xmIndex];
  400. /* Juggle our references. */
  401. old_value = member->value;
  402. member->value = valueP;
  403. xmlrpc_INCREF(member->value);
  404. xmlrpc_DECREF(old_value);
  405. } else {
  406. /* Add a new member. */
  407. new_member.key_hash = get_hash(key, key_len);
  408. new_member.key = keyvalP;
  409. new_member.value = valueP;
  410. XMLRPC_MEMBLOCK_APPEND(_struct_member, envP, &strctP->_block,
  411. &new_member, 1);
  412. XMLRPC_FAIL_IF_FAULT(envP);
  413. xmlrpc_INCREF(keyvalP);
  414. xmlrpc_INCREF(valueP);
  415. }
  416. cleanup:
  417. return;
  418. }
  419. /* Note that the order of keys and values is undefined, and may change
  420. when you modify the struct.
  421. */
  422. void
  423. xmlrpc_struct_read_member(xmlrpc_env * const envP,
  424. xmlrpc_value * const structP,
  425. unsigned int const xmIndex,
  426. xmlrpc_value ** const keyvalP,
  427. xmlrpc_value ** const valueP) {
  428. XMLRPC_ASSERT_ENV_OK(envP);
  429. XMLRPC_ASSERT_VALUE_OK(structP);
  430. XMLRPC_ASSERT_PTR_OK(keyvalP);
  431. XMLRPC_ASSERT_PTR_OK(valueP);
  432. if (structP->_type != XMLRPC_TYPE_STRUCT)
  433. xmlrpc_env_set_fault_formatted(
  434. envP, XMLRPC_TYPE_ERROR, "Attempt to read a struct member "
  435. "of something that is not a struct");
  436. else {
  437. _struct_member * const members =
  438. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  439. size_t const size =
  440. XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block);
  441. if (xmIndex >= size)
  442. xmlrpc_env_set_fault_formatted(
  443. envP, XMLRPC_INDEX_ERROR, "Index %u is beyond the end of "
  444. "the %u-member structure", xmIndex, (unsigned int)size);
  445. else {
  446. _struct_member * const memberP = &members[xmIndex];
  447. *keyvalP = memberP->key;
  448. xmlrpc_INCREF(memberP->key);
  449. *valueP = memberP->value;
  450. xmlrpc_INCREF(memberP->value);
  451. }
  452. }
  453. }
  454. void
  455. xmlrpc_struct_get_key_and_value(xmlrpc_env * const envP,
  456. xmlrpc_value * const structP,
  457. int const xmIndex,
  458. xmlrpc_value ** const keyvalP,
  459. xmlrpc_value ** const valueP) {
  460. /*----------------------------------------------------------------------------
  461. Same as xmlrpc_struct_read_member(), except doesn't take a reference
  462. to the returned value.
  463. This is obsolete.
  464. -----------------------------------------------------------------------------*/
  465. XMLRPC_ASSERT_ENV_OK(envP);
  466. XMLRPC_ASSERT_VALUE_OK(structP);
  467. XMLRPC_ASSERT_PTR_OK(keyvalP);
  468. XMLRPC_ASSERT_PTR_OK(valueP);
  469. if (xmIndex < 0)
  470. xmlrpc_env_set_fault_formatted(
  471. envP, XMLRPC_INDEX_ERROR, "Index %d is negative.");
  472. else {
  473. xmlrpc_struct_read_member(envP, structP, xmIndex, keyvalP, valueP);
  474. if (!envP->fault_occurred) {
  475. xmlrpc_DECREF(*keyvalP);
  476. xmlrpc_DECREF(*valueP);
  477. }
  478. }
  479. if (envP->fault_occurred) {
  480. *keyvalP = NULL;
  481. *valueP = NULL;
  482. }
  483. }