Changeset 04a7435f in mainline for uspace/app/bithenge/transform.c
- Timestamp:
- 2012-06-26T19:56:26Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 978ccaf1
- Parents:
- f2da0bb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/transform.c
rf2da0bb r04a7435f 41 41 #include "transform.h" 42 42 43 /** Initialize a new transform. 44 * @param[out] xform Transform to initialize. 45 * @param[in] ops Operations provided by the transform. 46 * @return EOK or an error code from errno.h. */ 47 int bithenge_new_transform(bithenge_transform_t *xform, 48 const bithenge_transform_ops_t *ops) 49 { 50 assert(ops); 51 assert(ops->apply); 52 assert(ops->destroy); 53 xform->ops = ops; 54 xform->refs = 1; 55 return EOK; 56 } 57 43 58 static int transform_indestructible(bithenge_transform_t *xform) 44 59 { … … 125 140 bithenge_named_transform_t *bithenge_primitive_transforms = primitive_transforms; 126 141 142 typedef struct { 143 bithenge_node_t base; 144 struct struct_transform *transform; 145 bithenge_blob_t *blob; 146 } struct_node_t; 147 148 typedef struct struct_transform { 149 bithenge_transform_t base; 150 bithenge_named_transform_t *subtransforms; 151 } struct_transform_t; 152 153 static bithenge_node_t *struct_as_node(struct_node_t *node) 154 { 155 return &node->base; 156 } 157 158 static struct_node_t *node_as_struct(bithenge_node_t *node) 159 { 160 return (struct_node_t *)node; 161 } 162 163 static bithenge_transform_t *struct_as_transform(struct_transform_t *xform) 164 { 165 return &xform->base; 166 } 167 168 static struct_transform_t *transform_as_struct(bithenge_transform_t *xform) 169 { 170 return (struct_transform_t *)xform; 171 } 172 173 static int struct_node_for_one(const char *name, 174 bithenge_transform_t *subxform, bithenge_blob_t **blob, 175 bithenge_for_each_func_t func, void *data) 176 { 177 int rc; 178 bithenge_node_t *subxform_result = NULL; 179 180 aoff64_t sub_size; 181 rc = bithenge_transform_prefix_length(subxform, *blob, &sub_size); 182 if (rc != EOK) 183 goto error; 184 185 bithenge_node_t *subblob_node; 186 bithenge_blob_inc_ref(*blob); 187 rc = bithenge_new_subblob(&subblob_node, *blob, 0, sub_size); 188 if (rc != EOK) 189 goto error; 190 191 rc = bithenge_transform_apply(subxform, subblob_node, 192 &subxform_result); 193 bithenge_node_dec_ref(subblob_node); 194 if (rc != EOK) 195 goto error; 196 197 if (name) { 198 bithenge_node_t *name_node; 199 rc = bithenge_new_string_node(&name_node, name, false); 200 if (rc != EOK) 201 goto error; 202 rc = func(name_node, subxform_result, data); 203 subxform_result = NULL; 204 if (rc != EOK) 205 goto error; 206 } else { 207 if (bithenge_node_type(subxform_result) != 208 BITHENGE_NODE_INTERNAL) { 209 rc = EINVAL; 210 goto error; 211 } 212 rc = bithenge_node_for_each(subxform_result, func, data); 213 if (rc != EOK) 214 goto error; 215 } 216 217 bithenge_node_t *blob_node; 218 rc = bithenge_new_offset_blob(&blob_node, *blob, sub_size); 219 *blob = NULL; 220 if (rc != EOK) 221 goto error; 222 *blob = bithenge_node_as_blob(blob_node); 223 224 error: 225 bithenge_node_dec_ref(subxform_result); 226 return rc; 227 } 228 229 static int struct_node_for_each(bithenge_node_t *base, 230 bithenge_for_each_func_t func, void *data) 231 { 232 int rc = EOK; 233 struct_node_t *struct_node = node_as_struct(base); 234 bithenge_named_transform_t *subxforms = 235 struct_node->transform->subtransforms; 236 237 bithenge_node_t *blob_node = NULL; 238 bithenge_blob_t *blob = NULL; 239 bithenge_blob_inc_ref(struct_node->blob); 240 rc = bithenge_new_offset_blob(&blob_node, struct_node->blob, 0); 241 if (rc != EOK) { 242 blob = NULL; 243 goto error; 244 } 245 blob = bithenge_node_as_blob(blob_node); 246 247 for (size_t i = 0; subxforms[i].transform; i++) { 248 rc = struct_node_for_one(subxforms[i].name, 249 subxforms[i].transform, &blob, func, data); 250 if (rc != EOK) 251 goto error; 252 } 253 254 aoff64_t remaining; 255 rc = bithenge_blob_size(blob, &remaining); 256 if (rc != EOK) 257 goto error; 258 if (remaining != 0) { 259 rc = EINVAL; 260 goto error; 261 } 262 263 error: 264 bithenge_blob_dec_ref(blob); 265 return rc; 266 } 267 268 static int struct_node_destroy(bithenge_node_t *base) 269 { 270 struct_node_t *node = node_as_struct(base); 271 bithenge_transform_dec_ref(struct_as_transform(node->transform)); 272 bithenge_blob_dec_ref(node->blob); 273 free(node); 274 return EOK; 275 } 276 277 static const bithenge_internal_node_ops_t struct_node_ops = { 278 .for_each = struct_node_for_each, 279 .destroy = struct_node_destroy, 280 }; 281 282 static int struct_transform_apply(bithenge_transform_t *xform, 283 bithenge_node_t *in, bithenge_node_t **out) 284 { 285 struct_transform_t *struct_transform = transform_as_struct(xform); 286 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB) 287 return EINVAL; 288 struct_node_t *node = malloc(sizeof(*node)); 289 if (!node) 290 return ENOMEM; 291 int rc = bithenge_init_internal_node(struct_as_node(node), 292 &struct_node_ops); 293 if (rc != EOK) { 294 free(node); 295 return rc; 296 } 297 bithenge_transform_inc_ref(xform); 298 node->transform = struct_transform; 299 bithenge_node_inc_ref(in); 300 node->blob = bithenge_node_as_blob(in); 301 *out = struct_as_node(node); 302 return EOK; 303 } 304 305 static int struct_transform_prefix_length(bithenge_transform_t *xform, 306 bithenge_blob_t *blob, aoff64_t *out) 307 { 308 struct_transform_t *struct_transform = transform_as_struct(xform); 309 int rc = EOK; 310 bithenge_node_t *node; 311 bithenge_blob_inc_ref(blob); 312 rc = bithenge_new_offset_blob(&node, blob, 0); 313 blob = NULL; 314 if (rc != EOK) 315 goto error; 316 blob = bithenge_node_as_blob(node); 317 *out = 0; 318 for (size_t i = 0; struct_transform->subtransforms[i].transform; i++) { 319 bithenge_transform_t *subxform = 320 struct_transform->subtransforms[i].transform; 321 aoff64_t sub_size; 322 rc = bithenge_transform_prefix_length(subxform, blob, &sub_size); 323 if (rc != EOK) 324 goto error; 325 *out += sub_size; 326 rc = bithenge_new_offset_blob(&node, blob, sub_size); 327 blob = NULL; 328 if (rc != EOK) 329 goto error; 330 blob = bithenge_node_as_blob(node); 331 } 332 error: 333 bithenge_blob_dec_ref(blob); 334 return EOK; 335 } 336 337 static void free_subtransforms(bithenge_named_transform_t *subtransforms) 338 { 339 for (size_t i = 0; subtransforms[i].transform; i++) { 340 free((void *)subtransforms[i].name); 341 bithenge_transform_dec_ref(subtransforms[i].transform); 342 } 343 free(subtransforms); 344 } 345 346 static int struct_transform_destroy(bithenge_transform_t *xform) 347 { 348 struct_transform_t *struct_transform = transform_as_struct(xform); 349 free_subtransforms(struct_transform->subtransforms); 350 free(struct_transform); 351 return EOK; 352 } 353 354 static bithenge_transform_ops_t struct_transform_ops = { 355 .apply = struct_transform_apply, 356 .prefix_length = struct_transform_prefix_length, 357 .destroy = struct_transform_destroy, 358 }; 359 360 /** Create a struct transform. The transform will apply its subtransforms 361 * sequentially to a blob to create an internal node. Each result is either 362 * given a key from @a subtransforms or, if the name is NULL, the result's keys 363 * and values are merged into the struct transform's result. This function 364 * takes ownership of @a subtransforms and the names and references therein. 365 * @param[out] out Stores the created transform. 366 * @param subtransforms The subtransforms and field names. 367 * @return EOK on success or an error code from errno.h. */ 368 int bithenge_new_struct(bithenge_transform_t **out, 369 bithenge_named_transform_t *subtransforms) 370 { 371 int rc; 372 struct_transform_t *struct_transform = 373 malloc(sizeof(*struct_transform)); 374 if (!struct_transform) { 375 rc = ENOMEM; 376 goto error; 377 } 378 rc = bithenge_new_transform(struct_as_transform(struct_transform), 379 &struct_transform_ops); 380 if (rc != EOK) 381 goto error; 382 struct_transform->subtransforms = subtransforms; 383 *out = struct_as_transform(struct_transform); 384 return EOK; 385 error: 386 free_subtransforms(subtransforms); 387 free(struct_transform); 388 return rc; 389 } 390 127 391 /** @} 128 392 */
Note:
See TracChangeset
for help on using the changeset viewer.