diff options
Diffstat (limited to 'subversion/libsvn_subr/skel.c')
-rw-r--r-- | subversion/libsvn_subr/skel.c | 240 |
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; +} |