1251881Speter/* iter.c : iteration drivers 2251881Speter * 3251881Speter * ==================================================================== 4251881Speter * Licensed to the Apache Software Foundation (ASF) under one 5251881Speter * or more contributor license agreements. See the NOTICE file 6251881Speter * distributed with this work for additional information 7251881Speter * regarding copyright ownership. The ASF licenses this file 8251881Speter * to you under the Apache License, Version 2.0 (the 9251881Speter * "License"); you may not use this file except in compliance 10251881Speter * with the License. You may obtain a copy of the License at 11251881Speter * 12251881Speter * http://www.apache.org/licenses/LICENSE-2.0 13251881Speter * 14251881Speter * Unless required by applicable law or agreed to in writing, 15251881Speter * software distributed under the License is distributed on an 16251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17251881Speter * KIND, either express or implied. See the License for the 18251881Speter * specific language governing permissions and limitations 19251881Speter * under the License. 20251881Speter * ==================================================================== 21251881Speter */ 22251881Speter 23251881Speter 24251881Speter#include "svn_iter.h" 25251881Speter#include "svn_pools.h" 26251881Speter#include "private/svn_dep_compat.h" 27251881Speter 28251881Speter#include "svn_error_codes.h" 29251881Speter 30251881Speterstatic svn_error_t internal_break_error = 31251881Speter { 32251881Speter SVN_ERR_ITER_BREAK, /* APR status */ 33251881Speter NULL, /* message */ 34251881Speter NULL, /* child error */ 35251881Speter NULL, /* pool */ 36251881Speter __FILE__, /* file name */ 37251881Speter __LINE__ /* line number */ 38251881Speter }; 39251881Speter 40251881Speter#if APR_VERSION_AT_LEAST(1, 4, 0) 41251881Speterstruct hash_do_baton 42251881Speter{ 43251881Speter void *baton; 44251881Speter svn_iter_apr_hash_cb_t func; 45251881Speter svn_error_t *err; 46251881Speter apr_pool_t *iterpool; 47251881Speter}; 48251881Speter 49251881Speterstatic 50251881Speterint hash_do_callback(void *baton, 51251881Speter const void *key, 52251881Speter apr_ssize_t klen, 53251881Speter const void *value) 54251881Speter{ 55251881Speter struct hash_do_baton *hdb = baton; 56251881Speter 57251881Speter svn_pool_clear(hdb->iterpool); 58251881Speter hdb->err = (*hdb->func)(hdb->baton, key, klen, (void *)value, hdb->iterpool); 59251881Speter 60251881Speter return hdb->err == SVN_NO_ERROR; 61251881Speter} 62251881Speter#endif 63251881Speter 64251881Spetersvn_error_t * 65251881Spetersvn_iter_apr_hash(svn_boolean_t *completed, 66251881Speter apr_hash_t *hash, 67251881Speter svn_iter_apr_hash_cb_t func, 68251881Speter void *baton, 69251881Speter apr_pool_t *pool) 70251881Speter{ 71251881Speter#if APR_VERSION_AT_LEAST(1, 4, 0) 72251881Speter struct hash_do_baton hdb; 73251881Speter svn_boolean_t error_received; 74251881Speter 75251881Speter hdb.func = func; 76251881Speter hdb.baton = baton; 77251881Speter hdb.iterpool = svn_pool_create(pool); 78251881Speter 79251881Speter error_received = !apr_hash_do(hash_do_callback, &hdb, hash); 80251881Speter 81251881Speter svn_pool_destroy(hdb.iterpool); 82251881Speter 83251881Speter if (completed) 84251881Speter *completed = !error_received; 85251881Speter 86251881Speter if (!error_received) 87251881Speter return SVN_NO_ERROR; 88251881Speter 89251881Speter if (hdb.err->apr_err == SVN_ERR_ITER_BREAK 90251881Speter && hdb.err != &internal_break_error) 91251881Speter { 92251881Speter /* Errors - except those created by svn_iter_break() - 93251881Speter need to be cleared when not further propagated. */ 94251881Speter svn_error_clear(hdb.err); 95251881Speter 96251881Speter hdb.err = SVN_NO_ERROR; 97251881Speter } 98251881Speter 99251881Speter return hdb.err; 100251881Speter#else 101251881Speter svn_error_t *err = SVN_NO_ERROR; 102251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 103251881Speter apr_hash_index_t *hi; 104251881Speter 105251881Speter for (hi = apr_hash_first(pool, hash); 106251881Speter ! err && hi; hi = apr_hash_next(hi)) 107251881Speter { 108251881Speter const void *key; 109251881Speter void *val; 110251881Speter apr_ssize_t len; 111251881Speter 112251881Speter svn_pool_clear(iterpool); 113251881Speter 114251881Speter apr_hash_this(hi, &key, &len, &val); 115251881Speter err = (*func)(baton, key, len, val, iterpool); 116251881Speter } 117251881Speter 118251881Speter if (completed) 119251881Speter *completed = ! err; 120251881Speter 121251881Speter if (err && err->apr_err == SVN_ERR_ITER_BREAK) 122251881Speter { 123251881Speter if (err != &internal_break_error) 124251881Speter /* Errors - except those created by svn_iter_break() - 125251881Speter need to be cleared when not further propagated. */ 126251881Speter svn_error_clear(err); 127251881Speter 128251881Speter err = SVN_NO_ERROR; 129251881Speter } 130251881Speter 131251881Speter /* Clear iterpool, because callers may clear the error but have no way 132251881Speter to clear the iterpool with potentially lots of allocated memory */ 133251881Speter svn_pool_destroy(iterpool); 134251881Speter 135251881Speter return err; 136251881Speter#endif 137251881Speter} 138251881Speter 139251881Spetersvn_error_t * 140251881Spetersvn_iter_apr_array(svn_boolean_t *completed, 141251881Speter const apr_array_header_t *array, 142251881Speter svn_iter_apr_array_cb_t func, 143251881Speter void *baton, 144251881Speter apr_pool_t *pool) 145251881Speter{ 146251881Speter svn_error_t *err = SVN_NO_ERROR; 147251881Speter apr_pool_t *iterpool = svn_pool_create(pool); 148251881Speter int i; 149251881Speter 150251881Speter for (i = 0; (! err) && i < array->nelts; ++i) 151251881Speter { 152251881Speter void *item = array->elts + array->elt_size*i; 153251881Speter 154251881Speter svn_pool_clear(iterpool); 155251881Speter 156251881Speter err = (*func)(baton, item, iterpool); 157251881Speter } 158251881Speter 159251881Speter if (completed) 160251881Speter *completed = ! err; 161251881Speter 162251881Speter if (err && err->apr_err == SVN_ERR_ITER_BREAK) 163251881Speter { 164251881Speter if (err != &internal_break_error) 165251881Speter /* Errors - except those created by svn_iter_break() - 166251881Speter need to be cleared when not further propagated. */ 167251881Speter svn_error_clear(err); 168251881Speter 169251881Speter err = SVN_NO_ERROR; 170251881Speter } 171251881Speter 172251881Speter /* Clear iterpool, because callers may clear the error but have no way 173251881Speter to clear the iterpool with potentially lots of allocated memory */ 174251881Speter svn_pool_destroy(iterpool); 175251881Speter 176251881Speter return err; 177251881Speter} 178251881Speter 179251881Speter/* Note: Although this is a "__" function, it is in the public ABI, so 180251881Speter * we can never remove it or change its signature. */ 181251881Spetersvn_error_t * 182251881Spetersvn_iter__break(void) 183251881Speter{ 184251881Speter return &internal_break_error; 185251881Speter} 186251881Speter 187299742Sdim#if !APR_VERSION_AT_LEAST(1, 5, 0) 188299742Sdimconst void *apr_hash_this_key(apr_hash_index_t *hi) 189251881Speter{ 190251881Speter const void *key; 191251881Speter 192251881Speter apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL); 193251881Speter return key; 194251881Speter} 195251881Speter 196299742Sdimapr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi) 197251881Speter{ 198251881Speter apr_ssize_t klen; 199251881Speter 200251881Speter apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL); 201251881Speter return klen; 202251881Speter} 203251881Speter 204299742Sdimvoid *apr_hash_this_val(apr_hash_index_t *hi) 205251881Speter{ 206251881Speter void *val; 207251881Speter 208251881Speter apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val); 209251881Speter return val; 210251881Speter} 211299742Sdim#endif 212