1/* svn_skel.h : interface to `skeleton' functions
2 *
3 * ====================================================================
4 *    Licensed to the Apache Software Foundation (ASF) under one
5 *    or more contributor license agreements.  See the NOTICE file
6 *    distributed with this work for additional information
7 *    regarding copyright ownership.  The ASF licenses this file
8 *    to you under the Apache License, Version 2.0 (the
9 *    "License"); you may not use this file except in compliance
10 *    with the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *    Unless required by applicable law or agreed to in writing,
15 *    software distributed under the License is distributed on an
16 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 *    KIND, either express or implied.  See the License for the
18 *    specific language governing permissions and limitations
19 *    under the License.
20 * ====================================================================
21 */
22
23#ifndef SVN_SKEL_H
24#define SVN_SKEL_H
25
26#include <apr_pools.h>
27
28#include "svn_string.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif /* __cplusplus */
33
34
35/* What is a skel?  */
36
37/* Subversion needs to read a lot of structured data from database
38   records.  Instead of writing a half-dozen parsers and getting lazy
39   about error-checking, we define a reasonably dense, open-ended
40   syntax for strings and lists, and then use that for the concrete
41   representation of files, directories, property lists, etc.  This
42   lets us handle all the fussy character-by-character testing and
43   sanity checks all in one place, allowing the users of this library
44   to focus on higher-level consistency.
45
46   A `skeleton' (or `skel') is either an atom, or a list.  A list may
47   contain zero or more elements, each of which may be an atom or a
48   list.
49
50   Here's a description of the syntax of a skel:
51
52   A "whitespace" byte is 9, 10, 12, 13, or 32 (ASCII tab, newline,
53   form feed, carriage return, or space).
54
55   A "digit" byte is 48 -- 57 (ASCII digits).
56
57   A "name" byte is 65 -- 90, or 97 -- 122 (ASCII upper- and
58   lower-case characters).
59
60   An atom has one the following two forms:
61   - any string of bytes whose first byte is a name character, and
62     which contains no whitespace characters, bytes 40 (ASCII '(') or
63     bytes 41 (ASCII ')') (`implicit-length form'), or
64   - a string of digit bytes, followed by exactly one whitespace
65     character, followed by N bytes, where N is the value of the digit
66     bytes as a decimal number (`explicit-length form').
67
68   In the first case, the `contents' of the atom are the entire string
69   of characters.  In the second case, the contents of the atom are
70   the N bytes after the count and whitespace.
71
72   A list consists of a byte 40 (ASCII '('), followed by a series of
73   atoms or lists, followed by a byte 41 (ASCII ')').  There may be
74   zero or more whitespace characters after the '(' and before the
75   ')', and between any pair of elements.  If two consecutive elements
76   are atoms, they must be separated by at least one whitespace
77   character.  */
78
79
80/* The `skel' structure.  */
81
82/* A structure representing the results of parsing an array of bytes
83   as a skel.  */
84struct svn_skel_t {
85
86  /* True if the string was an atom, false if it was a list.
87
88     If the string is an atom, DATA points to the beginning of its
89     contents, and LEN gives the content length, in bytes.
90
91     If the string is a list, DATA and LEN delimit the entire body of
92     the list.  */
93  svn_boolean_t is_atom;
94
95  const char *data;
96  apr_size_t len;
97
98  /* If the string is a list, CHILDREN is a pointer to a
99     null-terminated linked list of skel objects representing the
100     elements of the list, linked through their NEXT pointers.  */
101  struct svn_skel_t *children;
102  struct svn_skel_t *next;
103};
104typedef struct svn_skel_t svn_skel_t;
105
106
107
108/* Operations on skels.  */
109
110
111/* Parse the LEN bytes at DATA as the concrete representation of a
112   skel, and return a skel object allocated from POOL describing its
113   contents.  If the data is not a properly-formed SKEL object, return
114   zero.
115
116   The returned skel objects point into the block indicated by DATA
117   and LEN; we don't copy the contents. */
118svn_skel_t *svn_skel__parse(const char *data, apr_size_t len,
119                            apr_pool_t *pool);
120
121
122/* Create an atom skel whose contents are the C string STR, allocated
123   from POOL.  */
124svn_skel_t *svn_skel__str_atom(const char *str, apr_pool_t *pool);
125
126
127/* Create an atom skel whose contents are the LEN bytes at ADDR,
128   allocated from POOL.  */
129svn_skel_t *svn_skel__mem_atom(const void *addr, apr_size_t len,
130                               apr_pool_t *pool);
131
132
133/* Create an empty list skel, allocated from POOL.  */
134svn_skel_t *svn_skel__make_empty_list(apr_pool_t *pool);
135
136/* Duplicates the skel structure SRC_SKEL and if DUP_DATA is true also the
137   data it references in RESULT_POOL */
138svn_skel_t *svn_skel__dup(const svn_skel_t *src_skel, svn_boolean_t dup_data,
139                          apr_pool_t *result_pool);
140
141
142/* Prepend SKEL to LIST.  */
143void svn_skel__prepend(svn_skel_t *skel, svn_skel_t *list);
144
145
146/* Append SKEL to LIST. Note: this must traverse the LIST, so you
147   generally want to use svn_skel__prepend().
148
149   NOTE: careful of the argument order here.  */
150void svn_skel__append(svn_skel_t *list, svn_skel_t *skel);
151
152
153/* Create an atom skel whose contents are the string representation
154   of the integer VALUE, allocated in RESULT_POOL, and then prepend
155   it to SKEL.  */
156void svn_skel__prepend_int(apr_int64_t value,
157                           svn_skel_t *skel,
158                           apr_pool_t *result_pool);
159
160
161/* Create an atom skel (allocated from RESULT_POOL) whose contents refer
162   to the string VALUE, then prepend it to SKEL.
163
164   NOTE: VALUE must have a lifetime *at least* that of RESULT_POOL. This
165   function does NOT copy it into RESULT_POOL.  */
166void svn_skel__prepend_str(const char *value,
167                           svn_skel_t *skel,
168                           apr_pool_t *result_pool);
169
170
171/* Parse SKEL as an integer and return the result in *N.
172 * SCRATCH_POOL is used for temporary memory.  */
173svn_error_t *
174svn_skel__parse_int(apr_int64_t *n, const svn_skel_t *skel,
175                    apr_pool_t *scratch_pool);
176
177
178/* Return a string whose contents are a concrete representation of
179   SKEL.  Allocate the string from POOL.  */
180svn_stringbuf_t *svn_skel__unparse(const svn_skel_t *skel, apr_pool_t *pool);
181
182
183/* Return true iff SKEL is an atom whose data is the same as STR.  */
184svn_boolean_t svn_skel__matches_atom(const svn_skel_t *skel, const char *str);
185
186
187/* Return the length of the list skel SKEL.  Atoms have a length of -1.  */
188int svn_skel__list_length(const svn_skel_t *skel);
189
190
191/* Parse a `PROPLIST' SKEL into a regular hash of properties,
192   *PROPLIST_P, which has const char * property names, and
193   svn_string_t * values. Use RESULT_POOL for all allocations.  */
194svn_error_t *
195svn_skel__parse_proplist(apr_hash_t **proplist_p,
196                         const svn_skel_t *skel,
197                         apr_pool_t *result_pool);
198
199/* Parse a `IPROPS' SKEL into a depth-first ordered array of
200   svn_prop_inherited_item_t * structures *IPROPS. Use RESULT_POOL
201   for all allocations.  */
202svn_error_t *
203svn_skel__parse_iprops(apr_array_header_t **iprops,
204                       const svn_skel_t *skel,
205                       apr_pool_t *result_pool);
206
207/* Parse a `PROPLIST' SKEL looking for PROPNAME.  If PROPNAME is found
208   then return its value in *PROVAL, allocated in RESULT_POOL. */
209svn_error_t *
210svn_skel__parse_prop(svn_string_t **propval,
211                     const svn_skel_t *skel,
212                     const char *propname,
213                     apr_pool_t *result_pool);
214
215/* Unparse a PROPLIST hash (which has const char * property names and
216   svn_string_t * values) into a `PROPLIST' skel *SKEL_P.  Use POOL
217   for all allocations.  */
218svn_error_t *
219svn_skel__unparse_proplist(svn_skel_t **skel_p,
220                           const apr_hash_t *proplist,
221                           apr_pool_t *pool);
222
223/* Unparse INHERITED_PROPS, a depth-first ordered array of
224   svn_prop_inherited_item_t * structures, into a `IPROPS' skel *SKEL_P.
225   Use RESULT_POOL for all allocations. */
226svn_error_t *
227svn_skel__unparse_iproplist(svn_skel_t **skel_p,
228                            const apr_array_header_t *inherited_props,
229                            apr_pool_t *result_pool,
230                            apr_pool_t *scratch_pool);
231
232#ifdef __cplusplus
233}
234#endif /* __cplusplus */
235
236#endif /* SVN_SKEL_H */
237