xmlrpc_struct.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  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_valid = 0;
  63. /* Allocate and fill out an empty structure. */
  64. strct = (xmlrpc_value*) malloc(sizeof(xmlrpc_value));
  65. XMLRPC_FAIL_IF_NULL(strct, env, XMLRPC_INTERNAL_ERROR,
  66. "Could not allocate memory for struct");
  67. strct->_refcount = 1;
  68. strct->_type = XMLRPC_TYPE_STRUCT;
  69. XMLRPC_MEMBLOCK_INIT(_struct_member, env, &strct->_block, 0);
  70. XMLRPC_FAIL_IF_FAULT(env);
  71. strct_valid = 1;
  72. cleanup:
  73. if (env->fault_occurred) {
  74. if (strct) {
  75. if (strct_valid)
  76. xmlrpc_DECREF(strct);
  77. else
  78. free(strct);
  79. }
  80. return NULL;
  81. }
  82. return strct;
  83. }
  84. /*=========================================================================
  85. ** xmlrpc_struct_size
  86. **=========================================================================
  87. ** Return the number of key-value pairs contained in the struct. If the
  88. ** value is not a struct, return -1 and set a fault.
  89. */
  90. int
  91. xmlrpc_struct_size(xmlrpc_env* env, xmlrpc_value* strct)
  92. {
  93. int retval;
  94. /* Suppress a compiler warning about uninitialized variables. */
  95. retval = 0;
  96. XMLRPC_ASSERT_ENV_OK(env);
  97. XMLRPC_ASSERT_VALUE_OK(strct);
  98. XMLRPC_TYPE_CHECK(env, strct, XMLRPC_TYPE_STRUCT);
  99. retval = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strct->_block);
  100. cleanup:
  101. if (env->fault_occurred)
  102. return -1;
  103. return retval;
  104. }
  105. /*=========================================================================
  106. ** get_hash
  107. **=========================================================================
  108. ** A mindlessly simple hash function. Please feel free to write something
  109. ** more clever if this produces bad results.
  110. */
  111. static unsigned char
  112. get_hash(const char * const key,
  113. size_t const key_len) {
  114. unsigned char retval;
  115. size_t i;
  116. XMLRPC_ASSERT(key != NULL);
  117. retval = 0;
  118. for (i = 0; i < key_len; i++)
  119. retval += key[i];
  120. return retval;
  121. }
  122. /*=========================================================================
  123. ** find_member
  124. **=========================================================================
  125. ** Get the index of the member with the specified key, or -1 if no such
  126. ** member exists.
  127. */
  128. static int
  129. find_member(xmlrpc_value * const strctP,
  130. const char * const key,
  131. size_t const key_len) {
  132. size_t size, i;
  133. unsigned char hash;
  134. _struct_member *contents;
  135. xmlrpc_value *keyval;
  136. char *keystr;
  137. size_t keystr_size;
  138. XMLRPC_ASSERT_VALUE_OK(strctP);
  139. XMLRPC_ASSERT(key != NULL);
  140. /* Look for our key. */
  141. hash = get_hash(key, key_len);
  142. size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &strctP->_block);
  143. contents = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
  144. for (i = 0; i < size; i++) {
  145. if (contents[i].key_hash == hash) {
  146. keyval = contents[i].key;
  147. keystr = XMLRPC_MEMBLOCK_CONTENTS(char, &keyval->_block);
  148. keystr_size = XMLRPC_MEMBLOCK_SIZE(char, &keyval->_block)-1;
  149. if (key_len == keystr_size && memcmp(key, keystr, key_len) == 0)
  150. return i;
  151. }
  152. }
  153. return -1;
  154. }
  155. /*=========================================================================
  156. ** xmlrpc_struct_has_key
  157. **=========================================================================
  158. */
  159. int
  160. xmlrpc_struct_has_key(xmlrpc_env * const envP,
  161. xmlrpc_value * const strctP,
  162. const char * const key) {
  163. XMLRPC_ASSERT(key != NULL);
  164. return xmlrpc_struct_has_key_n(envP, strctP, key, strlen(key));
  165. }
  166. int
  167. xmlrpc_struct_has_key_n(xmlrpc_env * const envP,
  168. xmlrpc_value * const strctP,
  169. const char * const key,
  170. size_t const key_len) {
  171. int xmIndex;
  172. /* Suppress a compiler warning about uninitialized variables. */
  173. xmIndex = 0;
  174. XMLRPC_ASSERT_ENV_OK(envP);
  175. XMLRPC_ASSERT_VALUE_OK(strctP);
  176. XMLRPC_ASSERT(key != NULL);
  177. XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
  178. xmIndex = find_member(strctP, key, key_len);
  179. cleanup:
  180. if (envP->fault_occurred)
  181. return 0;
  182. return (xmIndex >= 0);
  183. }
  184. /*=========================================================================
  185. ** xmlrpc_struct_find_value...
  186. **=========================================================================
  187. ** These functions look up a specified key value in a specified struct.
  188. ** If it exists, they return the value of the struct member. If not,
  189. ** they return a NULL to indicate such.
  190. */
  191. /* It would be a nice extension to be able to look up a key that is
  192. not a text string.
  193. */
  194. void
  195. xmlrpc_struct_find_value(xmlrpc_env * const envP,
  196. xmlrpc_value * const structP,
  197. const char * const key,
  198. xmlrpc_value ** const valuePP) {
  199. /*----------------------------------------------------------------------------
  200. Given a key, retrieve a value from the struct. If the key is not
  201. present, return NULL as *valuePP.
  202. -----------------------------------------------------------------------------*/
  203. XMLRPC_ASSERT_ENV_OK(envP);
  204. XMLRPC_ASSERT_VALUE_OK(structP);
  205. XMLRPC_ASSERT_PTR_OK(key);
  206. if (structP->_type != XMLRPC_TYPE_STRUCT)
  207. xmlrpc_env_set_fault_formatted(
  208. envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d",
  209. structP->_type);
  210. else {
  211. int xmIndex;
  212. /* Get our member index. */
  213. xmIndex = find_member(structP, key, strlen(key));
  214. if (xmIndex < 0)
  215. *valuePP = NULL;
  216. else {
  217. _struct_member * const members =
  218. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  219. *valuePP = members[xmIndex].value;
  220. XMLRPC_ASSERT_VALUE_OK(*valuePP);
  221. xmlrpc_INCREF(*valuePP);
  222. }
  223. }
  224. }
  225. void
  226. xmlrpc_struct_find_value_v(xmlrpc_env * const envP,
  227. xmlrpc_value * const structP,
  228. xmlrpc_value * const keyP,
  229. xmlrpc_value ** const valuePP) {
  230. /*----------------------------------------------------------------------------
  231. Given a key, retrieve a value from the struct. If the key is not
  232. present, return NULL as *valuePP.
  233. -----------------------------------------------------------------------------*/
  234. XMLRPC_ASSERT_ENV_OK(envP);
  235. XMLRPC_ASSERT_VALUE_OK(structP);
  236. XMLRPC_ASSERT_VALUE_OK(keyP);
  237. if (structP->_type != XMLRPC_TYPE_STRUCT)
  238. xmlrpc_env_set_fault_formatted(
  239. envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d",
  240. structP->_type);
  241. else {
  242. if (keyP->_type != XMLRPC_TYPE_STRING)
  243. xmlrpc_env_set_fault_formatted(
  244. envP, XMLRPC_TYPE_ERROR, "Key value is not a string. "
  245. "It is type #%d",
  246. keyP->_type);
  247. else {
  248. int xmIndex;
  249. /* Get our member index. */
  250. xmIndex = find_member(structP,
  251. XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block),
  252. XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block)-1);
  253. if (xmIndex < 0)
  254. *valuePP = NULL;
  255. else {
  256. _struct_member * const members =
  257. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  258. *valuePP = members[xmIndex].value;
  259. XMLRPC_ASSERT_VALUE_OK(*valuePP);
  260. xmlrpc_INCREF(*valuePP);
  261. }
  262. }
  263. }
  264. }
  265. /*=========================================================================
  266. ** xmlrpc_struct_read_value...
  267. **=========================================================================
  268. ** These fail if no member with the specified key exists.
  269. ** Otherwise, they are the same as xmlrpc_struct_find_value...
  270. */
  271. void
  272. xmlrpc_struct_read_value_v(xmlrpc_env * const envP,
  273. xmlrpc_value * const structP,
  274. xmlrpc_value * const keyP,
  275. xmlrpc_value ** const valuePP) {
  276. xmlrpc_struct_find_value_v(envP, structP, keyP, valuePP);
  277. if (!envP->fault_occurred) {
  278. if (*valuePP == NULL) {
  279. xmlrpc_env_set_fault_formatted(
  280. envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%.*s'",
  281. XMLRPC_MEMBLOCK_SIZE(char, &keyP->_block),
  282. XMLRPC_MEMBLOCK_CONTENTS(char, &keyP->_block));
  283. }
  284. }
  285. }
  286. void
  287. xmlrpc_struct_read_value(xmlrpc_env * const envP,
  288. xmlrpc_value * const structP,
  289. const char * const key,
  290. xmlrpc_value ** const valuePP) {
  291. xmlrpc_struct_find_value(envP, structP, key, valuePP);
  292. if (!envP->fault_occurred) {
  293. if (*valuePP == NULL) {
  294. xmlrpc_env_set_fault_formatted(
  295. envP, XMLRPC_INDEX_ERROR, "No member of struct has key '%s'",
  296. key);
  297. /* We should fix the error message to format the key for display */
  298. }
  299. }
  300. }
  301. /*=========================================================================
  302. ** xmlrpc_struct_get_value...
  303. **=========================================================================
  304. ** These are for backward compatibility. They used to be the only ones.
  305. ** They're deprecated because they don't acquire a reference to the
  306. ** value they return.
  307. */
  308. xmlrpc_value *
  309. xmlrpc_struct_get_value_n(xmlrpc_env * const envP,
  310. xmlrpc_value * const structP,
  311. const char * const key,
  312. size_t const keyLen) {
  313. xmlrpc_value * retval;
  314. xmlrpc_value * keyP;
  315. keyP = xmlrpc_build_value(envP, "s#", key, keyLen);
  316. if (!envP->fault_occurred) {
  317. xmlrpc_struct_find_value_v(envP, structP, keyP, &retval);
  318. if (!envP->fault_occurred) {
  319. if (retval == NULL) {
  320. xmlrpc_env_set_fault_formatted(
  321. envP, XMLRPC_INDEX_ERROR,
  322. "No member of struct has key '%.*s'",
  323. keyLen, key);
  324. /* We should fix the error message to format the key
  325. for display */
  326. } else
  327. /* For backward compatibility. */
  328. xmlrpc_DECREF(retval);
  329. }
  330. xmlrpc_DECREF(keyP);
  331. }
  332. return retval;
  333. }
  334. xmlrpc_value *
  335. xmlrpc_struct_get_value(xmlrpc_env * const envP,
  336. xmlrpc_value * const strctP,
  337. const char * const key) {
  338. XMLRPC_ASSERT(key != NULL);
  339. return xmlrpc_struct_get_value_n(envP, strctP, key, strlen(key));
  340. }
  341. /*=========================================================================
  342. ** xmlrpc_struct_set_value
  343. **=========================================================================
  344. */
  345. void
  346. xmlrpc_struct_set_value(xmlrpc_env * const envP,
  347. xmlrpc_value * const strctP,
  348. const char * const key,
  349. xmlrpc_value * const valueP) {
  350. XMLRPC_ASSERT(key != NULL);
  351. xmlrpc_struct_set_value_n(envP, strctP, key, strlen(key), valueP);
  352. }
  353. void
  354. xmlrpc_struct_set_value_n(xmlrpc_env * const envP,
  355. xmlrpc_value * const strctP,
  356. const char * const key,
  357. size_t const key_len,
  358. xmlrpc_value * const valueP) {
  359. xmlrpc_value *keyval;
  360. XMLRPC_ASSERT_ENV_OK(envP);
  361. XMLRPC_ASSERT(key != NULL);
  362. /* Set up error handling preconditions. */
  363. keyval = NULL;
  364. XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
  365. /* Build an xmlrpc_value from our string. */
  366. keyval = xmlrpc_build_value(envP, "s#", key, key_len);
  367. XMLRPC_FAIL_IF_FAULT(envP);
  368. /* Do the actual work. */
  369. xmlrpc_struct_set_value_v(envP, strctP, keyval, valueP);
  370. cleanup:
  371. if (keyval)
  372. xmlrpc_DECREF(keyval);
  373. }
  374. void
  375. xmlrpc_struct_set_value_v(xmlrpc_env * const envP,
  376. xmlrpc_value * const strctP,
  377. xmlrpc_value * const keyvalP,
  378. xmlrpc_value * const valueP) {
  379. char *key;
  380. size_t key_len;
  381. int xmIndex;
  382. _struct_member *members, *member, new_member;
  383. xmlrpc_value *old_value;
  384. XMLRPC_ASSERT_ENV_OK(envP);
  385. XMLRPC_ASSERT_VALUE_OK(strctP);
  386. XMLRPC_ASSERT_VALUE_OK(keyvalP);
  387. XMLRPC_ASSERT_VALUE_OK(valueP);
  388. XMLRPC_TYPE_CHECK(envP, strctP, XMLRPC_TYPE_STRUCT);
  389. XMLRPC_TYPE_CHECK(envP, keyvalP, XMLRPC_TYPE_STRING);
  390. key = XMLRPC_MEMBLOCK_CONTENTS(char, &keyvalP->_block);
  391. key_len = XMLRPC_MEMBLOCK_SIZE(char, &keyvalP->_block) - 1;
  392. xmIndex = find_member(strctP, key, key_len);
  393. if (xmIndex >= 0) {
  394. /* Change the value of an existing member. (But be careful--the
  395. ** original and new values might be the same object, so watch
  396. ** the order of INCREF and DECREF calls!) */
  397. members = XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &strctP->_block);
  398. member = &members[xmIndex];
  399. /* Juggle our references. */
  400. old_value = member->value;
  401. member->value = valueP;
  402. xmlrpc_INCREF(member->value);
  403. xmlrpc_DECREF(old_value);
  404. } else {
  405. /* Add a new member. */
  406. new_member.key_hash = get_hash(key, key_len);
  407. new_member.key = keyvalP;
  408. new_member.value = valueP;
  409. XMLRPC_MEMBLOCK_APPEND(_struct_member, envP, &strctP->_block,
  410. &new_member, 1);
  411. XMLRPC_FAIL_IF_FAULT(envP);
  412. xmlrpc_INCREF(keyvalP);
  413. xmlrpc_INCREF(valueP);
  414. }
  415. cleanup:
  416. return;
  417. }
  418. /* Note that the order of keys and values is undefined, and may change
  419. when you modify the struct.
  420. */
  421. void
  422. xmlrpc_struct_read_member(xmlrpc_env * const envP,
  423. xmlrpc_value * const structP,
  424. unsigned int const xmIndex,
  425. xmlrpc_value ** const keyvalP,
  426. xmlrpc_value ** const valueP) {
  427. XMLRPC_ASSERT_ENV_OK(envP);
  428. XMLRPC_ASSERT_VALUE_OK(structP);
  429. XMLRPC_ASSERT_PTR_OK(keyvalP);
  430. XMLRPC_ASSERT_PTR_OK(valueP);
  431. if (structP->_type != XMLRPC_TYPE_STRUCT)
  432. xmlrpc_env_set_fault_formatted(
  433. envP, XMLRPC_TYPE_ERROR, "Attempt to read a struct member "
  434. "of something that is not a struct");
  435. else {
  436. _struct_member * const members =
  437. XMLRPC_MEMBLOCK_CONTENTS(_struct_member, &structP->_block);
  438. size_t const size =
  439. XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block);
  440. if (xmIndex >= size)
  441. xmlrpc_env_set_fault_formatted(
  442. envP, XMLRPC_INDEX_ERROR, "Index %u is beyond the end of "
  443. "the %u-member structure", xmIndex, (unsigned int)size);
  444. else {
  445. _struct_member * const memberP = &members[xmIndex];
  446. *keyvalP = memberP->key;
  447. xmlrpc_INCREF(memberP->key);
  448. *valueP = memberP->value;
  449. xmlrpc_INCREF(memberP->value);
  450. }
  451. }
  452. }
  453. void
  454. xmlrpc_struct_get_key_and_value(xmlrpc_env * const envP,
  455. xmlrpc_value * const structP,
  456. int const xmIndex,
  457. xmlrpc_value ** const keyvalP,
  458. xmlrpc_value ** const valueP) {
  459. /*----------------------------------------------------------------------------
  460. Same as xmlrpc_struct_read_member(), except doesn't take a reference
  461. to the returned value.
  462. This is obsolete.
  463. -----------------------------------------------------------------------------*/
  464. XMLRPC_ASSERT_ENV_OK(envP);
  465. XMLRPC_ASSERT_VALUE_OK(structP);
  466. XMLRPC_ASSERT_PTR_OK(keyvalP);
  467. XMLRPC_ASSERT_PTR_OK(valueP);
  468. if (xmIndex < 0)
  469. xmlrpc_env_set_fault_formatted(
  470. envP, XMLRPC_INDEX_ERROR, "Index %d is negative.");
  471. else {
  472. xmlrpc_struct_read_member(envP, structP, xmIndex, keyvalP, valueP);
  473. if (!envP->fault_occurred) {
  474. xmlrpc_DECREF(*keyvalP);
  475. xmlrpc_DECREF(*valueP);
  476. }
  477. }
  478. if (envP->fault_occurred) {
  479. *keyvalP = NULL;
  480. *valueP = NULL;
  481. }
  482. }