initial load of upstream version 1.06.32
[xmlrpc-c] / src / xmlrpc_array.c
1 /* Copyright information is at the end of the file */
2
3 /*=========================================================================
4 **  XML-RPC Array Functions
5 **=========================================================================
6 */
7
8 #include "xmlrpc_config.h"
9
10 #include <stddef.h>
11 #include <stdlib.h>
12
13 #include "xmlrpc-c/util.h"
14 #include "xmlrpc-c/base.h"
15 #include "xmlrpc-c/base_int.h"
16
17
18
19 void
20 xmlrpc_abort_if_array_bad(xmlrpc_value * const arrayP) {
21
22     if (arrayP == NULL)
23         abort();
24     else if (arrayP->_type != XMLRPC_TYPE_ARRAY)
25         abort();
26     else {
27         unsigned int const arraySize =
28             XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block);
29         xmlrpc_value ** const contents = 
30             XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block);
31         
32         if (contents == NULL)
33             abort();
34         else {
35             unsigned int index;
36             
37             for (index = 0; index < arraySize; ++index) {
38                 xmlrpc_value * const itemP = contents[index];
39                 if (itemP == NULL)
40                     abort();
41                 else if (itemP->_refcount < 1)
42                     abort();
43             }
44         }
45     }
46 }
47
48
49
50 void
51 xmlrpc_destroyArrayContents(xmlrpc_value * const arrayP) {
52 /*----------------------------------------------------------------------------
53    Dispose of the contents of an array (but not the array value itself).
54    The value is not valid after this.
55 -----------------------------------------------------------------------------*/
56     unsigned int const arraySize =
57         XMLRPC_MEMBLOCK_SIZE(xmlrpc_value*, &arrayP->_block);
58     xmlrpc_value ** const contents = 
59         XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block);
60
61     unsigned int index;
62     
63     XMLRPC_ASSERT_ARRAY_OK(arrayP);
64
65     /* Release our reference to each item in the array */
66     for (index = 0; index < arraySize; ++index) {
67         xmlrpc_value * const itemP = contents[index];
68         xmlrpc_DECREF(itemP);
69     }
70     XMLRPC_MEMBLOCK_CLEAN(xmlrpc_value *, &arrayP->_block);
71 }
72
73
74
75 int 
76 xmlrpc_array_size(xmlrpc_env *         const env, 
77                   const xmlrpc_value * const array) {
78
79     int retval;
80
81     /* Suppress a compiler warning about uninitialized variables. */
82     retval = 0;
83
84     XMLRPC_ASSERT_ENV_OK(env);
85     XMLRPC_ASSERT_VALUE_OK(array);
86     XMLRPC_TYPE_CHECK(env, array, XMLRPC_TYPE_ARRAY);
87
88     retval = XMLRPC_TYPED_MEM_BLOCK_SIZE(xmlrpc_value*, &array->_block);
89
90                   cleanup:
91     if (env->fault_occurred)
92         return -1;
93     else
94         return retval;
95 }
96
97
98
99 void 
100 xmlrpc_array_append_item(xmlrpc_env *   const envP,
101                          xmlrpc_value * const arrayP,
102                          xmlrpc_value * const valueP) {
103
104     XMLRPC_ASSERT_ENV_OK(envP);
105     XMLRPC_ASSERT_VALUE_OK(arrayP);
106     
107     if (xmlrpc_value_type(arrayP) != XMLRPC_TYPE_ARRAY)
108         xmlrpc_env_set_fault_formatted(
109             envP, XMLRPC_TYPE_ERROR, "Value is not an array");
110     else {
111         size_t const size = 
112             XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block);
113
114         XMLRPC_MEMBLOCK_RESIZE(xmlrpc_value *, envP, &arrayP->_block, size+1);
115
116         if (!envP->fault_occurred) {
117             xmlrpc_value ** const contents =
118                 XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value*, &arrayP->_block);
119             xmlrpc_INCREF(valueP);
120             contents[size] = valueP;
121         }
122     }
123 }
124
125
126
127 void
128 xmlrpc_array_read_item(xmlrpc_env *         const envP,
129                        const xmlrpc_value * const arrayP,
130                        unsigned int         const index,
131                        xmlrpc_value **      const valuePP) {
132
133     XMLRPC_ASSERT_ENV_OK(envP);
134     XMLRPC_ASSERT_VALUE_OK(arrayP);
135     XMLRPC_ASSERT_PTR_OK(valuePP);
136
137     if (arrayP->_type != XMLRPC_TYPE_ARRAY)
138         xmlrpc_env_set_fault_formatted(
139             envP, XMLRPC_TYPE_ERROR, "Attempt to read array item from "
140             "a value that is not an array");
141     else {
142         xmlrpc_value ** const contents = 
143             XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value *, &arrayP->_block);
144         size_t const size = 
145             XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block);
146
147         if (index >= size)
148             xmlrpc_env_set_fault_formatted(
149                 envP, XMLRPC_INDEX_ERROR, "Array index %u is beyond end "
150                 "of %u-item array", index, (unsigned int)size);
151         else {
152             *valuePP = contents[index];
153             xmlrpc_INCREF(*valuePP);
154         }
155     }
156 }
157
158
159
160 xmlrpc_value * 
161 xmlrpc_array_get_item(xmlrpc_env *         const envP,
162                       const xmlrpc_value * const arrayP,
163                       int                  const indexArg) {
164
165     /* We must maintain the historical thread-safeness of
166        xmlrpc_array_get_item().  That means we can't call
167        xmlrpc_read_array(), because it modifies the reference count
168        of its arguments, thus is not thread-safe.
169
170        The Xmlrpc-c method registry is an example of an application that
171        relies on thread-safeness of xmlrpc_array_get_item() -- it uses
172        xmlrpc_value's to represent the registry, and multiple server
173        threads read the registry simultaneously.
174     */
175
176     xmlrpc_value * valueP;
177
178     XMLRPC_ASSERT_ENV_OK(envP);
179     XMLRPC_ASSERT_VALUE_OK(arrayP);
180
181     valueP = NULL;
182
183     if (indexArg < 0)
184         xmlrpc_env_set_fault_formatted(
185             envP, XMLRPC_INDEX_ERROR, "Index %d is negative.", indexArg);
186     else {
187         unsigned int const index = indexArg;
188
189         if (arrayP->_type != XMLRPC_TYPE_ARRAY)
190             xmlrpc_env_set_fault_formatted(
191                 envP, XMLRPC_TYPE_ERROR, "Attempt to read array item from "
192                 "a value that is not an array");
193         else {
194             xmlrpc_value ** const contents = 
195                 XMLRPC_MEMBLOCK_CONTENTS(xmlrpc_value *, &arrayP->_block);
196             size_t const size = 
197                 XMLRPC_MEMBLOCK_SIZE(xmlrpc_value *, &arrayP->_block);
198
199             if (index >= size)
200                 xmlrpc_env_set_fault_formatted(
201                     envP, XMLRPC_INDEX_ERROR, "Array index %u is beyond end "
202                     "of %u-item array", index, (unsigned int)size);
203             else
204                 valueP = contents[index];
205         }
206     }
207     return valueP;
208 }
209
210
211
212 xmlrpc_value *
213 xmlrpc_array_new(xmlrpc_env * const envP) {
214 /*----------------------------------------------------------------------------
215    Create an empty array xmlrpc_value.
216 -----------------------------------------------------------------------------*/
217     xmlrpc_value * arrayP;
218
219     xmlrpc_createXmlrpcValue(envP, &arrayP);
220     if (!envP->fault_occurred) {
221         arrayP->_type = XMLRPC_TYPE_ARRAY;
222         XMLRPC_MEMBLOCK_INIT(xmlrpc_value*, envP, &arrayP->_block, 0);
223         if (envP->fault_occurred)
224             free(arrayP);
225     }
226     return arrayP;
227 }
228
229
230
231 /* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
232 ** Copyright (C) 2001 by Eric Kidd. All rights reserved.
233 **
234 ** Redistribution and use in source and binary forms, with or without
235 ** modification, are permitted provided that the following conditions
236 ** are met:
237 ** 1. Redistributions of source code must retain the above copyright
238 **    notice, this list of conditions and the following disclaimer.
239 ** 2. Redistributions in binary form must reproduce the above copyright
240 **    notice, this list of conditions and the following disclaimer in the
241 **    documentation and/or other materials provided with the distribution.
242 ** 3. The name of the author may not be used to endorse or promote products
243 **    derived from this software without specific prior written permission. 
244 **  
245 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
246 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
247 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
249 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
250 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
252 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
253 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
254 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255 ** SUCH DAMAGE. */