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