65 #include <amxc/amxc.h>
67 #include <amxc/amxc_macros.h>
72 "FOO",
"JAN",
"FEB",
"MAR",
"APR",
73 "MAY",
"JUN",
"JUL",
"AUG",
"SEP",
78 "SUN",
"MON",
"TUE",
"WED",
83 "SUNDAY",
"MONDAY",
"TUESDAY",
"WEDNESDAY",
84 "THURSDAY",
"FRIDAY",
"SATURDAY"
87 #define CRON_MONTHS_ARR_LEN 13
88 #define CRON_DAYS_ARR_LEN 7
91 uint8_t j = (uint8_t) (idx / 8);
92 uint8_t k = (uint8_t) (idx % 8);
98 uint8_t j = (uint8_t) (idx / 8);
99 uint8_t k = (uint8_t) (idx % 8);
101 rbyte[j] &= ~(1 << k);
111 for(i = 0; i < len; i++) {
130 value = strtol(str, &endptr, 10);
131 if((errno == ERANGE) || (*endptr !=
'\0') || (value < 0) || (value > INT32_MAX)) {
138 return (uint32_t) value;
142 const char*
const* arr,
147 for(uint32_t i = 0; i < arr_len; i++) {
148 amxc_var_set(uint32_t, &num, i);
149 cur = amxc_var_dyncast(cstring_t, &num);
150 amxc_string_replace(value, arr[i], cur, UINT32_MAX);
153 amxc_var_clean(&num);
159 uint32_t expected_len) {
162 amxc_string_t strfield;
163 amxc_string_init(&strfield, 0);
165 amxc_string_push_buffer(&strfield, str, strlen(str) + 1);
166 amxc_string_split_to_llist(&strfield, parts, sep);
168 len = amxc_llist_size(parts);
169 when_false(len == expected_len, exit);
175 amxc_llist_clean(parts, amxc_string_list_it_free);
178 amxc_string_take_buffer(&strfield);
179 amxc_string_clean(&strfield);
186 const char** error) {
188 uint32_t* res = (uint32_t*) calloc(2,
sizeof(uint32_t));
191 when_null(res, exit);
193 if((strlen(field) == 1) && (field[0] ==
'*')) {
198 when_true_status(invalid, exit, *error =
"Invalid value (1)");
203 amxc_llist_init(&parts);
204 when_failed_status(
split_string(&parts, field,
'-', 2), exit, *error =
"Specified range requires two fields");
206 amxc_llist_for_each(it, &parts) {
207 amxc_string_t* strpart = amxc_string_from_llist_it(it);
208 amxc_string_trim(strpart, NULL);
209 res[len] =
parse_uint(amxc_string_get(strpart, 0), &invalid);
211 *error =
"Invalid value (2)";
216 amxc_llist_clean(&parts, amxc_string_list_it_free);
217 when_true(invalid, exit);
221 when_true_status(res[0] >= max || res[1] >= max, exit, *error =
"Specified range exceeds maximum");
222 when_true_status(res[0] < min || res[1] < min, exit, *error =
"Specified range is less than minimum");
223 when_true_status(res[0] > res[1], exit, *error =
"Specified range start exceeds range end");
229 if(invalid && (res != NULL)) {
241 const char** error) {
242 amxc_llist_it_t* it = NULL;
243 amxc_string_t* strpart = NULL;
246 uint32_t* range = NULL;
248 amxc_llist_init(&parts);
249 when_failed_status(
split_string(&parts, field,
'/', 2), exit, *error =
"Incrementer must have two fields");
251 it = amxc_llist_get_first(&parts);
252 strpart = amxc_string_from_llist_it(it);
253 range =
get_range(strpart->buffer, min, max, error);
254 when_null(range, exit);
260 if(!
has_char(amxc_string_get(strpart, 0),
'-')) {
264 it = amxc_llist_it_get_next(it);
265 strpart = amxc_string_from_llist_it(it);
266 *increment =
parse_uint(amxc_string_get(strpart, 0), &invalid);
267 when_true_status(invalid, exit, *error =
"Invalid value (3)");
270 amxc_llist_clean(&parts, amxc_string_list_it_free);
275 uint8_t j = (uint8_t) (idx / 8);
276 uint8_t k = (uint8_t) (idx % 8);
278 if(rbyte[j] & (1 << k)) {
287 when_null(cron_expr, exit);
298 const char** error) {
301 uint32_t* range = NULL;
302 char* field_expr = NULL;
305 amxc_var_init(&fields);
306 amxc_var_set(csv_string_t, &fields, GET_CHAR(value, NULL));
307 amxc_var_cast(&fields, AMXC_VAR_ID_LIST);
309 amxc_var_for_each(field, &fields) {
310 field_expr = amxc_var_take(cstring_t, field);
312 range =
get_range(field_expr, min, max, error);
313 when_null(range, exit);
314 when_not_null_status(*error, exit, free(range));
317 when_null(range, exit);
318 when_not_null_status(*error, exit, free(range));
320 *error =
"Incrementer may not be zero";
326 for(
size_t i = range[0]; i <= range[1]; i += delta) {
338 amxc_var_clean(&fields);
346 const char** error) {
348 amxc_string_t str_value;
349 char* v = amxc_var_take(cstring_t, value);
350 amxc_string_init(&str_value, 0);
352 amxc_string_push_buffer(&str_value, v, strlen(v) + 1);
353 amxc_string_to_upper(&str_value);
355 amxc_var_set(cstring_t, value, amxc_string_get(&str_value, 0));
359 for(uint32_t i = 1; i <= max; i++) {
366 amxc_string_clean(&str_value);
374 const char** error) {
376 amxc_string_t str_value;
377 char* v = amxc_var_take(cstring_t, value);
379 amxc_string_init(&str_value, 0);
381 amxc_string_push_buffer(&str_value, v, strlen(v) + 1);
382 amxc_string_to_upper(&str_value);
384 if((amxc_string_text_length(&str_value) == 1) && (str_value.buffer[0] ==
'?')) {
385 str_value.buffer[0] =
'*';
390 amxc_var_set(cstring_t, value, amxc_string_get(&str_value, 0));
400 amxc_string_clean(&str_value);
408 const char** error) {
409 const char* field = GET_CHAR(value, NULL);
411 if((strlen(field) == 1) && (field[0] ==
'?')) {
412 amxc_var_set(cstring_t, value,
"*");
Ambiorix cron expression parser.
#define CRON_DAYS_ARR_LEN
static const char *const DAYS_ARR[]
int amxp_cron_set_months(amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
static uint32_t * get_range_increment(char *field, uint32_t min, uint32_t max, uint32_t *increment, const char **error)
static void cron_del_bit(uint8_t *rbyte, int idx)
int amxp_cron_set_days_of_week(amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
int amxp_cron_set_hits(amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
static bool has_char(const char *str, char ch)
static void cron_set_bit(uint8_t *rbyte, int idx)
static void replace_ordinals(amxc_string_t *value, const char *const *arr, uint32_t arr_len)
int amxp_cron_reset(amxp_cron_expr_t *cron_expr)
static int split_string(amxc_llist_t *parts, char *str, const char sep, uint32_t expected_len)
uint8_t cron_get_bit(const uint8_t *rbyte, int idx)
static uint32_t parse_uint(const char *str, bool *invalid)
static const char *const MONTHS_ARR[]
int amxp_cron_set_days_of_month(amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
static const char *const DAYS_ARR_FULL[]
#define CRON_MONTHS_ARR_LEN
static uint32_t * get_range(char *field, uint32_t min, uint32_t max, const char **error)
Structure containing parsed cron expression.