| /* 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 |