1 /*===========================================================================
2  *
3  *                            PUBLIC DOMAIN NOTICE
4  *               National Center for Biotechnology Information
5  *
6  *  This software/database is a "United States Government Work" under the
7  *  terms of the United States Copyright Act.  It was written as part of
8  *  the author's official duties as a United States Government employee and
9  *  thus cannot be copyrighted.  This software/database is freely available
10  *  to the public for use. The National Library of Medicine and the U.S.
11  *  Government have not placed any restriction on its use or reproduction.
12  *
13  *  Although all reasonable efforts have been taken to ensure the accuracy
14  *  and reliability of the software and data, the NLM and the U.S.
15  *  Government do not and cannot warrant the performance or results that
16  *  may be obtained by using this software or data. The NLM and the U.S.
17  *  Government disclaim all warranties, express or implied, including
18  *  warranties of performance, merchantability or fitness for any particular
19  *  purpose.
20  *
21  *  Please cite the author in any work or product based on this material.
22  *
23  * ===========================================================================
24  *
25  */
26 
27 #ifndef _h_klib_data_buffer
28 #define _h_klib_data_buffer
29 
30 #ifndef _h_klib_extern_
31 #include <klib/extern.h>
32 #endif
33 
34 #ifndef _h_klib_defs_
35 #include <klib/defs.h>
36 #endif
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 
43 /*--------------------------------------------------------------------------
44  * KDataBuffer
45  *  simple, open structure to reference an opaque data buffer
46  *
47  *  "base" - pointer to first byte of buffer
48  *
49  *  "elem_bits" - size of buffer element datatype in bits
50  *
51  *  "elem_count" - size of buffer in elements
52  *
53  *  "bit_offset" [ DEFAULT ZERO ] - offset from "base"
54  *  to first bit of buffer, always 0 when "elem_bits" % 8 == 0
55  *  bits are left-packed, i.e.:
56  *
57  *    bit_offset | starting bit
58  *   ============+=============
59  *            0  |  7
60  *            1  |  6
61  *            2  |  5
62  *              ...
63  *            6  |  1
64  *            7  |  0
65  *
66  * NB - there may be limits to the total number of bits within the buffer
67  *      that may be determined by architecture or runtime environment.
68  */
69 typedef struct KDataBuffer KDataBuffer;
70 struct KDataBuffer
71 {
72     const void *ignore;
73     void *base;
74     uint64_t elem_bits;
75     uint64_t elem_count;
76     uint8_t bit_offset;
77 };
78 
79 
80 /* Bits
81  *  return buffer size in bits
82  */
83 #define KDataBufferBits( self ) \
84     ((((bitsz_t)((const KDataBuffer *)(self))->elem_bits) * ((const KDataBuffer *)(self))->elem_count))
85 
86 /* Bytes
87  *  returns buffer size in bytes
88  */
89 #define KDataBufferBytes( self ) \
90    ((size_t)((KDataBufferBits(self) + 7) >> 3))
91 
92 
93 /* Make
94  *  create a new empty buffer
95  *
96  *  "buffer" [ OUT ] - pointer to structure to initialize
97  *
98  *  "elem_bits" [ IN ] - the number of bits in each element
99  *
100  *  "elem_capacity" [ IN ] - the minimum number of elements to be allocated
101  */
102 KLIB_EXTERN rc_t CC KDataBufferMake ( KDataBuffer *buffer,
103     uint64_t elem_bits, uint64_t elem_capacity );
104 
105 
106 /* MakeBytes
107  * MakeBits
108  *  create a new empty buffer with default element size
109  */
110 #define KDataBufferMakeBytes( buffer, bytes ) \
111     KDataBufferMake ( buffer, 8, bytes )
112 #define KDataBufferMakeBits( buffer, bits ) \
113     KDataBufferMake ( buffer, 1, bits )
114 
115 /* Sub
116  *  create a sub-range reference to an existing buffer
117  *
118  *  "sub" [ OUT ] - pointer to subrange structure
119  *
120  *  "start" [ IN ] - element offset of subrange from start of "self".
121  *  if given start >= self->elem_count, the resultant subrange
122  *  will have an element count of 0.
123  *
124  *  "count" [ IN, DEFAULT UINT64_MAX ] - number of elements of subrange.
125  *  when given count exceeds buffer size, the actual count is calculated to be
126  *  all remaining count in "self" from "start". otherwise, the
127  *  requested count will be limited to the actual count available
128  *  in "self".
129  */
130 KLIB_EXTERN rc_t CC KDataBufferSub ( const KDataBuffer *self,
131     KDataBuffer *sub, uint64_t start, uint64_t count );
132 
133 
134 /* MakeWritable
135  *  make a writable copy of the buffer, copying contents if needed.
136  *
137  *  "writable" [ OUT ] - pointer to the structure to initialize
138  *
139  * The usage pattern is:
140  *   KDataBuffer buffer;
141  * ...
142  * initialize buffer
143  * do stuff which might make it shared
144  *   (like pass it to a function that might retain it)
145  * ...
146  *   KDataBuffer writable;
147  *   rc_t rc = KDataBufferMakeWritable(&buffer, &writable);
148  *
149  *   if (rc == 0) {
150  *       / * until you whack the old one KDataBufferWritable(&writable) might be false! * /
151  *       KDataBufferWhack(&buffer);
152  *       buffer = writable;
153  * ...
154  * do whatever you want with buffer because it is now writable (not shared)
155  * ...
156  *   }
157  *   KDataBufferWhack(&buffer);
158  */
159 KLIB_EXTERN rc_t CC KDataBufferMakeWritable ( const KDataBuffer *self, KDataBuffer *writable );
160 
161 
162 /* Whack
163  *  release memory associated with a buffer.
164  */
165 KLIB_EXTERN rc_t CC KDataBufferWhack ( KDataBuffer *self );
166 
167 
168 /* Resize
169  *  make a buffer bigger or smaller.
170  *  can fail if not enough memory.
171  *  can fail if not writable.
172  *
173  *  "new_count" [ IN ] - new number of elements
174  */
175 KLIB_EXTERN rc_t CC KDataBufferResize ( KDataBuffer *self, uint64_t new_count );
176 
177 
178 /* Cast
179  *  create a new data-buffer with a different element size
180  *  won't increase the total number of bits
181  *
182  *  "cast" [ OUT ] - newly typed buffer
183  *
184  *  "new_elem_bits" [ IN ] - new element size in bits
185  *
186  *  "can_shrink" [ IN ] - when true allow
187  *  KDataBufferBits ( cast ) < KDataBufferBits ( self )
188  */
189 KLIB_EXTERN rc_t CC KDataBufferCast ( const KDataBuffer *self,
190     KDataBuffer *cast, uint64_t new_elem_bits, bool can_shrink );
191 
192 
193 /* Writable
194  *  returns true if buffer is valid and writable
195  */
196 KLIB_EXTERN bool CC KDataBufferWritable ( const KDataBuffer *self );
197 
198 
199 /* CheckIntegrity
200  *  performs some level of integrity checking on buffer structure
201  */
202 KLIB_EXTERN rc_t CC KDataBufferCheckIntegrity ( const KDataBuffer *self );
203 
204 
205 /* Wipe
206  *  overwrite allocated memory
207  */
208 KLIB_EXTERN rc_t CC KDataBufferWipe ( KDataBuffer * self );
209 
210 
211 /* WipeNWhack
212  *  wipes and releases memory associated with a buffer.
213  */
214 KLIB_EXTERN rc_t CC KDataBufferWipeNWhack ( KDataBuffer * self );
215 
216 
217 /* WipeResize
218  *  make a buffer bigger or smaller.
219  *  can fail if not enough memory.
220  *  can fail if not writable.
221  *  wipes memory before release or reallocation
222  *
223  *  "new_count" [ IN ] - new number of elements
224  */
225 KLIB_EXTERN rc_t CC KDataBufferWipeResize ( KDataBuffer * self, uint64_t new_count );
226 
227 
228 #ifdef __cplusplus
229 }
230 #endif
231 
232 #endif /* _h_klib_data_buffer_ */
233