/* iter.c : iteration drivers * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== */ #include "svn_iter.h" #include "svn_pools.h" #include "private/svn_dep_compat.h" #include "svn_error_codes.h" static svn_error_t internal_break_error = { SVN_ERR_ITER_BREAK, /* APR status */ NULL, /* message */ NULL, /* child error */ NULL, /* pool */ __FILE__, /* file name */ __LINE__ /* line number */ }; struct hash_do_baton { void *baton; svn_iter_apr_hash_cb_t func; svn_error_t *err; apr_pool_t *iterpool; }; static int hash_do_callback(void *baton, const void *key, apr_ssize_t klen, const void *value) { struct hash_do_baton *hdb = baton; svn_pool_clear(hdb->iterpool); hdb->err = (*hdb->func)(hdb->baton, key, klen, (void *)value, hdb->iterpool); return hdb->err == SVN_NO_ERROR; } svn_error_t * svn_iter_apr_hash(svn_boolean_t *completed, apr_hash_t *hash, svn_iter_apr_hash_cb_t func, void *baton, apr_pool_t *pool) { struct hash_do_baton hdb; svn_boolean_t error_received; hdb.func = func; hdb.baton = baton; hdb.iterpool = svn_pool_create(pool); error_received = !apr_hash_do(hash_do_callback, &hdb, hash); svn_pool_destroy(hdb.iterpool); if (completed) *completed = !error_received; if (!error_received) return SVN_NO_ERROR; if (hdb.err->apr_err == SVN_ERR_ITER_BREAK && hdb.err != &internal_break_error) { /* Errors - except those created by svn_iter_break() - need to be cleared when not further propagated. */ svn_error_clear(hdb.err); hdb.err = SVN_NO_ERROR; } return hdb.err; } svn_error_t * svn_iter_apr_array(svn_boolean_t *completed, const apr_array_header_t *array, svn_iter_apr_array_cb_t func, void *baton, apr_pool_t *pool) { svn_error_t *err = SVN_NO_ERROR; apr_pool_t *iterpool = svn_pool_create(pool); int i; for (i = 0; (! err) && i < array->nelts; ++i) { void *item = array->elts + array->elt_size*i; svn_pool_clear(iterpool); err = (*func)(baton, item, iterpool); } if (completed) *completed = ! err; if (err && err->apr_err == SVN_ERR_ITER_BREAK) { if (err != &internal_break_error) /* Errors - except those created by svn_iter_break() - need to be cleared when not further propagated. */ svn_error_clear(err); err = SVN_NO_ERROR; } /* Clear iterpool, because callers may clear the error but have no way to clear the iterpool with potentially lots of allocated memory */ svn_pool_destroy(iterpool); return err; } /* Note: Although this is a "__" function, it is in the public ABI, so * we can never remove it or change its signature. */ svn_error_t * svn_iter__break(void) { return &internal_break_error; } #if !APR_VERSION_AT_LEAST(1, 5, 0) const void *apr_hash_this_key(apr_hash_index_t *hi) { const void *key; apr_hash_this((apr_hash_index_t *)hi, &key, NULL, NULL); return key; } apr_ssize_t apr_hash_this_key_len(apr_hash_index_t *hi) { apr_ssize_t klen; apr_hash_this((apr_hash_index_t *)hi, NULL, &klen, NULL); return klen; } void *apr_hash_this_val(apr_hash_index_t *hi) { void *val; apr_hash_this((apr_hash_index_t *)hi, NULL, NULL, &val); return val; } #endif