1 // Copyright (c) 2014-2020 Josh Blum
2 // SPDX-License-Identifier: BSL-1.0
3
4 #include "ErrorHelpers.hpp"
5 #include "TypeHelpers.hpp"
6 #include <SoapySDR/Types.h>
7 #include <cstdlib>
8 #include <cstring>
9
10 extern "C" {
11
SoapySDRKwargs_fromString(const char * markup)12 SoapySDRKwargs SoapySDRKwargs_fromString(const char *markup)
13 {
14 __SOAPY_SDR_C_TRY
15 return toKwargs(SoapySDR::KwargsFromString(markup));
16 __SOAPY_SDR_C_CATCH_RET(SoapySDRKwargs());
17 }
18
SoapySDRKwargs_toString(const SoapySDRKwargs * args)19 char *SoapySDRKwargs_toString(const SoapySDRKwargs *args)
20 {
21 __SOAPY_SDR_C_TRY
22 return toCString(SoapySDR::KwargsToString(toKwargs(args)));
23 __SOAPY_SDR_C_CATCH_RET(nullptr);
24 }
25
SoapySDR_free(void * ptr)26 void SoapySDR_free(void *ptr)
27 {
28 std::free(ptr);
29 }
30
SoapySDRStrings_clear(char *** elems,const size_t length)31 void SoapySDRStrings_clear(char ***elems, const size_t length)
32 {
33 for (size_t i = 0; i < length; i++)
34 {
35 SoapySDR_free((*elems)[i]);
36 }
37 SoapySDR_free(*elems);
38 *elems = NULL;
39 }
40
SoapySDRKwargs_set(SoapySDRKwargs * args,const char * key,const char * val)41 int SoapySDRKwargs_set(SoapySDRKwargs *args, const char *key, const char *val)
42 {
43 for (size_t i = 0; i < args->size; i++)
44 {
45 if (std::strcmp(args->keys[i], key) == 0)
46 {
47 auto new_val = strdup(val);
48 if (new_val == nullptr) return -1;
49 SoapySDR_free(args->vals[i]);
50 args->vals[i] = new_val;
51 return 0;
52 }
53 }
54
55 //increase the memory size by 1 element and assign the new pointer on success
56 //the container will continue to be in a good state even after realloc failure
57 auto new_keys = (char **)std::realloc(args->keys, sizeof(char *)*(args->size+1));
58 auto new_vals = (char **)std::realloc(args->vals, sizeof(char *)*(args->size+1));
59 if (new_keys != nullptr) args->keys = new_keys;
60 if (new_vals != nullptr) args->vals = new_vals;
61
62 //error: the current allocation has no space for the new element
63 if (new_keys == nullptr or new_vals == nullptr) return -1;
64
65 //make copies of the key and value to store
66 auto new_key = strdup(key);
67 auto new_val = strdup(val);
68
69 //error: could not make a copy of the key or value string
70 //free both pointers in case one of them was allocated
71 if (new_key == nullptr or new_val == nullptr)
72 {
73 SoapySDR_free(new_key);
74 SoapySDR_free(new_val);
75 return -1;
76 }
77
78 //assign the new entry
79 args->keys[args->size] = new_key;
80 args->vals[args->size] = new_val;
81 args->size++;
82 return 0;
83 }
84
SoapySDRKwargs_get(const SoapySDRKwargs * args,const char * key)85 const char *SoapySDRKwargs_get(const SoapySDRKwargs *args, const char *key)
86 {
87 for (size_t i = 0; i < args->size; i++)
88 {
89 if (strcmp(args->keys[i], key) == 0)
90 {
91 return args->vals[i];
92 }
93 }
94 return NULL;
95 }
96
SoapySDRKwargs_clear(SoapySDRKwargs * args)97 void SoapySDRKwargs_clear(SoapySDRKwargs *args)
98 {
99 SoapySDRStrings_clear(&args->keys, args->size);
100 SoapySDRStrings_clear(&args->vals, args->size);
101 args->size = 0;
102 }
103
SoapySDRKwargsList_clear(SoapySDRKwargs * args,const size_t length)104 void SoapySDRKwargsList_clear(SoapySDRKwargs *args, const size_t length)
105 {
106 for (size_t i = 0; i < length; i++) SoapySDRKwargs_clear(args+i);
107 SoapySDR_free(args);
108 }
109
SoapySDRArgInfo_clear(SoapySDRArgInfo * info)110 void SoapySDRArgInfo_clear(SoapySDRArgInfo *info)
111 {
112 //clear strings
113 SoapySDR_free(info->key);
114 info->key = NULL;
115
116 SoapySDR_free(info->value);
117 info->value = NULL;
118
119 SoapySDR_free(info->name);
120 info->name = NULL;
121
122 SoapySDR_free(info->description);
123 info->description = NULL;
124
125 SoapySDR_free(info->units);
126 info->units = NULL;
127
128 //clear options
129 SoapySDRStrings_clear(&info->options, info->numOptions);
130 SoapySDRStrings_clear(&info->optionNames, info->numOptions);
131 info->numOptions = 0;
132 }
133
SoapySDRArgInfoList_clear(SoapySDRArgInfo * info,const size_t length)134 void SoapySDRArgInfoList_clear(SoapySDRArgInfo *info, const size_t length)
135 {
136 for (size_t i = 0; i < length; i++) SoapySDRArgInfo_clear(info+i);
137 SoapySDR_free(info);
138 }
139
140 }
141