source: mainline/uspace/app/bithenge/blob.c@ 1923501

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1923501 was 1923501, checked in by Sean Bartell <wingedtachikoma@…>, 13 years ago

Bithenge: use separate functions instead of casts.

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*
2 * Copyright (c) 2012 Sean Bartell
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup bithenge
30 * @{
31 */
32/**
33 * @file
34 * Raw binary blobs.
35 */
36
37#include <assert.h>
38#include <bool.h>
39#include <errno.h>
40#include <macros.h>
41#include <mem.h>
42#include <stdlib.h>
43#include "blob.h"
44
45/** Initialize a random access blob.
46 * @memberof bithenge_blob_t
47 * @param[out] blob The blob to initialize.
48 * @param[in] ops Operations providing random access support. This pointer must
49 * be valid until the blob is destroyed.
50 * @return EOK on success or an error code from errno.h.
51 */
52int bithenge_new_random_access_blob(bithenge_blob_t *blob,
53 const bithenge_random_access_blob_ops_t *ops)
54{
55 assert(blob);
56 assert(ops);
57 assert(ops->destroy);
58 assert(ops->read);
59 assert(ops->size);
60
61 blob->ops = ops;
62 return EOK;
63}
64
65static int sequential_buffer(bithenge_sequential_blob_t *blob, aoff64_t end)
66{
67 bool need_realloc = false;
68 while (end > blob->buffer_size) {
69 blob->buffer_size = max(4096, 2 * blob->buffer_size);
70 need_realloc = true;
71 }
72 if (need_realloc) {
73 char *buffer = realloc(blob->buffer, blob->buffer_size);
74 if (!buffer)
75 return ENOMEM;
76 blob->buffer = buffer;
77 }
78 aoff64_t size = end - blob->data_size;
79 int rc = blob->ops->read(blob, blob->buffer + blob->data_size, &size);
80 if (rc != EOK)
81 return rc;
82 blob->data_size += size;
83 return EOK;
84}
85
86static inline bithenge_sequential_blob_t *sequential_from_blob(
87 bithenge_blob_t *base)
88{
89 return (bithenge_sequential_blob_t *)base;
90}
91
92static inline bithenge_blob_t *blob_from_sequential(
93 bithenge_sequential_blob_t *blob)
94{
95 return &blob->base;
96}
97
98static int sequential_size(bithenge_blob_t *base, aoff64_t *size)
99{
100 bithenge_sequential_blob_t *blob = sequential_from_blob(base);
101 int rc;
102 if (blob->ops->size) {
103 rc = blob->ops->size(blob, size);
104 if (rc == EOK)
105 return EOK;
106 }
107 rc = sequential_buffer(blob, blob->buffer_size);
108 if (rc != EOK)
109 return rc;
110 while (blob->data_size == blob->buffer_size) {
111 rc = sequential_buffer(blob, 2 * blob->buffer_size);
112 if (rc != EOK)
113 return rc;
114 }
115 *size = blob->data_size;
116 return EOK;
117}
118
119static int sequential_read(bithenge_blob_t *base, aoff64_t offset,
120 char *buffer, aoff64_t *size)
121{
122 bithenge_sequential_blob_t *blob = sequential_from_blob(base);
123 aoff64_t end = offset + *size;
124 if (end > blob->data_size) {
125 int rc = sequential_buffer(blob, end);
126 if (rc != EOK)
127 return rc;
128 }
129 if (offset > blob->data_size)
130 return EINVAL;
131 *size = min(*size, blob->data_size - end);
132 memcpy(buffer, blob->buffer + offset, *size);
133 return EOK;
134}
135
136static int sequential_destroy(bithenge_blob_t *base)
137{
138 bithenge_sequential_blob_t *blob = sequential_from_blob(base);
139 free(blob->buffer);
140 return blob->ops->destroy(blob);
141}
142
143static const bithenge_random_access_blob_ops_t sequential_ops = {
144 .size = sequential_size,
145 .read = sequential_read,
146 .destroy = sequential_destroy,
147};
148
149/** Initialize a sequential blob.
150 * @memberof bithenge_sequential_blob_t
151 * @param[out] blob The blob to initialize.
152 * @param[in] ops Operations providing sequential access support. This pointer
153 * must be valid until the blob is destroyed.
154 * @return EOK on success or an error code from errno.h.
155 */
156int bithenge_new_sequential_blob(bithenge_sequential_blob_t *blob,
157 const bithenge_sequential_blob_ops_t *ops)
158{
159 assert(blob);
160 assert(ops);
161 assert(ops->destroy);
162 assert(ops->read);
163 // ops->size is optional
164
165 int rc = bithenge_new_random_access_blob(blob_from_sequential(blob),
166 &sequential_ops);
167 if (rc != EOK)
168 return rc;
169 blob->ops = ops;
170 blob->buffer = NULL; // realloc(NULL, ...) works like malloc
171 blob->buffer_size = 0;
172 blob->data_size = 0;
173 return EOK;
174}
175
176/** @}
177 */
Note: See TracBrowser for help on using the repository browser.