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 30static 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) 41struct 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 49static 50int 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 64svn_error_t * 65svn_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 139svn_error_t * 140svn_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. */ 181svn_error_t * 182svn_iter__break(void) 183{ 184 return &internal_break_error; 185} 186 187#if !APR_VERSION_AT_LEAST(1, 5, 0) 188const void *apr_hash_this_key(apr_hash_index_t *hi) 189{ 190 const void *key; 191 192 apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL); 193 return key; 194} 195 196apr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi) 197{ 198 apr_ssize_t klen; 199 200 apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL); 201 return klen; 202} 203 204void *apr_hash_this_val(apr_hash_index_t *hi) 205{ 206 void *val; 207 208 apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val); 209 return val; 210} 211#endif 212