1 /** 2 * @copyright 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 * @endcopyright 22 * 23 * @file svn_temp_serializer.h 24 * @brief Helper API for serializing _temporarily_ data structures. 25 * 26 * @note This API is intended for efficient serialization and duplication 27 * of temporary, e.g. cached, data structures ONLY. It is not 28 * suitable for persistent data. 29 */ 30 31 #ifndef SVN_TEMP_SERIALIZER_H 32 #define SVN_TEMP_SERIALIZER_H 33 34 #include "svn_string.h" 35 36 #ifdef __cplusplus 37 extern "C" { 38 #endif /* __cplusplus */ 39 40 /* forward declaration */ 41 struct svn_stringbuf_t; 42 43 /** 44 * The amount of extra memory allocated by #svn_temp_serializer__init for 45 * the internal buffer in addition to its suggested_buffer_size parameter. 46 * To allocate a 512 buffer, including overhead, just specify a size of 47 * 512 - SVN_TEMP_SERIALIZER__OVERHEAD. 48 */ 49 #define SVN_TEMP_SERIALIZER__OVERHEAD (sizeof(svn_stringbuf_t) + 1) 50 51 /** 52 * Opaque structure controlling the serialization process and holding the 53 * intermediate as well as final results. 54 */ 55 typedef struct svn_temp_serializer__context_t svn_temp_serializer__context_t; 56 57 /** 58 * Begin the serialization process for the @a source_struct and all objects 59 * referenced from it. @a struct_size must match the result of @c sizeof() 60 * of the actual structure. Due to the generic nature of the init function 61 * we can't determine the structure size as part of the function. 62 * 63 * It is possible to specify a @c NULL source_struct in which case the first 64 * call to svn_temp_serializer__push() will provide the root struct. 65 * Alternatively, one may even call svn_temp_serializer__add_string() 66 * but there is generally no point in doing so because the result will be 67 * simple string object in a #svn_stringbuf_t. 68 * 69 * You may suggest a larger initial buffer size in @a suggested_buffer_size 70 * to minimize the number of internal buffer re-allocations during the 71 * serialization process. All allocations will be made from @a pool. 72 * 73 * Pointers within the structure will be replaced by their serialized 74 * representation when the respective strings or sub-structures get 75 * serialized. This scheme allows only for tree-like, i.e. non-circular 76 * data structures. 77 * 78 * @return the serialization context. 79 */ 80 svn_temp_serializer__context_t * 81 svn_temp_serializer__init(const void *source_struct, 82 apr_size_t struct_size, 83 apr_size_t suggested_buffer_size, 84 apr_pool_t *pool); 85 86 /** 87 * Continue the serialization process of the @a source_struct that has 88 * already been serialized to @a buffer but contains references to new 89 * objects yet to serialize. I.e. this function allows you to append 90 * data to serialized structures returned by svn_temp_serializer__get(). 91 * 92 * The current size of the serialized data is given in @a currently_used. 93 * If the allocated data buffer is actually larger, you may specifiy that 94 * size in @a currently_allocated to prevent unnecessary re-allocations. 95 * Otherwise, set it to 0. 96 * 97 * All allocations will be made from @a pool. 98 * 99 * Please note that only sub-structures of @a source_struct may be added. 100 * To add item referenced from other parts of the buffer, serialize from 101 * @a source_struct first, get the result from svn_temp_serializer__get() 102 * and call svn_temp_serializer__init_append for the next part. 103 * 104 * @return the serialization context. 105 */ 106 svn_temp_serializer__context_t * 107 svn_temp_serializer__init_append(void *buffer, 108 void *source_struct, 109 apr_size_t currently_used, 110 apr_size_t currently_allocated, 111 apr_pool_t *pool); 112 113 /** 114 * Begin serialization of a referenced sub-structure within the 115 * serialization @a context. @a source_struct must be a reference to the 116 * pointer in the original parent structure so that the correspondence in 117 * the serialized structure can be established. @a struct_size must match 118 * the result of @c sizeof() of the actual structure. 119 * 120 * Only in case that svn_temp_serializer__init() has not been provided 121 * with a root structure and this is the first call after the initialization, 122 * @a source_struct will point to a reference to the root structure instead 123 * of being related to some other. 124 * 125 * Sub-structures and strings will be added in a FIFO fashion. If you need 126 * add further sub-structures on the same level, you need to call 127 * svn_serializer__pop() to realign the serialization context. 128 */ 129 void 130 svn_temp_serializer__push(svn_temp_serializer__context_t *context, 131 const void * const * source_struct, 132 apr_size_t struct_size); 133 134 /** 135 * End the serialization of the current sub-structure. The serialization 136 * @a context will be focused back on the parent structure. You may then 137 * add further sub-structures starting from that level. 138 * 139 * It is not necessary to call this function just for symmetry at the end 140 * of the serialization process. 141 */ 142 void 143 svn_temp_serializer__pop(svn_temp_serializer__context_t *context); 144 145 /** 146 * Serialize a referenced sub-structure within the serialization 147 * @a context. @a source_struct must be a reference to the 148 * pointer in the original parent structure so that the correspondence in 149 * the serialized structure can be established. @a struct_size must match 150 * the result of @c sizeof() of the actual structure. 151 * 152 * This function is equivalent but more efficient than calling 153 * #svn_temp_serializer__push() immediately followed by 154 * #svn_temp_serializer__pop(). 155 */ 156 void 157 svn_temp_serializer__add_leaf(svn_temp_serializer__context_t *context, 158 const void * const * source_struct, 159 apr_size_t struct_size); 160 161 /** 162 * Serialize a string referenced from the current structure within the 163 * serialization @a context. @a s must be a reference to the @c char* 164 * pointer in the original structure so that the correspondence in the 165 * serialized structure can be established. 166 * 167 * Only in case that svn_temp_serializer__init() has not been provided 168 * with a root structure and this is the first call after the initialization, 169 * @a s will not be related to some struct. 170 */ 171 void 172 svn_temp_serializer__add_string(svn_temp_serializer__context_t *context, 173 const char * const * s); 174 175 /** 176 * Set the serialized representation of the pointer @a ptr inside the 177 * current structure within the serialization @a context to @c NULL. 178 * This is particularly useful if the pointer is not @c NULL in the 179 * source structure. 180 */ 181 void 182 svn_temp_serializer__set_null(svn_temp_serializer__context_t *context, 183 const void * const * ptr); 184 185 /** 186 * @return the number of bytes currently used in the serialization buffer 187 * of the given serialization @a context. 188 */ 189 apr_size_t 190 svn_temp_serializer__get_length(svn_temp_serializer__context_t *context); 191 192 /** 193 * @return a reference to the data buffer containing the data serialialized 194 * so far in the given serialization @a context. 195 */ 196 struct svn_stringbuf_t * 197 svn_temp_serializer__get(svn_temp_serializer__context_t *context); 198 199 /** 200 * Deserialization is straightforward: just copy the serialized buffer to 201 * a natively aligned memory location (APR pools will take care of that 202 * automatically) and resolve all pointers to sub-structures. 203 * 204 * To do the latter, call this function for each of these pointers, giving 205 * the start address of the copied buffer in @a buffer and a reference to 206 * the pointer to resolve in @a ptr. 207 */ 208 void 209 svn_temp_deserializer__resolve(const void *buffer, void **ptr); 210 211 /** 212 * Similar to svn_temp_deserializer__resolve() but instead of modifying 213 * the buffer content, the resulting pointer is passed back to the caller 214 * as the return value. 215 */ 216 const void * 217 svn_temp_deserializer__ptr(const void *buffer, const void *const *ptr); 218 219 #ifdef __cplusplus 220 } 221 #endif /* __cplusplus */ 222 223 #endif /* SVN_TEMP_SERIALIZER_H */ 224