Newer
Older
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <inttypes.h>
#include <stdbool.h>
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
DIR *input_dir;
char input_dir_path[PATH_MAX];
FILE *output_stream;
uint8_t nb_threads;
bool verbose;
} args_t;
void usage(char *prog_name)
{
fprintf(stderr, "USAGE:\n");
fprintf(stderr, " %s [OPTIONS] input_dir\n", prog_name);
fprintf(stderr, " input_dir: path to the directory containing the instance files with the encoded messages\n");
fprintf(stderr, " -f output_file: path to the output file containing all decoded messages\n");
fprintf(stderr, " -n n_threads (default: 4): set the number of computing threads that will be used to execute the RLC algorithm\n");
fprintf(stderr, " -v : enable debugging messages. If not set, no such messages will be displayed (except error messages on failure)\n");
}
int parse_args(args_t *args, int argc, char *argv[])
{
memset(args, 0, sizeof(args_t));
// Default values of the arguments
args->nb_threads = 4;
args->verbose = false;
args->output_stream = stdout;
int opt;
while ((opt = getopt(argc, argv, "n:vf:")) != -1)
{
switch (opt)
{
case 'n':
args->nb_threads = atoi(optarg);
if (args->nb_threads == 0)
{
fprintf(stderr, "The number of computing threads must be a positive integer, got: %s\n", optarg);
return -1;
}
break;
case 'v':
args->verbose = true;
break;
case 'f':
args->output_stream = fopen(optarg, "w");
if (args->output_stream == NULL)
{
fprintf(stderr, "Impossible to open the output file %s: %s\n", optarg, strerror(errno));
return -1;
}
break;
case '?':
usage(argv[0]);
return 1;
default:
usage(argv[0]);
}
}
if (optind == argc)
{
fprintf(stderr, "You must provide an input directory containing the instance files!\n");
return -1;
}
// Source: https://stackoverflow.com/questions/11736060/how-to-read-all-files-in-a-folder-using-c
if (NULL == (args->input_dir = opendir(argv[optind])))
{
fprintf(stderr, "Impossible to open the directory containing the input instance files %s: %s\n", argv[optind], strerror(errno));
return -1;
}
// The following line is not very secure... Ask Prof. Legay and/or wait for LINGI2144 for more information :-)
strcpy(args->input_dir_path, argv[optind++]);
return 0;
}
{
args_t args;
int err = parse_args(&args, argc, argv);
if (err == -1)
{
exit(EXIT_FAILURE);
}
else if (err == 1)
{
exit(EXIT_SUCCESS);
}
// The following lines (and every code already present in this skeleton) can be removed, it is just an example to show you how to use the program arguments
fprintf(stderr, "\tnumber of threads executing the RLC decoding algorithm in parallel: %" PRIu32 "\n", args.nb_threads);
fprintf(stderr, "\tverbose mode: %s\n", args.verbose ? "enabled" : "disabled");
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// This is an example of how to open the instance files of the input directory. You may move/edit it during the project
struct dirent *directory_entry;
FILE *input_file;
while ((directory_entry = readdir(args.input_dir)))
{
// Ignore parent and current directory
if (!strcmp(directory_entry->d_name, "."))
{
continue;
}
if (!strcmp(directory_entry->d_name, ".."))
{
continue;
}
// Add the directory path to the filename to open it
char full_path[PATH_MAX];
memset(full_path, 0, sizeof(char) * PATH_MAX);
strcpy(full_path, args.input_dir_path);
strcat(full_path, "/");
strcat(full_path, directory_entry->d_name);
input_file = fopen(full_path, "r");
if (input_file == NULL)
{
fprintf(stderr, "Failed to open the input file %s: %s\n", full_path, strerror(errno));
goto file_read_error;
}
if (args.verbose)
{
// This is a simple example of how to use the verbose mode
fprintf(stderr, "Successfully opened the file %s\n", full_path);
}
// TODO: parse the input binary file, decode the encoded message with RLC and write the output in the output stream following the statement
// You may modify or delete the following lines. This is just an example of how to use tinymt32
uint32_t seed = 42; // Replace with the seed from the instance file!
tinymt32_t prng;
memset(&prng, 0, sizeof(tinymt32_t));
// Do not modify these values!
prng.mat1 = 0x8f7011ee;
prng.mat2 = 0xfc78ff1f;
prng.tmat = 0x3793fdff;
tinymt32_init(&prng, seed);
// You can generate coefficients by calling this function
// Do not forget that we use byte values, so we have to
// cast the uint32_t returned value to only keep the last 8 bits.
uint8_t coef = (uint8_t)tinymt32_generate_uint32(&prng);
if (args.verbose)
{
printf("Coefficient: %u\n", coef);
}
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Close this instance file
fclose(input_file);
}
// Close the input directory and the output file
err = closedir(args.input_dir);
if (err < 0)
{
fprintf(stderr, "Error while closing the input directory containing the instance files\n");
}
if (args.output_stream != stdout)
{
fclose(args.output_stream);
}
return 0;
file_read_error:
err = closedir(args.input_dir);
if (err < 0)
{
fprintf(stderr, "Error while closing the input directory containing the instance files\n");
}
if (args.output_stream != stdout)
{
fclose(args.output_stream);
}
exit(EXIT_FAILURE);
}