Skip to content

Commit ff9ddbc

Browse files
committed
- Freed all allocs. No more memory leaks.
- Created a simple example.
1 parent 34f1f98 commit ff9ddbc

File tree

5 files changed

+138
-56
lines changed

5 files changed

+138
-56
lines changed

CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ set(CMAKE_C_FLAGS "--std=gnu99" ${CMAKE_C_FLAGS})
1717

1818
option(WITH-TESTS "Compile the test application." OFF)
1919

20+
include_directories(${PROJECT_SOURCE_DIR}/src)
21+
22+
add_executable(example-01 ${CMAKE_SOURCE_DIR}/examples/example_01.c ${CMAKE_SOURCE_DIR}/src/sap.c ${CMAKE_SOURCE_DIR}/src/sap.h)
23+
2024
IF(WITH-TESTS)
2125
add_subdirectory(${PROJECT_SOURCE_DIR}/tests)
2226
endif()

examples/example_01.c

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
#include "sap.h"
3+
4+
5+
static int default_handler(sap_command_list_t* commands, sap_option_list_t* options) {
6+
7+
sap_command_t* cc = commands->first;
8+
while (cc) {
9+
printf("Command %s\n", cc->label);
10+
cc = cc->next;
11+
}
12+
13+
unsigned int curIndex = 0;
14+
sap_option_t* co = sap_get_option_by_index(options, curIndex);
15+
while (co) {
16+
if (co->is_flag) {
17+
printf("flag %s\n", co->label);
18+
} else {
19+
printf("option %s with value %s.\n", co->label, co->value);
20+
}
21+
22+
co = sap_get_option_by_index(options, ++curIndex);
23+
24+
}
25+
26+
}
27+
28+
int main(int argc, char** argv) {
29+
30+
sap_t parser;
31+
32+
sap_init(&parser, argc, argv);
33+
34+
sap_set_default(&parser, default_handler);
35+
36+
int retVal = sap_execute(&parser);
37+
38+
sap_free(&parser);
39+
40+
return retVal;
41+
42+
}

src/sap.c

+83-54
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
int sap_init(sap_t* parser, int argc, char** argv) {
44

5+
56
parser->argc = argc;
67
parser->argv = argv;
78

@@ -10,6 +11,9 @@ int sap_init(sap_t* parser, int argc, char** argv) {
1011

1112
parser->default_command = NULL;
1213

14+
parser->arg_commands = calloc(1, sizeof(sap_command_list_t));
15+
parser->arg_options = calloc(1, sizeof(sap_option_list_t));
16+
1317
parser->error_string = calloc(1, 100);
1418

1519
return 0;
@@ -25,8 +29,6 @@ int sap_add_command(sap_t* parser, char* command, command_handler handler) {
2529
/* go through the command list and look for existing
2630
* commands, return -1 if so. */
2731

28-
29-
3032
sap_command_t* current_command = parser->commands.first;
3133

3234

@@ -146,13 +148,14 @@ static sap_option_t* sap_parse_option(char* arg) {
146148
* and store this string as the options label */
147149

148150
int len = match[1].rm_eo - match[1].rm_so;
149-
char* label = calloc(1, len);
151+
char* label = calloc(1, len + 1);
150152
memcpy(label, arg + match[1].rm_so, len);
151153

152154
sap_option_t* option = calloc(1, sizeof(sap_option_t));
153155
option->label = label;
154156
option->value = NULL;
155157
option->is_flag = 1;
158+
option->next = NULL;
156159

157160
/* if there is no value assigned to the option then we mark
158161
* this option as flag. Meaning this option is enabled.
@@ -164,7 +167,7 @@ static sap_option_t* sap_parse_option(char* arg) {
164167
}
165168

166169
len = match[3].rm_eo - match[3].rm_so;
167-
char* value = calloc(1, len);
170+
char* value = calloc(1, len + 1);
168171
memcpy(value, arg + match[3].rm_so, len);
169172

170173
option->value = value;
@@ -205,34 +208,32 @@ static int sap_is_command(sap_t* parser, char* arg) {
205208

206209
int sap_execute(sap_t* parser) {
207210

208-
sap_command_list_t* commands = calloc(1, sizeof(sap_command_list_t));
209-
sap_option_list_t* options = calloc(1, sizeof(sap_option_list_t));
210-
211211
sap_command_t* command = parser->default_command;
212212

213213
for (unsigned int i = 1; i < parser->argc; i += 1) {
214214

215215
char* command_str = parser->argv[i];
216216

217-
if (sap_is_command(parser, command_str)) {
218-
219-
sap_command_t* new_command = calloc(1, sizeof(sap_command_t));
220-
new_command->label = calloc(1, strlen(command_str) + 1);
221-
strcpy(new_command->label, command_str);
217+
if (!sap_is_command(parser, command_str)) {
218+
continue;
219+
}
222220

223-
if (!commands->first) {
221+
sap_command_t* new_command = calloc(1, sizeof(sap_command_t));
222+
new_command->label = calloc(1, strlen(command_str) + 1);
223+
strcpy(new_command->label, command_str);
224224

225-
commands->first = new_command;
226-
commands->last = new_command;
225+
if (!parser->arg_commands->first) {
227226

228-
} else {
229-
230-
commands->last->next = new_command;
231-
commands->last = new_command;
227+
parser->arg_commands->first = new_command;
228+
parser->arg_commands->last = new_command;
232229

233-
}
230+
} else {
231+
232+
parser->arg_commands->last->next = new_command;
233+
parser->arg_commands->last = new_command;
234234

235235
}
236+
236237
}
237238

238239
for (unsigned int i = 1; i < parser->argc; i += 1) {
@@ -241,33 +242,36 @@ int sap_execute(sap_t* parser) {
241242

242243
/* check if current_string is option */
243244

244-
if (sap_is_option(parser, current_string)) {
245+
if (!sap_is_option(parser, current_string)) {
246+
continue;
247+
}
245248

246-
sap_option_t* option = sap_parse_option(current_string);
249+
sap_option_t* option = sap_parse_option(current_string);
247250

248-
if (!options->first) {
251+
if (!option) {
252+
continue;
253+
}
249254

250-
options->first = option;
251-
options->last = option;
255+
if (!parser->arg_options->first) {
252256

253-
option->next = NULL;
257+
parser->arg_options->first = option;
258+
parser->arg_options->last = option;
254259

255-
} else {
256-
257-
options->last->next = option;
258-
options->last = option;
260+
option->next = NULL;
259261

260-
option->next = NULL;
262+
} else {
263+
264+
parser->arg_options->last->next = option;
265+
parser->arg_options->last = option;
261266

262-
}
267+
option->next = NULL;
263268

264-
}
265-
269+
}
266270
}
267271

268272
/* get command from the parsers commands list */
269273

270-
sap_command_t* first_command = commands->first;
274+
sap_command_t* first_command = parser->arg_commands->first;
271275
sap_command_t* current_command = parser->commands.first;
272276

273277
while (current_command) {
@@ -286,27 +290,30 @@ int sap_execute(sap_t* parser) {
286290

287291
}
288292

293+
int retVal = -1;
289294

290295
if (current_command) {
291296

292-
commands->first = commands->first->next;
293-
294-
int retVal = current_command->handler(commands, options);
297+
sap_command_t* first = parser->arg_commands->first;
298+
parser->arg_commands->first = parser->arg_commands->first->next;
295299

296-
free(commands->first);
300+
retVal = current_command->handler(parser->arg_commands, parser->arg_options);
297301

298-
return retVal;
302+
free(first->label);
303+
free(first);
299304

300305
} else if (parser->default_command) {
301306

302-
return parser->default_command->handler(commands, options);
307+
retVal = parser->default_command->handler(parser->arg_commands, parser->arg_options);
303308

304309
} else {
305310

306-
return -1;
311+
retVal = -1;
307312

308313
}
309314

315+
return retVal;
316+
310317
}
311318

312319
int sap_execute_ex(sap_t* parser, sap_command_list_t* commands, sap_option_list_t* options) {
@@ -332,27 +339,30 @@ int sap_execute_ex(sap_t* parser, sap_command_list_t* commands, sap_option_list_
332339

333340
}
334341

342+
int retVal = -1;
335343

336344
if (current_command && first_command) {
337345

346+
sap_command_t* first = commands->first;
338347
commands->first = commands->first->next;
339348

340-
int retVal = current_command->handler(commands, options);
341-
342-
free(commands->first);
349+
retVal = current_command->handler(commands, options);
343350

344-
return retVal;
351+
free(first->label);
352+
free(first);
345353

346354
} else if (parser->default_command) {
347355

348-
return parser->default_command->handler(commands, options);
356+
retVal = parser->default_command->handler(commands, options);
349357

350358
} else {
351359

352-
return -1;
360+
retVal = 1;
353361

354362
}
355363

364+
return retVal;
365+
356366
}
357367

358368
void sap_free(sap_t* parser) {
@@ -377,6 +387,30 @@ void sap_free(sap_t* parser) {
377387
free(tmp);
378388
}
379389

390+
sap_command_t* cc = parser->arg_commands->first;
391+
392+
while (cc) {
393+
sap_command_t* nc = cc->next;
394+
free(cc->label);
395+
free(cc);
396+
cc = nc;
397+
}
398+
399+
sap_option_t* co = parser->arg_options->first;
400+
while (co) {
401+
sap_option_t* no = co->next;
402+
free(co->label);
403+
if (!co->is_flag) {
404+
free(co->value);
405+
}
406+
free(co);
407+
co = no;
408+
}
409+
410+
free(parser->arg_commands);
411+
free(parser->arg_options);
412+
413+
380414
}
381415

382416
sap_option_t* sap_get_option_by_index(sap_option_list_t* options, unsigned int index) {
@@ -389,7 +423,6 @@ sap_option_t* sap_get_option_by_index(sap_option_list_t* options, unsigned int i
389423

390424
sap_option_t* curOption = options->first;
391425

392-
393426
while (curOption) {
394427

395428
if (counter == index) {
@@ -413,15 +446,11 @@ sap_option_t* sap_get_option_by_key(sap_option_list_t* options, char* key) {
413446

414447
sap_option_t* curOption = options->first;
415448

416-
417-
while (curOption) {
418-
449+
while (curOption) {
419450
if (strcmp(curOption->label, key) == 0) {
420451
return curOption;
421452
}
422-
423453
curOption =curOption->next;
424-
425454
}
426455

427456
return NULL;

src/sap.h

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ struct sap_st {
6464
sap_command_list_t commands;
6565
sap_command_t* default_command;
6666

67+
sap_command_list_t* arg_commands;
68+
sap_option_list_t* arg_options;
69+
6770
int argc;
6871
char** argv;
6972

tests/sap.test.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
int call_count = 0;
55
int return_value = 0;
66

7-
sap_option_list_t* catched_options;
8-
sap_command_list_t* catched_commands;
7+
sap_option_list_t* catched_options = NULL;
8+
sap_command_list_t* catched_commands = NULL;
99

1010
int default_handler(sap_command_list_t* commands, sap_option_list_t* options) {
1111

1212
call_count += 1;
1313

14+
catched_options = options;
15+
catched_commands = commands;
16+
1417
return return_value;
1518

1619
}
@@ -159,6 +162,7 @@ TEST(SAP, ExecuteMatchedHandlerWithOptions) {
159162
sap_option_t* third = sap_get_option_by_index(catched_options, 2);
160163

161164
ASSERT_TRUE(first != NULL);
165+
ASSERT_TRUE(first->label != NULL);
162166
ASSERT_STREQ(first->label, "key");
163167
ASSERT_STREQ(first->value, "value");
164168
ASSERT_EQ(0, first->is_flag);

0 commit comments

Comments
 (0)