source: azure_iot_hub/trunk/azure_iohub/c-utility/src/map.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 22.5 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 "azure_c_shared_utility/gballoc.h"
6#include "azure_c_shared_utility/map.h"
7#include "azure_c_shared_utility/optimize_size.h"
8#include "azure_c_shared_utility/xlogging.h"
9#include "azure_c_shared_utility/strings.h"
10
11MU_DEFINE_ENUM_STRINGS(MAP_RESULT, MAP_RESULT_VALUES);
12
13typedef struct MAP_HANDLE_DATA_TAG
14{
15 char** keys;
16 char** values;
17 size_t count;
18 MAP_FILTER_CALLBACK mapFilterCallback;
19}MAP_HANDLE_DATA;
20
21#define LOG_MAP_ERROR LogError("result = %s", MU_ENUM_TO_STRING(MAP_RESULT, result));
22
23MAP_HANDLE Map_Create(MAP_FILTER_CALLBACK mapFilterFunc)
24{
25 /*Codes_SRS_MAP_02_001: [Map_Create shall create a new, empty map.]*/
26 MAP_HANDLE_DATA* result = (MAP_HANDLE_DATA*)malloc(sizeof(MAP_HANDLE_DATA));
27 /*Codes_SRS_MAP_02_002: [If during creation there are any error, then Map_Create shall return NULL.]*/
28 if (result != NULL)
29 {
30 /*Codes_SRS_MAP_02_003: [Otherwise, it shall return a non-NULL handle that can be used in subsequent calls.] */
31 result->keys = NULL;
32 result->values = NULL;
33 result->count = 0;
34 result->mapFilterCallback = mapFilterFunc;
35 }
36 return (MAP_HANDLE)result;
37}
38
39void Map_Destroy(MAP_HANDLE handle)
40{
41 /*Codes_SRS_MAP_02_005: [If parameter handle is NULL then Map_Destroy shall take no action.] */
42 if (handle != NULL)
43 {
44 /*Codes_SRS_MAP_02_004: [Map_Destroy shall release all resources associated with the map.] */
45 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
46 size_t i;
47
48 for (i = 0; i < handleData->count; i++)
49 {
50 free(handleData->keys[i]);
51 free(handleData->values[i]);
52 }
53 free(handleData->keys);
54 free(handleData->values);
55 free(handleData);
56 }
57}
58
59/*makes a copy of a vector of const char*, having size "size". source cannot be NULL*/
60/*returns NULL if it fails*/
61static char** Map_CloneVector(const char*const * source, size_t count)
62{
63 char** result;
64 result = (char**)malloc(count *sizeof(char*));
65 if (result == NULL)
66 {
67 /*do nothing, just return it (NULL)*/
68 }
69 else
70 {
71 size_t i;
72 for (i = 0; i < count; i++)
73 {
74 if (mallocAndStrcpy_s(result + i, source[i]) != 0)
75 {
76 break;
77 }
78 }
79
80 if (i == count)
81 {
82 /*it is all good, proceed to return result*/
83 }
84 else
85 {
86 size_t j;
87 for (j = 0; j < i; j++)
88 {
89 free(result[j]);
90 }
91 free(result);
92 result = NULL;
93 }
94 }
95 return result;
96}
97
98/*Codes_SRS_MAP_02_039: [Map_Clone shall make a copy of the map indicated by parameter handle and return a non-NULL handle to it.]*/
99MAP_HANDLE Map_Clone(MAP_HANDLE handle)
100{
101 MAP_HANDLE_DATA* result;
102 if (handle == NULL)
103 {
104 /*Codes_SRS_MAP_02_038: [Map_Clone returns NULL if parameter handle is NULL.]*/
105 result = NULL;
106 LogError("invalid arg to Map_Clone (NULL)");
107 }
108 else
109 {
110 MAP_HANDLE_DATA * handleData = (MAP_HANDLE_DATA *)handle;
111 result = (MAP_HANDLE_DATA*)malloc(sizeof(MAP_HANDLE_DATA));
112 if (result == NULL)
113 {
114 /*Codes_SRS_MAP_02_047: [If during cloning, any operation fails, then Map_Clone shall return NULL.] */
115 /*do nothing, proceed to return it, this is an error case*/
116 LogError("unable to malloc");
117 }
118 else
119 {
120 if (handleData->count == 0)
121 {
122 result->count = 0;
123 result->keys = NULL;
124 result->values = NULL;
125 result->mapFilterCallback = NULL;
126 }
127 else
128 {
129 result->mapFilterCallback = handleData->mapFilterCallback;
130 result->count = handleData->count;
131 if( (result->keys = Map_CloneVector((const char* const*)handleData->keys, handleData->count))==NULL)
132 {
133 /*Codes_SRS_MAP_02_047: [If during cloning, any operation fails, then Map_Clone shall return NULL.] */
134 LogError("unable to clone keys");
135 free(result);
136 result = NULL;
137 }
138 else if ((result->values = Map_CloneVector((const char* const*)handleData->values, handleData->count)) == NULL)
139 {
140 size_t i;
141 /*Codes_SRS_MAP_02_047: [If during cloning, any operation fails, then Map_Clone shall return NULL.] */
142 LogError("unable to clone values");
143 for (i = 0; i < result->count; i++)
144 {
145 free(result->keys[i]);
146 }
147 free(result->keys);
148 free(result);
149 result = NULL;
150 }
151 else
152 {
153 /*all fine, return it*/
154 }
155 }
156 }
157 }
158 return (MAP_HANDLE)result;
159}
160
161static int Map_IncreaseStorageKeysValues(MAP_HANDLE_DATA* handleData)
162{
163 int result;
164 char** newKeys = (char**)realloc(handleData->keys, (handleData->count + 1) * sizeof(char*));
165 if (newKeys == NULL)
166 {
167 LogError("realloc error");
168 result = MU_FAILURE;
169 }
170 else
171 {
172 char** newValues;
173 handleData->keys = newKeys;
174 handleData->keys[handleData->count] = NULL;
175 newValues = (char**)realloc(handleData->values, (handleData->count + 1) * sizeof(char*));
176 if (newValues == NULL)
177 {
178 LogError("realloc error");
179 if (handleData->count == 0) /*avoiding an implementation defined behavior */
180 {
181 free(handleData->keys);
182 handleData->keys = NULL;
183 }
184 else
185 {
186 char** undoneKeys = (char**)realloc(handleData->keys, (handleData->count) * sizeof(char*));
187 if (undoneKeys == NULL)
188 {
189 LogError("CATASTROPHIC error, unable to undo through realloc to a smaller size");
190 }
191 else
192 {
193 handleData->keys = undoneKeys;
194 }
195 }
196 result = MU_FAILURE;
197 }
198 else
199 {
200 handleData->values = newValues;
201 handleData->values[handleData->count] = NULL;
202 handleData->count++;
203 result = 0;
204 }
205 }
206 return result;
207}
208
209static void Map_DecreaseStorageKeysValues(MAP_HANDLE_DATA* handleData)
210{
211 if (handleData->count == 1)
212 {
213 free(handleData->keys);
214 handleData->keys = NULL;
215 free(handleData->values);
216 handleData->values = NULL;
217 handleData->count = 0;
218 handleData->mapFilterCallback = NULL;
219 }
220 else
221 {
222 /*certainly > 1...*/
223 char** undoneValues;
224 char** undoneKeys = (char**)realloc(handleData->keys, sizeof(char*)* (handleData->count - 1));
225 if (undoneKeys == NULL)
226 {
227 LogError("CATASTROPHIC error, unable to undo through realloc to a smaller size");
228 }
229 else
230 {
231 handleData->keys = undoneKeys;
232 }
233
234 undoneValues = (char**)realloc(handleData->values, sizeof(char*)* (handleData->count - 1));
235 if (undoneValues == NULL)
236 {
237 LogError("CATASTROPHIC error, unable to undo through realloc to a smaller size");
238 }
239 else
240 {
241 handleData->values = undoneValues;
242 }
243
244 handleData->count--;
245 }
246}
247
248static char** findKey(MAP_HANDLE_DATA* handleData, const char* key)
249{
250 char** result;
251 if (handleData->keys == NULL)
252 {
253 result = NULL;
254 }
255 else
256 {
257 size_t i;
258 result = NULL;
259 for (i = 0; i < handleData->count; i++)
260 {
261 if (strcmp(handleData->keys[i], key) == 0)
262 {
263 result = handleData->keys + i;
264 break;
265 }
266 }
267 }
268 return result;
269}
270
271static char** findValue(MAP_HANDLE_DATA* handleData, const char* value)
272{
273 char** result;
274 if (handleData->values == NULL)
275 {
276 result = NULL;
277 }
278 else
279 {
280 size_t i;
281 result = NULL;
282 for (i = 0; i < handleData->count; i++)
283 {
284 if (strcmp(handleData->values[i], value) == 0)
285 {
286 result = handleData->values + i;
287 break;
288 }
289 }
290 }
291 return result;
292}
293
294static int insertNewKeyValue(MAP_HANDLE_DATA* handleData, const char* key, const char* value)
295{
296 int result;
297 if (Map_IncreaseStorageKeysValues(handleData) != 0) /*this increases handleData->count*/
298 {
299 result = MU_FAILURE;
300 }
301 else
302 {
303 if (mallocAndStrcpy_s(&(handleData->keys[handleData->count - 1]), key) != 0)
304 {
305 Map_DecreaseStorageKeysValues(handleData);
306 LogError("unable to mallocAndStrcpy_s");
307 result = MU_FAILURE;
308 }
309 else
310 {
311 if (mallocAndStrcpy_s(&(handleData->values[handleData->count - 1]), value) != 0)
312 {
313 free(handleData->keys[handleData->count - 1]);
314 Map_DecreaseStorageKeysValues(handleData);
315 LogError("unable to mallocAndStrcpy_s");
316 result = MU_FAILURE;
317 }
318 else
319 {
320 result = 0;
321 }
322 }
323 }
324 return result;
325}
326
327MAP_RESULT Map_Add(MAP_HANDLE handle, const char* key, const char* value)
328{
329 MAP_RESULT result;
330 /*Codes_SRS_MAP_02_006: [If parameter handle is NULL then Map_Add shall return MAP_INVALID_ARG.] */
331 /*Codes_SRS_MAP_02_007: [If parameter key is NULL then Map_Add shall return MAP_INVALID_ARG.]*/
332 /*Codes_SRS_MAP_02_008: [If parameter value is NULL then Map_Add shall return MAP_INVALID_ARG.] */
333 if (
334 (handle == NULL) ||
335 (key == NULL) ||
336 (value == NULL)
337 )
338 {
339 result = MAP_INVALIDARG;
340 LOG_MAP_ERROR;
341 }
342 else
343 {
344 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
345 /*Codes_SRS_MAP_02_009: [If the key already exists, then Map_Add shall return MAP_KEYEXISTS.] */
346 if (findKey(handleData, key) != NULL)
347 {
348 result = MAP_KEYEXISTS;
349 }
350 else
351 {
352 /* Codes_SRS_MAP_07_009: [If the mapFilterCallback function is not NULL, then the return value will be check and if it is not zero then Map_Add shall return MAP_FILTER_REJECT.] */
353 if ( (handleData->mapFilterCallback != NULL) && (handleData->mapFilterCallback(key, value) != 0) )
354 {
355 result = MAP_FILTER_REJECT;
356 }
357 else
358 {
359 /*Codes_SRS_MAP_02_010: [Otherwise, Map_Add shall add the pair <key,value> to the map.] */
360 if (insertNewKeyValue(handleData, key, value) != 0)
361 {
362 /*Codes_SRS_MAP_02_011: [If adding the pair <key,value> fails then Map_Add shall return MAP_ERROR.] */
363 result = MAP_ERROR;
364 LOG_MAP_ERROR;
365 }
366 else
367 {
368 /*Codes_SRS_MAP_02_012: [Otherwise, Map_Add shall return MAP_OK.] */
369 result = MAP_OK;
370 }
371 }
372 }
373 }
374 return result;
375}
376
377MAP_RESULT Map_AddOrUpdate(MAP_HANDLE handle, const char* key, const char* value)
378{
379 MAP_RESULT result;
380 /*Codes_SRS_MAP_02_013: [If parameter handle is NULL then Map_AddOrUpdate shall return MAP_INVALID_ARG.]*/
381 /*Codes_SRS_MAP_02_014: [If parameter key is NULL then Map_AddOrUpdate shall return MAP_INVALID_ARG.]*/
382 /*Codes_SRS_MAP_02_015: [If parameter value is NULL then Map_AddOrUpdate shall return MAP_INVALID_ARG.] */
383 if (
384 (handle == NULL) ||
385 (key == NULL) ||
386 (value == NULL)
387 )
388 {
389 result = MAP_INVALIDARG;
390 LOG_MAP_ERROR;
391 }
392 else
393 {
394 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
395
396 /* Codes_SRS_MAP_07_008: [If the mapFilterCallback function is not NULL, then the return value will be check and if it is not zero then Map_AddOrUpdate shall return MAP_FILTER_REJECT.] */
397 if (handleData->mapFilterCallback != NULL && handleData->mapFilterCallback(key, value) != 0)
398 {
399 result = MAP_FILTER_REJECT;
400 }
401 else
402 {
403 char** whereIsIt = findKey(handleData, key);
404 if (whereIsIt == NULL)
405 {
406 /*Codes_SRS_MAP_02_017: [Otherwise, Map_AddOrUpdate shall add the pair <key,value> to the map.]*/
407 if (insertNewKeyValue(handleData, key, value) != 0)
408 {
409 result = MAP_ERROR;
410 LOG_MAP_ERROR;
411 }
412 else
413 {
414 result = MAP_OK;
415 }
416 }
417 else
418 {
419 /*Codes_SRS_MAP_02_016: [If the key already exists, then Map_AddOrUpdate shall overwrite the value of the existing key with parameter value.]*/
420 size_t index = whereIsIt - handleData->keys;
421 size_t valueLength = strlen(value);
422 /*try to realloc value of this key*/
423 char* newValue = (char*)realloc(handleData->values[index],valueLength + 1);
424 if (newValue == NULL)
425 {
426 result = MAP_ERROR;
427 LOG_MAP_ERROR;
428 }
429 else
430 {
431 (void)memcpy(newValue, value, valueLength + 1);
432 handleData->values[index] = newValue;
433 /*Codes_SRS_MAP_02_019: [Otherwise, Map_AddOrUpdate shall return MAP_OK.] */
434 result = MAP_OK;
435 }
436 }
437 }
438 }
439 return result;
440}
441
442MAP_RESULT Map_Delete(MAP_HANDLE handle, const char* key)
443{
444 MAP_RESULT result;
445 /*Codes_SRS_MAP_02_020: [If parameter handle is NULL then Map_Delete shall return MAP_INVALIDARG.]*/
446 /*Codes_SRS_MAP_02_021: [If parameter key is NULL then Map_Delete shall return MAP_INVALIDARG.]*/
447 if (
448 (handle == NULL) ||
449 (key == NULL)
450 )
451 {
452 result = MAP_INVALIDARG;
453 LOG_MAP_ERROR;
454 }
455 else
456 {
457 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
458 char** whereIsIt = findKey(handleData,key);
459 if (whereIsIt == NULL)
460 {
461 /*Codes_SRS_MAP_02_022: [If key does not exist then Map_Delete shall return MAP_KEYNOTFOUND.]*/
462 result = MAP_KEYNOTFOUND;
463 }
464 else
465 {
466 /*Codes_SRS_MAP_02_023: [Otherwise, Map_Delete shall remove the key and its associated value from the map and return MAP_OK.]*/
467 size_t index = whereIsIt - handleData->keys;
468 free(handleData->keys[index]);
469 free(handleData->values[index]);
470 memmove(handleData->keys + index, handleData->keys + index + 1, (handleData->count - index - 1)*sizeof(char*)); /*if order doesn't matter... then this can be optimized*/
471 memmove(handleData->values + index, handleData->values + index + 1, (handleData->count - index - 1)*sizeof(char*));
472 Map_DecreaseStorageKeysValues(handleData);
473 result = MAP_OK;
474 }
475
476 }
477 return result;
478}
479
480MAP_RESULT Map_ContainsKey(MAP_HANDLE handle, const char* key, bool* keyExists)
481{
482 MAP_RESULT result;
483 /*Codes_SRS_MAP_02_024: [If parameter handle, key or keyExists are NULL then Map_ContainsKey shall return MAP_INVALIDARG.]*/
484 if (
485 (handle ==NULL) ||
486 (key == NULL) ||
487 (keyExists == NULL)
488 )
489 {
490 result = MAP_INVALIDARG;
491 LOG_MAP_ERROR;
492 }
493 else
494 {
495 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
496 /*Codes_SRS_MAP_02_025: [Otherwise if a key exists then Map_ContainsKey shall return MAP_OK and shall write in keyExists "true".]*/
497 /*Codes_SRS_MAP_02_026: [If a key doesn't exist, then Map_ContainsKey shall return MAP_OK and write in keyExists "false".] */
498 *keyExists = (findKey(handleData, key) != NULL) ? true: false;
499 result = MAP_OK;
500 }
501 return result;
502}
503
504MAP_RESULT Map_ContainsValue(MAP_HANDLE handle, const char* value, bool* valueExists)
505{
506 MAP_RESULT result;
507 /*Codes_SRS_MAP_02_027: [If parameter handle, value or valueExists is NULL then Map_ContainsValue shall return MAP_INVALIDARG.] */
508 if (
509 (handle == NULL) ||
510 (value == NULL) ||
511 (valueExists == NULL)
512 )
513 {
514 result = MAP_INVALIDARG;
515 LOG_MAP_ERROR;
516 }
517 else
518 {
519 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA*)handle;
520 /*Codes_SRS_MAP_02_028: [Otherwise, if a pair <key, value> has its value equal to the parameter value, the Map_ContainsValue shall return MAP_OK and shall write in valueExists "true".]*/
521 /*Codes_SRS_MAP_02_029: [Otherwise, if such a <key, value> does not exist, then Map_ContainsValue shall return MAP_OK and shall write in valueExists "false".] */
522 *valueExists = (findValue(handleData, value) != NULL) ? true : false;
523 result = MAP_OK;
524 }
525 return result;
526}
527
528const char* Map_GetValueFromKey(MAP_HANDLE handle, const char* key)
529{
530 const char* result;
531 /*Codes_SRS_MAP_02_040: [If parameter handle or key is NULL then Map_GetValueFromKey returns NULL.]*/
532 if (
533 (handle == NULL) ||
534 (key == NULL)
535 )
536 {
537 result = NULL;
538 LogError("invalid parameter to Map_GetValueFromKey");
539 }
540 else
541 {
542 MAP_HANDLE_DATA * handleData = (MAP_HANDLE_DATA *)handle;
543 char** whereIsIt = findKey(handleData, key);
544 if(whereIsIt == NULL)
545 {
546 /*Codes_SRS_MAP_02_041: [If the key is not found, then Map_GetValueFromKey returns NULL.]*/
547 result = NULL;
548 }
549 else
550 {
551 /*Codes_SRS_MAP_02_042: [Otherwise, Map_GetValueFromKey returns the key's value.] */
552 size_t index = whereIsIt - handleData->keys;
553 result = handleData->values[index];
554 }
555 }
556 return result;
557}
558
559MAP_RESULT Map_GetInternals(MAP_HANDLE handle, const char*const** keys, const char*const** values, size_t* count)
560{
561 MAP_RESULT result;
562 /*Codes_SRS_MAP_02_046: [If parameter handle, keys, values or count is NULL then Map_GetInternals shall return MAP_INVALIDARG.] */
563 if (
564 (handle == NULL) ||
565 (keys == NULL) ||
566 (values == NULL) ||
567 (count == NULL)
568 )
569 {
570 result = MAP_INVALIDARG;
571 LOG_MAP_ERROR;
572 }
573 else
574 {
575 /*Codes_SRS_MAP_02_043: [Map_GetInternals shall produce in *keys an pointer to an array of const char* having all the keys stored so far by the map.]*/
576 /*Codes_SRS_MAP_02_044: [Map_GetInternals shall produce in *values a pointer to an array of const char* having all the values stored so far by the map.]*/
577 /*Codes_SRS_MAP_02_045: [ Map_GetInternals shall produce in *count the number of stored keys and values.]*/
578 MAP_HANDLE_DATA * handleData = (MAP_HANDLE_DATA *)handle;
579 *keys =(const char* const*)(handleData->keys);
580 *values = (const char* const*)(handleData->values);
581 *count = handleData->count;
582 result = MAP_OK;
583 }
584 return result;
585}
586
587STRING_HANDLE Map_ToJSON(MAP_HANDLE handle)
588{
589 STRING_HANDLE result;
590 /*Codes_SRS_MAP_02_052: [If parameter handle is NULL then Map_ToJSON shall return NULL.] */
591 if (handle == NULL)
592 {
593 result = NULL;
594 LogError("invalid arg (NULL)");
595 }
596 else
597 {
598 /*Codes_SRS_MAP_02_048: [Map_ToJSON shall produce a STRING_HANDLE representing the content of the MAP.] */
599 result = STRING_construct("{");
600 if (result == NULL)
601 {
602 LogError("STRING_construct failed");
603 }
604 else
605 {
606 size_t i;
607 MAP_HANDLE_DATA* handleData = (MAP_HANDLE_DATA *)handle;
608 /*Codes_SRS_MAP_02_049: [If the MAP is empty, then Map_ToJSON shall produce the string "{}".*/
609 bool breakFor = false; /*used to break out of for*/
610 for (i = 0; (i < handleData->count) && (!breakFor); i++)
611 {
612 /*add one entry to the JSON*/
613 /*Codes_SRS_MAP_02_050: [If the map has properties then Map_ToJSON shall produce the following string:{"name1":"value1", "name2":"value2" ...}]*/
614 STRING_HANDLE key = STRING_new_JSON(handleData->keys[i]);
615 if (key == NULL)
616 {
617 LogError("STRING_new_JSON failed");
618 STRING_delete(result);
619 result = NULL;
620 breakFor = true;
621 }
622 else
623 {
624 STRING_HANDLE value = STRING_new_JSON(handleData->values[i]);
625 if (value == NULL)
626 {
627 LogError("STRING_new_JSON failed");
628 STRING_delete(result);
629 result = NULL;
630 breakFor = true;
631 }
632 else
633 {
634 if (!(
635 ((i>0) ? (STRING_concat(result, ",") == 0) : 1) &&
636 (STRING_concat_with_STRING(result, key) == 0) &&
637 (STRING_concat(result, ":") == 0) &&
638 (STRING_concat_with_STRING(result, value) == 0)
639 ))
640 {
641 LogError("failed to build the JSON");
642 STRING_delete(result);
643 result = NULL;
644 breakFor = true;
645 }
646 else
647 {
648 /*all nice, go to the next element in the map*/
649 }
650 STRING_delete(value);
651 }
652 STRING_delete(key);
653 }
654 }
655
656 if (breakFor)
657 {
658 LogError("error happened during JSON string builder");
659 }
660 else
661 {
662 if (STRING_concat(result, "}") != 0)
663 {
664 LogError("failed to build the JSON");
665 STRING_delete(result);
666 result = NULL;
667 }
668 else
669 {
670 /*return as is, JSON has been build*/
671 }
672 }
673 }
674 }
675 return result;
676
677}
Note: See TracBrowser for help on using the repository browser.