blob: 1a303b5119458cd5a634e485fe2a407a2cdb0e7d [file] [log] [blame]
/* 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