source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/constbuffer.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 15.0 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include <stdlib.h>
5#include <stdbool.h>
6#include "azure_macro_utils/macro_utils.h"
7#include "azure_c_shared_utility/gballoc.h"
8#include "azure_c_shared_utility/xlogging.h"
9#include "azure_c_shared_utility/refcount.h"
10
11#include "azure_c_shared_utility/constbuffer.h"
12
13#define CONSTBUFFER_TYPE_VALUES \
14 CONSTBUFFER_TYPE_COPIED, \
15 CONSTBUFFER_TYPE_MEMORY_MOVED, \
16 CONSTBUFFER_TYPE_WITH_CUSTOM_FREE, \
17 CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE
18
19MU_DEFINE_ENUM(CONSTBUFFER_TYPE, CONSTBUFFER_TYPE_VALUES)
20
21typedef struct CONSTBUFFER_HANDLE_DATA_TAG
22{
23 CONSTBUFFER alias;
24 COUNT_TYPE count;
25 CONSTBUFFER_TYPE buffer_type;
26 CONSTBUFFER_CUSTOM_FREE_FUNC custom_free_func;
27 void* custom_free_func_context;
28 CONSTBUFFER_HANDLE originalHandle; /*where the CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE was build from*/
29} CONSTBUFFER_HANDLE_DATA;
30
31static CONSTBUFFER_HANDLE CONSTBUFFER_Create_Internal(const unsigned char* source, size_t size)
32{
33 CONSTBUFFER_HANDLE result;
34 /*Codes_SRS_CONSTBUFFER_02_005: [The non-NULL handle returned by CONSTBUFFER_Create shall have its ref count set to "1".]*/
35 /*Codes_SRS_CONSTBUFFER_02_010: [The non-NULL handle returned by CONSTBUFFER_CreateFromBuffer shall have its ref count set to "1".]*/
36 result = (CONSTBUFFER_HANDLE)calloc(1, (sizeof(CONSTBUFFER_HANDLE_DATA) + size));
37 if (result == NULL)
38 {
39 /*Codes_SRS_CONSTBUFFER_02_003: [If creating the copy fails then CONSTBUFFER_Create shall return NULL.]*/
40 /*Codes_SRS_CONSTBUFFER_02_008: [If copying the content fails, then CONSTBUFFER_CreateFromBuffer shall fail and return NULL.] */
41 LogError("unable to malloc");
42 /*return as is*/
43 }
44 else
45 {
46 INIT_REF_VAR(result->count);
47
48 /*Codes_SRS_CONSTBUFFER_02_002: [Otherwise, CONSTBUFFER_Create shall create a copy of the memory area pointed to by source having size bytes.]*/
49 result->alias.size = size;
50 if (size == 0)
51 {
52 result->alias.buffer = NULL;
53 }
54 else
55 {
56 unsigned char* temp = (unsigned char*)(result + 1);
57 /*Codes_SRS_CONSTBUFFER_02_004: [Otherwise CONSTBUFFER_Create shall return a non-NULL handle.]*/
58 /*Codes_SRS_CONSTBUFFER_02_007: [Otherwise, CONSTBUFFER_CreateFromBuffer shall copy the content of buffer.]*/
59 /*Codes_SRS_CONSTBUFFER_02_009: [Otherwise, CONSTBUFFER_CreateFromBuffer shall return a non-NULL handle.]*/
60 (void)memcpy(temp, source, size);
61 result->alias.buffer = temp;
62 }
63
64 result->buffer_type = CONSTBUFFER_TYPE_COPIED;
65 }
66 return result;
67}
68
69IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_Create, const unsigned char*, source, size_t, size)
70{
71 CONSTBUFFER_HANDLE result;
72 /*Codes_SRS_CONSTBUFFER_02_001: [If source is NULL and size is different than 0 then CONSTBUFFER_Create shall fail and return NULL.]*/
73 if (
74 (source == NULL) &&
75 (size != 0)
76 )
77 {
78 LogError("invalid arguments passes to CONSTBUFFER_Create");
79 result = NULL;
80 }
81 else
82 {
83 result = CONSTBUFFER_Create_Internal(source, size);
84 }
85 return result;
86}
87
88/*this creates a new constbuffer from an existing BUFFER_HANDLE*/
89IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateFromBuffer, BUFFER_HANDLE, buffer)
90{
91 CONSTBUFFER_HANDLE result;
92 /*Codes_SRS_CONSTBUFFER_02_006: [If buffer is NULL then CONSTBUFFER_CreateFromBuffer shall fail and return NULL.]*/
93 if (buffer == NULL)
94 {
95 LogError("invalid arg passed to CONSTBUFFER_CreateFromBuffer");
96 result = NULL;
97 }
98 else
99 {
100 size_t length = BUFFER_length(buffer);
101 unsigned char* rawBuffer = BUFFER_u_char(buffer);
102 result = CONSTBUFFER_Create_Internal(rawBuffer, length);
103 }
104 return result;
105}
106
107IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateWithMoveMemory, unsigned char*, source, size_t, size)
108{
109 CONSTBUFFER_HANDLE result;
110
111 /* Codes_SRS_CONSTBUFFER_01_001: [ If source is NULL and size is different than 0 then CONSTBUFFER_Create shall fail and return NULL. ]*/
112 if ((source == NULL) && (size > 0))
113 {
114 LogError("Invalid arguments: unsigned char* source=%p, size_t size=%u", source, (unsigned int)size);
115 result = NULL;
116 }
117 else
118 {
119 result = (CONSTBUFFER_HANDLE)calloc(1, sizeof(CONSTBUFFER_HANDLE_DATA));
120 if (result == NULL)
121 {
122 /* Codes_SRS_CONSTBUFFER_01_005: [ If any error occurs, CONSTBUFFER_CreateWithMoveMemory shall fail and return NULL. ]*/
123 LogError("malloc failed");
124 }
125 else
126 {
127 /* Codes_SRS_CONSTBUFFER_01_004: [ If source is non-NULL and size is 0, the source pointer shall be owned (and freed) by the newly created instance of const buffer. ]*/
128 /* Codes_SRS_CONSTBUFFER_01_002: [ CONSTBUFFER_CreateWithMoveMemory shall store the source and size and return a non-NULL handle to the newly created const buffer. ]*/
129 result->alias.buffer = source;
130 result->alias.size = size;
131 result->buffer_type = CONSTBUFFER_TYPE_MEMORY_MOVED;
132
133 /* Codes_SRS_CONSTBUFFER_01_003: [ The non-NULL handle returned by CONSTBUFFER_CreateWithMoveMemory shall have its ref count set to "1". ]*/
134 INIT_REF_VAR(result->count);
135 }
136 }
137
138 return result;
139}
140
141IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateWithCustomFree, const unsigned char*, source, size_t, size, CONSTBUFFER_CUSTOM_FREE_FUNC, customFreeFunc, void*, customFreeFuncContext)
142{
143 CONSTBUFFER_HANDLE result;
144
145 /* Codes_SRS_CONSTBUFFER_01_014: [ customFreeFuncContext shall be allowed to be NULL. ]*/
146
147 if (
148 /* Codes_SRS_CONSTBUFFER_01_006: [ If source is NULL and size is different than 0 then CONSTBUFFER_CreateWithCustomFree shall fail and return NULL. ]*/
149 ((source == NULL) && (size > 0)) ||
150 /* Codes_SRS_CONSTBUFFER_01_013: [ If customFreeFunc is NULL, CONSTBUFFER_CreateWithCustomFree shall fail and return NULL. ]*/
151 (customFreeFunc == NULL)
152 )
153 {
154 LogError("Invalid arguments: unsigned char* source=%p, size_t size=%u, customFreeFunc=%p, customFreeFuncContext=%p",
155 source, (unsigned int)size, customFreeFunc, customFreeFuncContext);
156 result = NULL;
157 }
158 else
159 {
160 result = (CONSTBUFFER_HANDLE)calloc(1, sizeof(CONSTBUFFER_HANDLE_DATA));
161 if (result == NULL)
162 {
163 /* Codes_SRS_CONSTBUFFER_01_011: [ If any error occurs, CONSTBUFFER_CreateWithMoveMemory shall fail and return NULL. ]*/
164 LogError("malloc failed");
165 }
166 else
167 {
168 /* Codes_SRS_CONSTBUFFER_01_007: [ If source is non-NULL and size is 0, the source pointer shall be owned (and freed) by the newly created instance of const buffer. ]*/
169 /* Codes_SRS_CONSTBUFFER_01_008: [ CONSTBUFFER_CreateWithCustomFree shall store the source and size and return a non-NULL handle to the newly created const buffer. ]*/
170 result->alias.buffer = source;
171 result->alias.size = size;
172 result->buffer_type = CONSTBUFFER_TYPE_WITH_CUSTOM_FREE;
173
174 /* Codes_SRS_CONSTBUFFER_01_009: [ CONSTBUFFER_CreateWithCustomFree shall store customFreeFunc and customFreeFuncContext in order to use them to free the memory when the CONST buffer resources are freed. ]*/
175 result->custom_free_func = customFreeFunc;
176 result->custom_free_func_context = customFreeFuncContext;
177
178 /* Codes_SRS_CONSTBUFFER_01_010: [ The non-NULL handle returned by CONSTBUFFER_CreateWithCustomFree shall have its ref count set to 1. ]*/
179 INIT_REF_VAR(result->count);
180 }
181 }
182
183 return result;
184}
185
186IMPLEMENT_MOCKABLE_FUNCTION(, CONSTBUFFER_HANDLE, CONSTBUFFER_CreateFromOffsetAndSize, CONSTBUFFER_HANDLE, handle, size_t, offset, size_t, size)
187{
188 CONSTBUFFER_HANDLE result;
189
190 if (
191 /*Codes_SRS_CONSTBUFFER_02_025: [ If handle is NULL then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
192 (handle == NULL) ||
193 /*Codes_SRS_CONSTBUFFER_02_026: [ If offset is greater than or equal to handles's size then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
194 (offset > handle->alias.size) ||
195 /*Codes_SRS_CONSTBUFFER_02_032: [ If there are any failures then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
196 (offset > SIZE_MAX - size) ||
197 /*Codes_SRS_CONSTBUFFER_02_027: [ If offset + size exceed handles's size then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
198 (offset + size > handle->alias.size)
199 )
200 {
201 LogError("invalid arguments CONSTBUFFER_HANDLE handle=%p, size_t offset=%zu, size_t size=%zu",
202 handle, offset, size);
203 result = NULL;
204 }
205 else
206 {
207 /*Codes_SRS_CONSTBUFFER_02_028: [ CONSTBUFFER_CreateFromOffsetAndSize shall allocate memory for a new CONSTBUFFER_HANDLE's content. ]*/
208 result = (CONSTBUFFER_HANDLE)calloc(1, sizeof(CONSTBUFFER_HANDLE_DATA));
209 if (result == NULL)
210 {
211 /*Codes_SRS_CONSTBUFFER_02_032: [ If there are any failures then CONSTBUFFER_CreateFromOffsetAndSize shall fail and return NULL. ]*/
212 LogError("failure in malloc(sizeof(CONSTBUFFER_HANDLE_DATA)=%zu)", sizeof(CONSTBUFFER_HANDLE_DATA));
213 /*return as is*/
214 }
215 else
216 {
217 result->buffer_type = CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE;
218 result->alias.buffer = handle->alias.buffer+offset;
219 result->alias.size = size;
220
221 /*Codes_SRS_CONSTBUFFER_02_030: [ CONSTBUFFER_CreateFromOffsetAndSize shall increment the reference count of handle. ]*/
222 INC_REF_VAR(handle->count);
223 result->originalHandle = handle;
224
225 /*Codes_SRS_CONSTBUFFER_02_029: [ CONSTBUFFER_CreateFromOffsetAndSize shall set the ref count of the newly created CONSTBUFFER_HANDLE to the initial value. ]*/
226 INIT_REF_VAR(result->count);
227
228 /*Codes_SRS_CONSTBUFFER_02_031: [ CONSTBUFFER_CreateFromOffsetAndSize shall succeed and return a non-NULL value. ]*/
229 }
230 }
231 return result;
232}
233
234IMPLEMENT_MOCKABLE_FUNCTION(, void, CONSTBUFFER_IncRef, CONSTBUFFER_HANDLE, constbufferHandle)
235{
236 if (constbufferHandle == NULL)
237 {
238 /*Codes_SRS_CONSTBUFFER_02_013: [If constbufferHandle is NULL then CONSTBUFFER_IncRef shall return.]*/
239 LogError("Invalid arguments: CONSTBUFFER_HANDLE constbufferHandle=%p", constbufferHandle);
240 }
241 else
242 {
243 /*Codes_SRS_CONSTBUFFER_02_014: [Otherwise, CONSTBUFFER_IncRef shall increment the reference count.]*/
244 INC_REF_VAR(constbufferHandle->count);
245 }
246}
247
248IMPLEMENT_MOCKABLE_FUNCTION(, const CONSTBUFFER*, CONSTBUFFER_GetContent, CONSTBUFFER_HANDLE, constbufferHandle)
249{
250 const CONSTBUFFER* result;
251 if (constbufferHandle == NULL)
252 {
253 /*Codes_SRS_CONSTBUFFER_02_011: [If constbufferHandle is NULL then CONSTBUFFER_GetContent shall return NULL.]*/
254 result = NULL;
255 LogError("invalid arg");
256 }
257 else
258 {
259 /*Codes_SRS_CONSTBUFFER_02_012: [Otherwise, CONSTBUFFER_GetContent shall return a const CONSTBUFFER* that matches byte by byte the original bytes used to created the const buffer and has the same length.]*/
260 result = &(constbufferHandle->alias);
261 }
262 return result;
263}
264
265static void CONSTBUFFER_DecRef_internal(CONSTBUFFER_HANDLE constbufferHandle)
266{
267 /*Codes_SRS_CONSTBUFFER_02_016: [Otherwise, CONSTBUFFER_DecRef shall decrement the refcount on the constbufferHandle handle.]*/
268 if (DEC_REF_VAR(constbufferHandle->count) == DEC_RETURN_ZERO)
269 {
270 if (constbufferHandle->buffer_type == CONSTBUFFER_TYPE_MEMORY_MOVED)
271 {
272 free((void*)constbufferHandle->alias.buffer);
273 }
274 else if (constbufferHandle->buffer_type == CONSTBUFFER_TYPE_WITH_CUSTOM_FREE)
275 {
276 /* Codes_SRS_CONSTBUFFER_01_012: [ If the buffer was created by calling CONSTBUFFER_CreateWithCustomFree, the customFreeFunc function shall be called to free the memory, while passed customFreeFuncContext as argument. ]*/
277 constbufferHandle->custom_free_func(constbufferHandle->custom_free_func_context);
278 }
279 /*Codes_SRS_CONSTBUFFER_02_024: [ If the constbufferHandle was created by calling CONSTBUFFER_CreateFromOffsetAndSize then CONSTBUFFER_DecRef shall decrement the ref count of the original handle passed to CONSTBUFFER_CreateFromOffsetAndSize. ]*/
280 else if (constbufferHandle->buffer_type == CONSTBUFFER_TYPE_FROM_OFFSET_AND_SIZE)
281 {
282 CONSTBUFFER_DecRef_internal(constbufferHandle->originalHandle);
283 }
284
285 /*Codes_SRS_CONSTBUFFER_02_017: [If the refcount reaches zero, then CONSTBUFFER_DecRef shall deallocate all resources used by the CONSTBUFFER_HANDLE.]*/
286 free(constbufferHandle);
287 }
288}
289
290IMPLEMENT_MOCKABLE_FUNCTION(, void, CONSTBUFFER_DecRef, CONSTBUFFER_HANDLE, constbufferHandle)
291{
292 if (constbufferHandle == NULL)
293 {
294 /*Codes_SRS_CONSTBUFFER_02_015: [If constbufferHandle is NULL then CONSTBUFFER_DecRef shall do nothing.]*/
295 LogError("Invalid arguments: CONSTBUFFER_HANDLE constbufferHandle=%p", constbufferHandle);
296 }
297 else
298 {
299 CONSTBUFFER_DecRef_internal(constbufferHandle);
300 }
301}
302
303
304IMPLEMENT_MOCKABLE_FUNCTION(, bool, CONSTBUFFER_HANDLE_contain_same, CONSTBUFFER_HANDLE, left, CONSTBUFFER_HANDLE, right)
305{
306 bool result;
307 if (left == NULL)
308 {
309 if (right == NULL)
310 {
311 /*Codes_SRS_CONSTBUFFER_02_018: [ If left is NULL and right is NULL then CONSTBUFFER_HANDLE_contain_same shall return true. ]*/
312 result = true;
313 }
314 else
315 {
316 /*Codes_SRS_CONSTBUFFER_02_019: [ If left is NULL and right is not NULL then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
317 result = false;
318 }
319 }
320 else
321 {
322 if (right == NULL)
323 {
324 /*Codes_SRS_CONSTBUFFER_02_020: [ If left is not NULL and right is NULL then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
325 result = false;
326 }
327 else
328 {
329 if (left->alias.size != right->alias.size)
330 {
331 /*Codes_SRS_CONSTBUFFER_02_021: [ If left's size is different than right's size then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
332 result = false;
333 }
334 else
335 {
336 if (memcmp(left->alias.buffer, right->alias.buffer, left->alias.size) != 0)
337 {
338 /*Codes_SRS_CONSTBUFFER_02_022: [ If left's buffer is contains different bytes than rights's buffer then CONSTBUFFER_HANDLE_contain_same shall return false. ]*/
339 result = false;
340 }
341 else
342 {
343 /*Codes_SRS_CONSTBUFFER_02_023: [ CONSTBUFFER_HANDLE_contain_same shall return true. ]*/
344 result = true;
345 }
346 }
347 }
348 }
349 return result;
350}
Note: See TracBrowser for help on using the repository browser.