summaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/skel.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/skel.c')
-rw-r--r--subversion/libsvn_subr/skel.c240
1 files changed, 170 insertions, 70 deletions
diff --git a/subversion/libsvn_subr/skel.c b/subversion/libsvn_subr/skel.c
index 8c7a0ee..ed12db0 100644
--- a/subversion/libsvn_subr/skel.c
+++ b/subversion/libsvn_subr/skel.c
@@ -23,7 +23,10 @@
#include <string.h>
#include "svn_string.h"
#include "svn_error.h"
+#include "svn_props.h"
+#include "svn_pools.h"
#include "private/svn_skel.h"
+#include "private/svn_string_private.h"
/* Parsing skeletons. */
@@ -135,41 +138,6 @@ getsize(const char *data, apr_size_t len,
}
}
-/* Store the ASCII decimal representation of VALUE at DATA. Return
- the length of the representation if all goes well; return zero if
- the result doesn't fit in LEN bytes. */
-static int
-putsize(char *data, apr_size_t len, apr_size_t value)
-{
- apr_size_t i = 0;
-
- /* Generate the digits, least-significant first. */
- do
- {
- if (i >= len)
- return 0;
-
- data[i] = (value % 10) + '0';
- value /= 10;
- i++;
- }
- while (value > 0);
-
- /* Put the digits in most-significant-first order. */
- {
- int left, right;
-
- for (left = 0, right = i-1; left < right; left++, right--)
- {
- char t = data[left];
- data[left] = data[right];
- data[right] = t;
- }
- }
-
- return i;
-}
-
/* Checking validity of skels. */
static svn_error_t *
@@ -201,6 +169,35 @@ is_valid_proplist_skel(const svn_skel_t *skel)
return FALSE;
}
+static svn_boolean_t
+is_valid_iproplist_skel(const svn_skel_t *skel)
+{
+ int len = svn_skel__list_length(skel);
+
+ if ((len >= 0) && (len & 1) == 0)
+ {
+ svn_skel_t *elt;
+
+ for (elt = skel->children; elt; elt = elt->next)
+ {
+ if (!elt->is_atom)
+ return FALSE;
+
+ if (elt->next == NULL)
+ return FALSE;
+
+ elt = elt->next;
+
+ if (! is_valid_proplist_skel(elt))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static svn_skel_t *parse(const char *data, apr_size_t len,
apr_pool_t *pool);
@@ -401,23 +398,16 @@ explicit_atom(const char *data,
static apr_size_t estimate_unparsed_size(const svn_skel_t *skel);
static svn_stringbuf_t *unparse(const svn_skel_t *skel,
- svn_stringbuf_t *str,
- apr_pool_t *pool);
+ svn_stringbuf_t *str);
svn_stringbuf_t *
svn_skel__unparse(const svn_skel_t *skel, apr_pool_t *pool)
{
- svn_stringbuf_t *str;
-
- /* Allocate a string to hold the data. */
- str = apr_palloc(pool, sizeof(*str));
- str->pool = pool;
- str->blocksize = estimate_unparsed_size(skel) + 200;
- str->data = apr_palloc(pool, str->blocksize);
- str->len = 0;
+ svn_stringbuf_t *str
+ = svn_stringbuf_create_ensure(estimate_unparsed_size(skel) + 200, pool);
- return unparse(skel, str, pool);
+ return unparse(skel, str);
}
@@ -440,7 +430,7 @@ estimate_unparsed_size(const svn_skel_t *skel)
}
else
{
- int total_len;
+ apr_size_t total_len;
svn_skel_t *child;
/* Allow space for opening and closing parens, and a space
@@ -486,10 +476,9 @@ use_implicit(const svn_skel_t *skel)
}
-/* Append the concrete representation of SKEL to the string STR.
- Grow S with new space from POOL as necessary. */
+/* Append the concrete representation of SKEL to the string STR. */
static svn_stringbuf_t *
-unparse(const svn_skel_t *skel, svn_stringbuf_t *str, apr_pool_t *pool)
+unparse(const svn_skel_t *skel, svn_stringbuf_t *str)
{
if (skel->is_atom)
{
@@ -498,11 +487,12 @@ unparse(const svn_skel_t *skel, svn_stringbuf_t *str, apr_pool_t *pool)
svn_stringbuf_appendbytes(str, skel->data, skel->len);
else
{
- /* Append the length to STR. */
- char buf[200];
- int length_len;
+ /* Append the length to STR. Ensure enough space for at least
+ * one 64 bit int. */
+ char buf[200 + SVN_INT64_BUFFER_SIZE];
+ apr_size_t length_len;
- length_len = putsize(buf, sizeof(buf), skel->len);
+ length_len = svn__ui64toa(buf, skel->len);
SVN_ERR_ASSERT_NO_RETURN(length_len > 0);
@@ -510,31 +500,25 @@ unparse(const svn_skel_t *skel, svn_stringbuf_t *str, apr_pool_t *pool)
atom's contents. */
svn_stringbuf_ensure(str, str->len + length_len + 1 + skel->len);
svn_stringbuf_appendbytes(str, buf, length_len);
- str->data[str->len++] = ' ';
+ svn_stringbuf_appendbyte(str, ' ');
svn_stringbuf_appendbytes(str, skel->data, skel->len);
}
}
else
{
- /* Append a list to STR. */
+ /* Append a list to STR: an opening parenthesis, the list elements
+ * separated by a space, and a closing parenthesis. */
svn_skel_t *child;
- /* Emit an opening parenthesis. */
- svn_stringbuf_ensure(str, str->len + 1);
- str->data[str->len++] = '(';
+ svn_stringbuf_appendbyte(str, '(');
- /* Append each element. Emit a space between each pair of elements. */
for (child = skel->children; child; child = child->next)
{
- unparse(child, str, pool);
+ unparse(child, str);
if (child->next)
- {
- svn_stringbuf_ensure(str, str->len + 1);
- str->data[str->len++] = ' ';
- }
+ svn_stringbuf_appendbyte(str, ' ');
}
- /* Emit a closing parenthesis. */
svn_stringbuf_appendbyte(str, ')');
}
@@ -579,6 +563,33 @@ svn_skel__make_empty_list(apr_pool_t *pool)
return skel;
}
+svn_skel_t *svn_skel__dup(const svn_skel_t *src_skel, svn_boolean_t dup_data,
+ apr_pool_t *result_pool)
+{
+ svn_skel_t *skel = apr_pmemdup(result_pool, src_skel, sizeof(svn_skel_t));
+
+ if (dup_data && skel->data)
+ {
+ if (skel->is_atom)
+ skel->data = apr_pmemdup(result_pool, skel->data, skel->len);
+ else
+ {
+ /* When creating a skel this would be NULL, 0 for a list.
+ When parsing a string to a skel this might point to real data
+ delimiting the sublist. We don't copy that from here. */
+ skel->data = NULL;
+ skel->len = 0;
+ }
+ }
+
+ if (skel->children)
+ skel->children = svn_skel__dup(skel->children, dup_data, result_pool);
+
+ if (skel->next)
+ skel->next = svn_skel__dup(skel->next, dup_data, result_pool);
+
+ return skel;
+}
void
svn_skel__prepend(svn_skel_t *skel, svn_skel_t *list_skel)
@@ -596,9 +607,10 @@ void svn_skel__prepend_int(apr_int64_t value,
svn_skel_t *skel,
apr_pool_t *result_pool)
{
- const char *str = apr_psprintf(result_pool, "%" APR_INT64_T_FMT, value);
+ char *val_string = apr_palloc(result_pool, SVN_INT64_BUFFER_SIZE);
+ svn__i64toa(val_string, value);
- svn_skel__prepend_str(str, skel, result_pool);
+ svn_skel__prepend_str(val_string, skel, result_pool);
}
@@ -708,6 +720,34 @@ svn_skel__parse_proplist(apr_hash_t **proplist_p,
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_skel__parse_iprops(apr_array_header_t **iprops,
+ const svn_skel_t *skel,
+ apr_pool_t *result_pool)
+{
+ svn_skel_t *elt;
+
+ /* Validate the skel. */
+ if (! is_valid_iproplist_skel(skel))
+ return skel_err("iprops");
+
+ /* Create the returned structure */
+ *iprops = apr_array_make(result_pool, 1,
+ sizeof(svn_prop_inherited_item_t *));
+
+ for (elt = skel->children; elt; elt = elt->next->next)
+ {
+ svn_prop_inherited_item_t *new_iprop = apr_palloc(result_pool,
+ sizeof(*new_iprop));
+ svn_string_t *repos_parent = svn_string_ncreate(elt->data, elt->len,
+ result_pool);
+ SVN_ERR(svn_skel__parse_proplist(&(new_iprop->prop_hash), elt->next,
+ result_pool));
+ new_iprop->path_or_url = repos_parent->data;
+ APR_ARRAY_PUSH(*iprops, svn_prop_inherited_item_t *) = new_iprop;
+ }
+ return SVN_NO_ERROR;
+}
svn_error_t *
svn_skel__parse_prop(svn_string_t **propval,
@@ -744,7 +784,7 @@ svn_skel__parse_prop(svn_string_t **propval,
svn_error_t *
svn_skel__unparse_proplist(svn_skel_t **skel_p,
- apr_hash_t *proplist,
+ const apr_hash_t *proplist,
apr_pool_t *pool)
{
svn_skel_t *skel = svn_skel__make_empty_list(pool);
@@ -754,7 +794,8 @@ svn_skel__unparse_proplist(svn_skel_t **skel_p,
if (proplist)
{
/* Loop over hash entries */
- for (hi = apr_hash_first(pool, proplist); hi; hi = apr_hash_next(hi))
+ for (hi = apr_hash_first(pool, (apr_hash_t *)proplist); hi;
+ hi = apr_hash_next(hi))
{
const void *key;
void *val;
@@ -779,3 +820,62 @@ svn_skel__unparse_proplist(svn_skel_t **skel_p,
*skel_p = skel;
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_skel__unparse_iproplist(svn_skel_t **skel_p,
+ const apr_array_header_t *inherited_props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_skel_t *skel = svn_skel__make_empty_list(result_pool);
+
+ /* Create the skel. */
+ if (inherited_props)
+ {
+ int i;
+ apr_hash_index_t *hi;
+
+ for (i = 0; i < inherited_props->nelts; i++)
+ {
+ svn_prop_inherited_item_t *iprop =
+ APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
+
+ svn_skel_t *skel_list = svn_skel__make_empty_list(result_pool);
+ svn_skel_t *skel_atom;
+
+ /* Loop over hash entries */
+ for (hi = apr_hash_first(scratch_pool, iprop->prop_hash);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *key;
+ void *val;
+ apr_ssize_t klen;
+ svn_string_t *value;
+
+ apr_hash_this(hi, &key, &klen, &val);
+ value = val;
+
+ /* VALUE */
+ svn_skel__prepend(svn_skel__mem_atom(value->data, value->len,
+ result_pool), skel_list);
+
+ /* NAME */
+ svn_skel__prepend(svn_skel__mem_atom(key, klen, result_pool),
+ skel_list);
+ }
+
+ skel_atom = svn_skel__str_atom(
+ apr_pstrdup(result_pool, iprop->path_or_url), result_pool);
+ svn_skel__append(skel, skel_atom);
+ svn_skel__append(skel, skel_list);
+ }
+ }
+
+ /* Validate and return the skel. */
+ if (! is_valid_iproplist_skel(skel))
+ return skel_err("iproplist");
+
+ *skel_p = skel;
+ return SVN_NO_ERROR;
+}