1251881Speter/**
2251881Speter * @copyright
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 * @endcopyright
22251881Speter *
23251881Speter * @file svn_temp_serializer.h
24251881Speter * @brief Helper API for serializing _temporarily_ data structures.
25251881Speter *
26251881Speter * @note This API is intended for efficient serialization and duplication
27251881Speter *       of temporary, e.g. cached, data structures ONLY. It is not
28251881Speter *       suitable for persistent data.
29251881Speter */
30251881Speter
31251881Speter#ifndef SVN_TEMP_SERIALIZER_H
32251881Speter#define SVN_TEMP_SERIALIZER_H
33251881Speter
34251881Speter#include "svn_string.h"
35251881Speter
36251881Speter#ifdef __cplusplus
37251881Speterextern "C" {
38251881Speter#endif /* __cplusplus */
39251881Speter
40251881Speter/* forward declaration */
41251881Speterstruct svn_stringbuf_t;
42251881Speter
43251881Speter/**
44251881Speter * The amount of extra memory allocated by #svn_temp_serializer__init for
45251881Speter * the internal buffer in addition to its suggested_buffer_size parameter.
46251881Speter * To allocate a 512 buffer, including overhead, just specify a size of
47251881Speter * 512 - SVN_TEMP_SERIALIZER__OVERHEAD.
48251881Speter */
49251881Speter#define SVN_TEMP_SERIALIZER__OVERHEAD (sizeof(svn_stringbuf_t) + 1)
50251881Speter
51251881Speter/**
52251881Speter * Opaque structure controlling the serialization process and holding the
53251881Speter * intermediate as well as final results.
54251881Speter */
55251881Spetertypedef struct svn_temp_serializer__context_t svn_temp_serializer__context_t;
56251881Speter
57251881Speter/**
58251881Speter * Begin the serialization process for the @a source_struct and all objects
59251881Speter * referenced from it. @a struct_size must match the result of @c sizeof()
60251881Speter * of the actual structure. Due to the generic nature of the init function
61251881Speter * we can't determine the structure size as part of the function.
62251881Speter *
63251881Speter * It is possible to specify a @c NULL source_struct in which case the first
64251881Speter * call to svn_temp_serializer__push() will provide the root struct.
65251881Speter * Alternatively, one may even call svn_temp_serializer__add_string()
66251881Speter * but there is generally no point in doing so because the result will be
67251881Speter * simple string object in a #svn_stringbuf_t.
68251881Speter *
69251881Speter * You may suggest a larger initial buffer size in @a suggested_buffer_size
70251881Speter * to minimize the number of internal buffer re-allocations during the
71251881Speter * serialization process. All allocations will be made from @a pool.
72251881Speter *
73251881Speter * Pointers within the structure will be replaced by their serialized
74251881Speter * representation when the respective strings or sub-structures get
75251881Speter * serialized. This scheme allows only for tree-like, i.e. non-circular
76251881Speter * data structures.
77251881Speter *
78251881Speter * @return the serialization context.
79251881Speter */
80251881Spetersvn_temp_serializer__context_t *
81251881Spetersvn_temp_serializer__init(const void *source_struct,
82251881Speter                          apr_size_t struct_size,
83251881Speter                          apr_size_t suggested_buffer_size,
84251881Speter                          apr_pool_t *pool);
85251881Speter
86251881Speter/**
87251881Speter * Continue the serialization process of the @a source_struct that has
88251881Speter * already been serialized to @a buffer but contains references to new
89251881Speter * objects yet to serialize. I.e. this function allows you to append
90251881Speter * data to serialized structures returned by svn_temp_serializer__get().
91251881Speter *
92251881Speter * The current size of the serialized data is given in @a currently_used.
93251881Speter * If the allocated data buffer is actually larger, you may specifiy that
94251881Speter * size in @a currently_allocated to prevent unnecessary re-allocations.
95251881Speter * Otherwise, set it to 0.
96251881Speter *
97251881Speter * All allocations will be made from @a pool.
98251881Speter *
99251881Speter * Please note that only sub-structures of @a source_struct may be added.
100251881Speter * To add item referenced from other parts of the buffer, serialize from
101251881Speter * @a source_struct first, get the result from svn_temp_serializer__get()
102251881Speter * and call svn_temp_serializer__init_append for the next part.
103251881Speter *
104251881Speter * @return the serialization context.
105251881Speter */
106251881Spetersvn_temp_serializer__context_t *
107251881Spetersvn_temp_serializer__init_append(void *buffer,
108251881Speter                                 void *source_struct,
109251881Speter                                 apr_size_t currently_used,
110251881Speter                                 apr_size_t currently_allocated,
111251881Speter                                 apr_pool_t *pool);
112251881Speter
113251881Speter/**
114251881Speter * Begin serialization of a referenced sub-structure within the
115251881Speter * serialization @a context. @a source_struct must be a reference to the
116251881Speter * pointer in the original parent structure so that the correspondence in
117251881Speter * the serialized structure can be established. @a struct_size must match
118251881Speter * the result of @c sizeof() of the actual structure.
119251881Speter *
120251881Speter * Only in case that svn_temp_serializer__init() has not been provided
121251881Speter * with a root structure and this is the first call after the initialization,
122251881Speter * @a source_struct will point to a reference to the root structure instead
123251881Speter * of being related to some other.
124251881Speter *
125251881Speter * Sub-structures and strings will be added in a FIFO fashion. If you need
126251881Speter * add further sub-structures on the same level, you need to call
127251881Speter * svn_serializer__pop() to realign the serialization context.
128251881Speter */
129251881Spetervoid
130251881Spetersvn_temp_serializer__push(svn_temp_serializer__context_t *context,
131251881Speter                          const void * const * source_struct,
132251881Speter                          apr_size_t struct_size);
133251881Speter
134251881Speter/**
135251881Speter * End the serialization of the current sub-structure. The serialization
136251881Speter * @a context will be focused back on the parent structure. You may then
137251881Speter * add further sub-structures starting from that level.
138251881Speter *
139251881Speter * It is not necessary to call this function just for symmetry at the end
140251881Speter * of the serialization process.
141251881Speter */
142251881Spetervoid
143251881Spetersvn_temp_serializer__pop(svn_temp_serializer__context_t *context);
144251881Speter
145251881Speter/**
146251881Speter * Serialize a string referenced from the current structure within the
147251881Speter * serialization @a context. @a s must be a reference to the @c char*
148251881Speter * pointer in the original structure so that the correspondence in the
149251881Speter * serialized structure can be established.
150251881Speter *
151251881Speter * Only in case that svn_temp_serializer__init() has not been provided
152251881Speter * with a root structure and this is the first call after the initialization,
153251881Speter * @a s will not be related to some struct.
154251881Speter */
155251881Spetervoid
156251881Spetersvn_temp_serializer__add_string(svn_temp_serializer__context_t *context,
157251881Speter                                const char * const * s);
158251881Speter
159251881Speter/**
160251881Speter * Set the serialized representation of the pointer @a ptr inside the
161251881Speter * current structure within the serialization @a context to @c NULL.
162251881Speter * This is particularly useful if the pointer is not @c NULL in the
163251881Speter * source structure.
164251881Speter */
165251881Spetervoid
166251881Spetersvn_temp_serializer__set_null(svn_temp_serializer__context_t *context,
167251881Speter                              const void * const * ptr);
168251881Speter
169251881Speter/**
170251881Speter * @return the number of bytes currently used in the serialization buffer
171251881Speter * of the given serialization @a context.
172251881Speter */
173251881Speterapr_size_t
174251881Spetersvn_temp_serializer__get_length(svn_temp_serializer__context_t *context);
175251881Speter
176251881Speter/**
177251881Speter * @return a reference to the data buffer containing the data serialialized
178251881Speter * so far in the given serialization @a context.
179251881Speter */
180251881Speterstruct svn_stringbuf_t *
181251881Spetersvn_temp_serializer__get(svn_temp_serializer__context_t *context);
182251881Speter
183251881Speter/**
184251881Speter * Deserialization is straightforward: just copy the serialized buffer to
185251881Speter * a natively aligned memory location (APR pools will take care of that
186251881Speter * automatically) and resolve all pointers to sub-structures.
187251881Speter *
188251881Speter * To do the latter, call this function for each of these pointers, giving
189251881Speter * the start address of the copied buffer in @a buffer and a reference to
190251881Speter * the pointer to resolve in @a ptr.
191251881Speter */
192251881Spetervoid
193251881Spetersvn_temp_deserializer__resolve(void *buffer, void **ptr);
194251881Speter
195251881Speter/**
196251881Speter * Similar to svn_temp_deserializer__resolve() but instead of modifying
197251881Speter * the buffer content, the resulting pointer is passed back to the caller
198251881Speter * as the return value.
199251881Speter */
200251881Speterconst void *
201251881Spetersvn_temp_deserializer__ptr(const void *buffer, const void *const *ptr);
202251881Speter
203251881Speter#ifdef __cplusplus
204251881Speter}
205251881Speter#endif /* __cplusplus */
206251881Speter
207251881Speter#endif /* SVN_TEMP_SERIALIZER_H */
208