firmware  v0.1.2
Chromation Spectrometer Dev-Kit
RecordedArg.c
1 #include "RecordedArg.h"
2 #include <stdlib.h> // malloc, free
3 #include <stdbool.h> // bool, true, false
4 
5 RecordedArg * RecordedArg_new(SetupRecordedArg SetupRecord)
6 {
7  RecordedArg *out = (RecordedArg *)malloc(sizeof(RecordedArg));
8  SetupRecord(out);
9  return out;
10 }
11 void RecordedArg_destroy(RecordedArg *self)
12 { // Deallocate this recorded arg.
13  self->Destroy(self); // Deallocate the memory `pArg` points to.
14  // `Destroy` is assigned to a function specific
15  // to the datatype of this recorded arg.
16  free(self); // Deallocate the RecordedArg struct itself.
17 }
18 
19 //=====[ RecordedArg: type-specific functions assigned by SetupRecord ]=====
20 // The `RecordedArg` struct has *four* elements
21  // - pointer to the heap-mem that stores the argument value
22  // - Free function to dealloacte heap-mem
23  // - Print function to print the value in heap-mem
24  // - Match function to check if the args in two RecordedArg structs match
25  // - CheckArg function to check for equality to the arg value in a RecordedArg struct
26 static FreeArg Destroy_uint8;
27 static FreeArg Destroy_uint16;
28 static FreeArg Destroy_uint32;
29 static FreeArg Destroy_GString;
30 static FreeArg Destroy_p_uint8;
31 static FreeArg Destroy_p_GString;
32 static PrintArgToString Print_uint8;
33 static PrintArgToString Print_uint16;
34 static PrintArgToString Print_uint32;
35 static PrintArgToString Print_GString;
36 static PrintArgToString Print_p_uint8;
37 static PrintArgToString Print_p_GString;
38 static DoArgsMatch Match_uint8;
39 static DoArgsMatch Match_uint16;
40 static DoArgsMatch Match_uint32;
41 static DoArgsMatch Match_GString;
42 static DoArgsMatch Match_p_uint8;
43 static DoArgsMatch Match_p_GString;
44 static CheckArg_t CheckArg_uint8;
45 static CheckArg_t CheckArg_uint16;
46 static CheckArg_t CheckArg_uint32;
47 static CheckArg_t CheckArg_GString;
48 static CheckArg_t CheckArg_p_uint8;
49 static CheckArg_t CheckArg_p_GString;
50 static CheckValArgPointsTo_t CheckValArgPointsTo_p_uint8;
51 /* static CheckValArgPointsTo_t CheckValArgPointsTo_p_GString; */
52 
53 //=====[ RecordedArg: Define SetupRecord for different arg datatypes ]=====
54 // The *four* elements of a RecordedArg struct are defined by the
55 // `SetupRecordedArg_arg_t` functions.
56 void SetupRecord_uint8_t(RecordedArg *self)
57 {
58  self->pArg = malloc(sizeof(uint8_t)); // Get heap-mem.
59  self->Destroy = Destroy_uint8; // How to deallocate.
60  self->Print = Print_uint8; // How to print.
61  self->Match = Match_uint8; // How to check if args match.
62  self->CheckArg = CheckArg_uint8; // How to check if arg equals a value.
63 }
64 void SetupRecord_uint16_t(RecordedArg *self)
65 {
66  self->pArg = malloc(sizeof(uint16_t)); // Get heap-mem.
67  self->Destroy = Destroy_uint16; // How to deallocate.
68  self->Print = Print_uint16; // How to print.
69  self->Match = Match_uint16; // How to check if args match.
70  self->CheckArg = CheckArg_uint16; // How to check if arg equals a value.
71 }
72 void SetupRecord_uint32_t(RecordedArg *self)
73 {
74  self->pArg = malloc(sizeof(uint32_t)); // Get heap-mem.
75  self->Destroy = Destroy_uint32; // How to deallocate.
76  self->Print = Print_uint32; // How to print.
77  self->Match = Match_uint32; // How to check if args match.
78  self->CheckArg = CheckArg_uint32; // How to check if arg equals a value.
79 }
80 void SetupRecord_GString(RecordedArg *self)
81 {
82  self->pArg = malloc(sizeof(GString)); // Get heap-mem.
83  self->Destroy = Destroy_GString; // How to deallocate.
84  self->Print = Print_GString; // How to print.
85  self->Match = Match_GString; // How to check if args match.
86  self->CheckArg = CheckArg_GString; // How to check if arg equals a value.
87 }
88 void SetupRecord_p_uint8_t(RecordedArg *self)
89 {
90  self->pArg = malloc(sizeof(uint8_t *)); // Get heap-mem.
91  self->Destroy = Destroy_p_uint8; // How to deallocate.
92  self->Print = Print_p_uint8; // How to print.
93  self->Match = Match_p_uint8; // How to check if args match.
94  self->CheckArg = CheckArg_p_uint8; // How to check if arg equals a value.
95  self->CheckValArgPointsTo = CheckValArgPointsTo_p_uint8; // How to check if arg equals a value.
96 }
97 void SetupRecord_p_GString(RecordedArg *self)
98 {
99  self->pArg = malloc(sizeof(GString *)); // Get heap-mem.
100  self->Destroy = Destroy_p_GString; // How to deallocate.
101  self->Print = Print_p_GString; // How to print.
102  self->Match = Match_p_GString; // How to check if args match.
103  self->CheckArg = CheckArg_p_GString; // How to check if arg equals a value.
104  /* self->CheckValArgPointsTo = CheckValArgPointsTo_p_GString; // How to check if arg equals a value. */
105 }
106 
107 //=====[ RecordedArg: Define Destroy for different arg datatypes ]=====
108 static void Destroy_uint8(RecordedArg *self)
109 {
110  free((uint8_t *)self->pArg);
111 }
112 static void Destroy_uint16(RecordedArg *self)
113 {
114  free((uint16_t *)self->pArg);
115 }
116 static void Destroy_uint32(RecordedArg *self)
117 {
118  free((uint32_t *)self->pArg);
119 }
120 static void Destroy_GString(RecordedArg *self)
121 {
122  g_string_free((GString *)self->pArg, true);
123 }
124 static void Destroy_p_uint8(RecordedArg *self)
125 {
126  free((uint8_t **)self->pArg);
127 }
128 static void Destroy_p_GString(RecordedArg *self)
129 {
130  free((GString **)self->pArg);
131 }
132 
133 //=====[ RecordedArg: Define Print for different arg datatypes ]=====
134 static void Print_uint8(GString *string, RecordedArg *self)
135 { // Caller provides a temporary string to store the result in.
136  g_string_printf(string, "(uint8_t)%#04x", *(uint8_t *)self->pArg);
137 }
138 static void Print_uint16(GString *string, RecordedArg *self)
139 {
140  g_string_printf(string, "(uint16_t)%#06x", *(uint16_t *)self->pArg);
141  //g_string_printf(string, "%d", *(uint16_t *)self->pArg);
142 }
143 static void Print_uint32(GString *string, RecordedArg *self)
144 {
145  g_string_printf(string, "(uint32_t)%#06x", *(uint32_t *)self->pArg);
146  //g_string_printf(string, "%d", *(uint32_t *)self->pArg);
147 }
148 static void Print_GString(GString *string, RecordedArg *self)
149 {
150  g_string_printf(string, "(GString)%s", ((GString *)self->pArg)->str);
151 }
152 static void Print_p_uint8(GString *string, RecordedArg *self)
153 { // Caller provides a temporary string to store the result in.
154  // TODO: print address or dereferenced value?
155  // This prints the dereferenced value instead of the address.
156  // This may not be what I want to print, but for now it's fine.
157  // I'm just trying to get code to compile and tests to pass.
158  // If I really do need the address, come back and fix later.
159  g_string_printf(string, "(uint8_t)%#04x", **(uint8_t **)self->pArg);
160  // 2019-11-01 there is something very wrong with this print.
161  // I am only getting values 0000 and 0x01, regardles off the actual value
162  // pointed to by the argument.
163 }
164 static void Print_p_GString(GString *string, RecordedArg *self)
165 {
166  g_string_printf(string, "(GString *)%s", (*((GString **)self->pArg))->str);
167 }
168 
169 //=====[ RecordedArg: Define CheckArg for different arg datatypes ]=====
170 // CheckArg is used in unit tests to assert a specific arg in a specific call
171 // is equal to some value.
172 static bool CheckArg_uint8(RecordedArg *argk, void const * arg)
173 {
174  return *((uint8_t *)argk->pArg) == *((uint8_t *)arg);
175 }
176 // TODO: used, but not unit tested
177 static bool CheckArg_uint16(RecordedArg *argk, void const * arg)
178 {
179  return *((uint16_t *)argk->pArg) == *((uint16_t *)arg);
180 }
181 // TODO: unit test:
182 static bool CheckArg_uint32(RecordedArg *argk, void const * arg)
183 {
184  return *((uint32_t *)argk->pArg) == *((uint32_t *)arg);
185 }
186 // TODO: unit test:
187 static bool CheckArg_GString(RecordedArg *argk, void const * arg)
188 {
189  int strings_do_not_match = g_strcmp0(
190  ((GString *)argk->pArg)->str,
191  ((GString *)arg)->str
192  );
193  return strings_do_not_match ? false : true;
194 }
195 // TODO: unit test:
196 static bool CheckArg_p_uint8(RecordedArg *argk, void const * arg)
197 {
198  return *((uint8_t **)argk->pArg) == *((uint8_t **)arg);
199 }
200 // TODO: unit test:
201 static bool CheckValArgPointsTo_p_uint8(RecordedArg *argk, void const * arg)
202 {
203  return **((uint8_t **)argk->pArg) == **((uint8_t **)arg);
204 }
205 // TODO: unit test:
206 static bool CheckArg_p_GString(RecordedArg *argk, void const * arg)
207 {
208  // Compare the strings ultimately being pointed to
209  int strings_do_not_match = g_strcmp0(
210  (*((GString **)argk->pArg))->str,
211  (*((GString **)arg))->str
212  );
213  return strings_do_not_match ? false : true;
214 }
215 
216 //=====[ RecordedArg: Define Match for different arg datatypes ]=====
217 // Match is used in `Mock.c to define RecordedArgsMatch()`:
218  // static bool RecordedArgsMatch(RecordedArg *expected_arg, RecordedArg *actual_arg)
219  // {
220  // if (expected_arg->Match != actual_arg->Match) return false;
221  // return expected_arg->Match(expected_arg, actual_arg);
222  // }
223 // Compare `pRec_s->Match` to see if args have same datatype.
224 // Call `pRec_s->Match(pRec1,pRec2)` returns true if args have same value.
225 static bool Match_uint8(RecordedArg *arg1, RecordedArg *arg2)
226 {
227  return *((uint8_t *)arg1->pArg) == *((uint8_t *)arg2->pArg);
228 }
229 static bool Match_uint16(RecordedArg *arg1, RecordedArg *arg2)
230 {
231  return *((uint16_t *)arg1->pArg) == *((uint16_t *)arg2->pArg);
232 }
233 static bool Match_uint32(RecordedArg *arg1, RecordedArg *arg2)
234 {
235  return *((uint32_t *)arg1->pArg) == *((uint32_t *)arg2->pArg);
236 }
237 static bool Match_GString(RecordedArg *arg1, RecordedArg *arg2)
238 {
239  int strings_do_not_match = g_strcmp0(
240  ((GString *)arg1->pArg)->str,
241  ((GString *)arg2->pArg)->str
242  );
243  return strings_do_not_match ? false : true;
244 }
245 static bool Match_p_uint8(RecordedArg *arg1, RecordedArg *arg2)
246 {
247  /* TODO: match address or dereferenced value? */
248  /* Both pass the test. But I want to compare the address. */
249  /* Compare the addresses: */
250  return *((uint8_t **)arg1->pArg) == *((uint8_t **)arg2->pArg);
251  /* Compare the dereferenced values: */
252  //return **((uint8_t **)arg1->pArg) == **((uint8_t **)arg2->pArg);
253  /* This does not pass the test. */
254  /* It compares the pArgs. The pArgs are different. */
255  //return (uint8_t **)arg1->pArg == (uint8_t **)arg2->pArg;
256 }
257 static bool Match_p_GString(RecordedArg *arg1, RecordedArg *arg2)
258 {
259  // Compare the strings ultimately being pointed to
260  int strings_do_not_match = g_strcmp0(
261  (*((GString **)arg1->pArg))->str,
262  (*((GString **)arg2->pArg))->str);
263  return strings_do_not_match ? false : true;
264 }