]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/libsvn_subr/iter.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / subversion / subversion / libsvn_subr / iter.c
1 /* iter.c : iteration drivers
2  *
3  * ====================================================================
4  *    Licensed to the Apache Software Foundation (ASF) under one
5  *    or more contributor license agreements.  See the NOTICE file
6  *    distributed with this work for additional information
7  *    regarding copyright ownership.  The ASF licenses this file
8  *    to you under the Apache License, Version 2.0 (the
9  *    "License"); you may not use this file except in compliance
10  *    with the License.  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *    Unless required by applicable law or agreed to in writing,
15  *    software distributed under the License is distributed on an
16  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  *    KIND, either express or implied.  See the License for the
18  *    specific language governing permissions and limitations
19  *    under the License.
20  * ====================================================================
21  */
22
23
24 #include "svn_iter.h"
25 #include "svn_pools.h"
26 #include "private/svn_dep_compat.h"
27
28 #include "svn_error_codes.h"
29
30 static svn_error_t internal_break_error =
31   {
32     SVN_ERR_ITER_BREAK, /* APR status */
33     NULL, /* message */
34     NULL, /* child error */
35     NULL, /* pool */
36     __FILE__, /* file name */
37     __LINE__ /* line number */
38   };
39
40 #if APR_VERSION_AT_LEAST(1, 4, 0)
41 struct hash_do_baton
42 {
43   void *baton;
44   svn_iter_apr_hash_cb_t func;
45   svn_error_t *err;
46   apr_pool_t *iterpool;
47 };
48
49 static
50 int hash_do_callback(void *baton,
51                      const void *key,
52                      apr_ssize_t klen,
53                      const void *value)
54 {
55   struct hash_do_baton *hdb = baton;
56
57   svn_pool_clear(hdb->iterpool);
58   hdb->err = (*hdb->func)(hdb->baton, key, klen, (void *)value, hdb->iterpool);
59
60   return hdb->err == SVN_NO_ERROR;
61 }
62 #endif
63
64 svn_error_t *
65 svn_iter_apr_hash(svn_boolean_t *completed,
66                   apr_hash_t *hash,
67                   svn_iter_apr_hash_cb_t func,
68                   void *baton,
69                   apr_pool_t *pool)
70 {
71 #if APR_VERSION_AT_LEAST(1, 4, 0)
72   struct hash_do_baton hdb;
73   svn_boolean_t error_received;
74
75   hdb.func = func;
76   hdb.baton = baton;
77   hdb.iterpool = svn_pool_create(pool);
78
79   error_received = !apr_hash_do(hash_do_callback, &hdb, hash);
80
81   svn_pool_destroy(hdb.iterpool);
82
83   if (completed)
84     *completed = !error_received;
85
86   if (!error_received)
87     return SVN_NO_ERROR;
88
89   if (hdb.err->apr_err == SVN_ERR_ITER_BREAK
90         && hdb.err != &internal_break_error)
91     {
92         /* Errors - except those created by svn_iter_break() -
93            need to be cleared when not further propagated. */
94         svn_error_clear(hdb.err);
95
96         hdb.err = SVN_NO_ERROR;
97     }
98
99   return hdb.err;
100 #else
101   svn_error_t *err = SVN_NO_ERROR;
102   apr_pool_t *iterpool = svn_pool_create(pool);
103   apr_hash_index_t *hi;
104
105   for (hi = apr_hash_first(pool, hash);
106        ! err && hi; hi = apr_hash_next(hi))
107     {
108       const void *key;
109       void *val;
110       apr_ssize_t len;
111
112       svn_pool_clear(iterpool);
113
114       apr_hash_this(hi, &key, &len, &val);
115       err = (*func)(baton, key, len, val, iterpool);
116     }
117
118   if (completed)
119     *completed = ! err;
120
121   if (err && err->apr_err == SVN_ERR_ITER_BREAK)
122     {
123       if (err != &internal_break_error)
124         /* Errors - except those created by svn_iter_break() -
125            need to be cleared when not further propagated. */
126         svn_error_clear(err);
127
128       err = SVN_NO_ERROR;
129     }
130
131   /* Clear iterpool, because callers may clear the error but have no way
132      to clear the iterpool with potentially lots of allocated memory */
133   svn_pool_destroy(iterpool);
134
135   return err;
136 #endif
137 }
138
139 svn_error_t *
140 svn_iter_apr_array(svn_boolean_t *completed,
141                    const apr_array_header_t *array,
142                    svn_iter_apr_array_cb_t func,
143                    void *baton,
144                    apr_pool_t *pool)
145 {
146   svn_error_t *err = SVN_NO_ERROR;
147   apr_pool_t *iterpool = svn_pool_create(pool);
148   int i;
149
150   for (i = 0; (! err) && i < array->nelts; ++i)
151     {
152       void *item = array->elts + array->elt_size*i;
153
154       svn_pool_clear(iterpool);
155
156       err = (*func)(baton, item, iterpool);
157     }
158
159   if (completed)
160     *completed = ! err;
161
162   if (err && err->apr_err == SVN_ERR_ITER_BREAK)
163     {
164       if (err != &internal_break_error)
165         /* Errors - except those created by svn_iter_break() -
166            need to be cleared when not further propagated. */
167         svn_error_clear(err);
168
169       err = SVN_NO_ERROR;
170     }
171
172   /* Clear iterpool, because callers may clear the error but have no way
173      to clear the iterpool with potentially lots of allocated memory */
174   svn_pool_destroy(iterpool);
175
176   return err;
177 }
178
179 /* Note: Although this is a "__" function, it is in the public ABI, so
180  * we can never remove it or change its signature. */
181 svn_error_t *
182 svn_iter__break(void)
183 {
184   return &internal_break_error;
185 }
186
187 /* Note about the type casts:  apr_hash_this() does not expect a const hash
188  * index pointer even though it does not modify the hash index.  In
189  * Subversion we're trying to be const-correct, so these functions all take
190  * a const hash index and we cast away the const when passing it down to
191  * APR.  (A compiler may warn about casting away 'const', but at least this
192  * cast is explicit and gathered in one place.) */
193
194 const void *svn__apr_hash_index_key(const apr_hash_index_t *hi)
195 {
196   const void *key;
197
198   apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL);
199   return key;
200 }
201
202 apr_ssize_t svn__apr_hash_index_klen(const apr_hash_index_t *hi)
203 {
204   apr_ssize_t klen;
205
206   apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL);
207   return klen;
208 }
209
210 void *svn__apr_hash_index_val(const apr_hash_index_t *hi)
211 {
212   void *val;
213
214   apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val);
215   return val;
216 }