Add remaining documentation
[libcontrac.git] / src / utils.c
1 /** \ingroup Utils
2 * @file
3 * @author David Llewellyn-Jones <david@flypig.co.uk>
4 * @version $(VERSION)
5 *
6 * @section LICENSE
7 *
8 * Copyright David Llewellyn-Jones, 2020
9 * Released under the GPLv2.
10 *
11 * @brief Static utitlity functions.
12 * @section DESCRIPTION
13 *
14 * Provides various static utitlity functions. In particular:
15 *
16 * base64 encoding and decoding functionality.
17 * Time conversion: from epoch to day numbers and time interval numbers.
18 *
19 */
20
21 /** \addtogroup Utils
22 * @{
23 */
24
25 // Includes
26
27 #include <openssl/evp.h>
28
29 // Defines
30
31 // Structures
32
33 // Function prototypes
34
35 // Function definitions
36
37 // Function definitions
38
39 /**
40 * Returns the amount of space needed to store the base64 equivalent of a binary
41 * input.
42 *
43 * When converting to base64 it's often useful to know how much space will be
44 * needed to store the result, for example so that a buffer of the correct size
45 * can be allocated for it.
46 *
47 * This function returns the size needed for a buffer that will be large enough
48 * to store the result, including a terminating null character. The returned
49 * value may be larger than the size actually needed.
50 *
51 * @param binary_input The length of binary input that would be encoded.
52 * @return The buffer size needed to store the base64 version of the same data.
53 */
54 size_t base64_encode_size(size_t binary_input) {
55 return (((size_t)((binary_input + 2) / 3)) * 4) + 1;
56 }
57
58 /**
59 * Returns the amount of space needed to store the binary equivalent of a base64
60 * string.
61 *
62 * When converting from base64 it's often useful to know how much space will be
63 * needed to store the result, for example so that a buffer of the correct size
64 * can be allocated for it.
65 *
66 * This function returns the size needed for a buffer that will be large enough
67 * to store the result. The returned value may be larger than the size actually
68 * needed.
69 *
70 * @param base64_input The length of a base64 string that would be decoded.
71 * @return The buffer size needed to store the binary version of the same data.
72 */
73 size_t base64_decode_size(size_t base64_input) {
74 return (((size_t)((base64_input + 3) / 4)) * 3) + 1;
75 }
76
77 /**
78 * Encodes binary data to base64 format string.
79 *
80 * Encodes the binary data provided into a base64 string, storing the result
81 * in the output buffer provided. The output buffer must be pre-allocated
82 * with enough space to store the result. The size needed can be found by
83 * calling the \ref base64_encode_size() function.
84 *
85 * If the output buffer is too small (based on the size provided) then the
86 * base64 string may be only partially written.
87 *
88 * @param input The binary data to encode. This doesn't need to be zero
89 * terminated.
90 * @param input_size The size of the input buffer to be converted.
91 * @param output A pre-allocated buffer to store the result.
92 * @param output_size The size of the allocated buffer, which will be updated
93 * to the number of bytes written to the buffer.
94 */
95 void base64_encode_binary_to_base64(unsigned char const *input, size_t input_size, unsigned char *output, size_t *output_size) {
96 size_t size_in;
97 size_t size_out;
98
99 size_in = input_size;
100 size_out = base64_encode_size(input_size);
101
102 if (size_out > *output_size) {
103 size_in = base64_decode_size(*output_size - 1) - 1;
104 }
105 *output_size = base64_encode_size(size_in);
106
107 EVP_EncodeBlock(output, input, size_in);
108 }
109
110 /**
111 * Decodes a base64 string into the original binary data it represents.
112 *
113 * Decodes the base64 string provided into binary, storing the result in the
114 * output buffer provided. The output buffer must be pre-allocated with enough
115 * space to store the result. The size needed can be found by calling the
116 * \ref base64_decode_size() function.
117 *
118 * If the output buffer is too small (based on the size provided) then the
119 * binary output may be only partially written.
120 *
121 * @param input The base64 string to encode. This doesn't need to be zero
122 * terminated.
123 * @param input_size The size of the input buffer to be converted.
124 * @param output A pre-allocated buffer to store the result.
125 * @param output_size The size of the allocated buffer, which will be updated
126 * to the number of bytes written to the buffer.
127 */
128 void base64_decode_base64_to_binary(unsigned char const *input, size_t input_size, unsigned char *output, size_t *output_size) {
129 size_t size_in;
130 size_t size_out;
131
132 size_in = input_size;
133 size_out = base64_decode_size(input_size);
134
135 if (size_out > *output_size) {
136 size_in = base64_encode_size(*output_size - 1) - 1;
137 }
138 *output_size = base64_decode_size(size_in);
139
140 EVP_DecodeBlock(output, input, size_in);
141 }
142
143 /**
144 * Converts a time in epoch format into a day number.
145 *
146 * Returns the day number for the given epoch time. The epoch time represents
147 * the number of seconds since 00:00:00 UTC on 01/01/1970.
148 *
149 * The day number is calculated as:
150 * (Number of Seconds since Epoch) / (60 * 60 * 24)
151 *
152 * @param epoch The epoch time in seconds.
153 * @return The day number for this epoch time.
154 */
155 uint32_t epoch_to_day_number(time_t epoch) {
156 uint32_t day_number;
157
158 // DayNumber <- (Number of Seconds since Epoch) / (60 * 60 * 24)
159 day_number = epoch / (60 * 60 * 24);
160
161 return day_number;
162 }
163
164 /**
165 * Converts a time in epoch format into a time interval number.
166 *
167 * Returns the time interval number for the given epoch time. The epoch time
168 * represents the number of seconds since 00:00:00 UTC on 01/01/1970.
169 *
170 * The time interval number is calculated as:
171 * (Seconds Since Start of DayNumber) / (60 * 10)
172 *
173 * and must fall in the interval [0, 143].
174 *
175 * @param epoch The epoch time in seconds.
176 * @return The time interval number for this epoch time.
177 */
178 uint8_t epoch_to_time_interval_number(time_t epoch) {
179 uint8_t time_interval_number;
180 uint32_t day_number;
181 uint32_t seconds;
182
183 // TimeNumberInterval <- (Seconds Since Start of DayNumber) / (60 * 10)
184 day_number = epoch_to_day_number(epoch);
185 seconds = epoch - (day_number * (60 * 60 * 24));
186
187 time_interval_number = seconds / (60 * 10);
188
189 // Falls in interval [0,143]
190 if (time_interval_number > 143) {
191 time_interval_number = 143;
192 }
193
194 return time_interval_number;
195 }
196
197 /** @} addtogroup Utils */
198