libamxp  1.4.0
Patterns C Implementation
amxp_cron_parser.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <amxc/amxc.h>
#include <amxp/amxp_cron.h>
#include <amxc/amxc_macros.h>
#include "amxp_cron_parser_priv.h"

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 
#define CRON_MONTHS_ARR_LEN   13
 
#define CRON_DAYS_ARR_LEN   7
 

Functions

static void cron_set_bit (uint8_t *rbyte, int idx)
 
static void cron_del_bit (uint8_t *rbyte, int idx)
 
static bool has_char (const char *str, char ch)
 
static uint32_t parse_uint (const char *str, bool *invalid)
 
static void replace_ordinals (amxc_string_t *value, const char *const *arr, uint32_t arr_len)
 
static int split_string (amxc_llist_t *parts, char *str, const char sep, uint32_t expected_len)
 
static uint32_t * get_range (char *field, 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)
 
uint8_t cron_get_bit (const uint8_t *rbyte, int idx)
 
int amxp_cron_reset (amxp_cron_expr_t *cron_expr)
 
int amxp_cron_set_hits (amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
 
int amxp_cron_set_months (amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
 
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_days_of_month (amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)
 

Variables

static const char *const MONTHS_ARR []
 
static const char *const DAYS_ARR []
 
static const char *const DAYS_ARR_FULL []
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 56 of file amxp_cron_parser.c.

◆ CRON_DAYS_ARR_LEN

#define CRON_DAYS_ARR_LEN   7

Definition at line 88 of file amxp_cron_parser.c.

◆ CRON_MONTHS_ARR_LEN

#define CRON_MONTHS_ARR_LEN   13

Definition at line 87 of file amxp_cron_parser.c.

Function Documentation

◆ amxp_cron_reset()

int amxp_cron_reset ( amxp_cron_expr_t cron_expr)

Definition at line 285 of file amxp_cron_parser.c.

285  {
286  int retval = -1;
287  when_null(cron_expr, exit);
288  memset(cron_expr, 0, sizeof(amxp_cron_expr_t));
289 
290 exit:
291  return retval;
292 }
Structure containing parsed cron expression.
Definition: amxp_cron.h:103

◆ amxp_cron_set_days_of_month()

int amxp_cron_set_days_of_month ( amxc_var_t *  value,
uint8_t *  target,
uint32_t  min,
uint32_t  max,
const char **  error 
)

Definition at line 404 of file amxp_cron_parser.c.

408  {
409  const char* field = GET_CHAR(value, NULL);
410 
411  if((strlen(field) == 1) && (field[0] == '?')) {
412  amxc_var_set(cstring_t, value, "*");
413  }
414 
415  return amxp_cron_set_hits(value, target, min, max, error);
416 }
int amxp_cron_set_hits(amxc_var_t *value, uint8_t *target, uint32_t min, uint32_t max, const char **error)

◆ amxp_cron_set_days_of_week()

int amxp_cron_set_days_of_week ( amxc_var_t *  value,
uint8_t *  target,
uint32_t  min,
uint32_t  max,
const char **  error 
)

Definition at line 370 of file amxp_cron_parser.c.

374  {
375  int rv = -1;
376  amxc_string_t str_value;
377  char* v = amxc_var_take(cstring_t, value);
378 
379  amxc_string_init(&str_value, 0);
380 
381  amxc_string_push_buffer(&str_value, v, strlen(v) + 1);
382  amxc_string_to_upper(&str_value);
383 
384  if((amxc_string_text_length(&str_value) == 1) && (str_value.buffer[0] == '?')) {
385  str_value.buffer[0] = '*';
386  }
387 
390  amxc_var_set(cstring_t, value, amxc_string_get(&str_value, 0));
391 
392  rv = amxp_cron_set_hits(value, target, min, max, error);
393 
394  if(cron_get_bit(target, 7)) {
395  // Sunday can be represented as 0 or 7
396  cron_set_bit(target, 0);
397  cron_del_bit(target, 7);
398  }
399 
400  amxc_string_clean(&str_value);
401  return rv;
402 }
#define CRON_DAYS_ARR_LEN
static const char *const DAYS_ARR[]
static void cron_del_bit(uint8_t *rbyte, int idx)
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)
uint8_t cron_get_bit(const uint8_t *rbyte, int idx)
static const char *const DAYS_ARR_FULL[]

◆ amxp_cron_set_hits()

int amxp_cron_set_hits ( amxc_var_t *  value,
uint8_t *  target,
uint32_t  min,
uint32_t  max,
const char **  error 
)

Definition at line 294 of file amxp_cron_parser.c.

298  {
299  amxc_var_t fields;
300  uint32_t delta = 1;
301  uint32_t* range = NULL;
302  char* field_expr = NULL;
303  int rv = -1;
304 
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);
308 
309  amxc_var_for_each(field, &fields) {
310  field_expr = amxc_var_take(cstring_t, field);
311  if(!has_char(field_expr, '/')) {
312  range = get_range(field_expr, min, max, error);
313  when_null(range, exit);
314  when_not_null_status(*error, exit, free(range));
315  } else {
316  range = get_range_increment(field_expr, min, max, &delta, error);
317  when_null(range, exit);
318  when_not_null_status(*error, exit, free(range));
319  if(delta == 0) {
320  *error = "Incrementer may not be zero";
321  free(range);
322  goto exit;
323  }
324  }
325 
326  for(size_t i = range[0]; i <= range[1]; i += delta) {
327  cron_set_bit(target, i);
328  }
329  free(range);
330  free(field_expr);
331  field_expr = NULL;
332  }
333 
334  rv = 0;
335 
336 exit:
337  free(field_expr);
338  amxc_var_clean(&fields);
339  return rv;
340 }
static uint32_t * get_range_increment(char *field, uint32_t min, uint32_t max, uint32_t *increment, const char **error)
static bool has_char(const char *str, char ch)
static uint32_t * get_range(char *field, uint32_t min, uint32_t max, const char **error)

◆ amxp_cron_set_months()

int amxp_cron_set_months ( amxc_var_t *  value,
uint8_t *  target,
uint32_t  min,
uint32_t  max,
const char **  error 
)

Definition at line 342 of file amxp_cron_parser.c.

346  {
347  int rv = -1;
348  amxc_string_t str_value;
349  char* v = amxc_var_take(cstring_t, value);
350  amxc_string_init(&str_value, 0);
351 
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));
356  rv = amxp_cron_set_hits(value, target, min, max, error);
357 
358  /* ... and then rotate it to the front of the months */
359  for(uint32_t i = 1; i <= max; i++) {
360  if(cron_get_bit(target, i)) {
361  cron_set_bit(target, i - 1);
362  cron_del_bit(target, i);
363  }
364  }
365 
366  amxc_string_clean(&str_value);
367  return rv;
368 }
static const char *const MONTHS_ARR[]
#define CRON_MONTHS_ARR_LEN

◆ cron_del_bit()

static void cron_del_bit ( uint8_t *  rbyte,
int  idx 
)
static

Definition at line 97 of file amxp_cron_parser.c.

97  {
98  uint8_t j = (uint8_t) (idx / 8);
99  uint8_t k = (uint8_t) (idx % 8);
100 
101  rbyte[j] &= ~(1 << k);
102 }

◆ cron_get_bit()

uint8_t cron_get_bit ( const uint8_t *  rbyte,
int  idx 
)

Definition at line 274 of file amxp_cron_parser.c.

274  {
275  uint8_t j = (uint8_t) (idx / 8);
276  uint8_t k = (uint8_t) (idx % 8);
277 
278  if(rbyte[j] & (1 << k)) {
279  return 1;
280  } else {
281  return 0;
282  }
283 }

◆ cron_set_bit()

static void cron_set_bit ( uint8_t *  rbyte,
int  idx 
)
static

Definition at line 90 of file amxp_cron_parser.c.

90  {
91  uint8_t j = (uint8_t) (idx / 8);
92  uint8_t k = (uint8_t) (idx % 8);
93 
94  rbyte[j] |= (1 << k);
95 }

◆ get_range()

static uint32_t* get_range ( char *  field,
uint32_t  min,
uint32_t  max,
const char **  error 
)
static

Definition at line 183 of file amxp_cron_parser.c.

186  {
187  size_t len = 0;
188  uint32_t* res = (uint32_t*) calloc(2, sizeof(uint32_t));
189  bool invalid = true;
190 
191  when_null(res, exit);
192 
193  if((strlen(field) == 1) && (field[0] == '*')) {
194  res[0] = min;
195  res[1] = max - 1;
196  } else if(!has_char(field, '-')) {
197  uint32_t val = parse_uint(field, &invalid);
198  when_true_status(invalid, exit, *error = "Invalid value (1)");
199  res[0] = val;
200  res[1] = val;
201  } else {
202  amxc_llist_t parts;
203  amxc_llist_init(&parts);
204  when_failed_status(split_string(&parts, field, '-', 2), exit, *error = "Specified range requires two fields");
205  len = 0;
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);
210  if(invalid) {
211  *error = "Invalid value (2)";
212  break;
213  }
214  len++;
215  }
216  amxc_llist_clean(&parts, amxc_string_list_it_free);
217  when_true(invalid, exit);
218  }
219 
220  invalid = true;
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");
224 
225  invalid = false;
226  *error = NULL;
227 
228 exit:
229  if(invalid && (res != NULL)) {
230  free(res);
231  res = NULL;
232  }
233 
234  return res;
235 }
static int split_string(amxc_llist_t *parts, char *str, const char sep, uint32_t expected_len)
static uint32_t parse_uint(const char *str, bool *invalid)

◆ get_range_increment()

static uint32_t* get_range_increment ( char *  field,
uint32_t  min,
uint32_t  max,
uint32_t *  increment,
const char **  error 
)
static

Definition at line 237 of file amxp_cron_parser.c.

241  {
242  amxc_llist_it_t* it = NULL;
243  amxc_string_t* strpart = NULL;
244  amxc_llist_t parts;
245  bool invalid = true;
246  uint32_t* range = NULL;
247 
248  amxc_llist_init(&parts);
249  when_failed_status(split_string(&parts, field, '/', 2), exit, *error = "Incrementer must have two fields");
250 
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);
255  if(*error != NULL) {
256  free(range);
257  range = NULL;
258  goto exit;
259  }
260  if(!has_char(amxc_string_get(strpart, 0), '-')) {
261  range[1] = max - 1;
262  }
263 
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)");
268 
269 exit:
270  amxc_llist_clean(&parts, amxc_string_list_it_free);
271  return range;
272 }

◆ has_char()

static bool has_char ( const char *  str,
char  ch 
)
static

Definition at line 104 of file amxp_cron_parser.c.

104  {
105  size_t i = 0;
106  size_t len = 0;
107  bool rv = false;
108 
109  len = strlen(str);
110 
111  for(i = 0; i < len; i++) {
112  if(str[i] == ch) {
113  rv = true;
114  break;
115  }
116  }
117 
118  return rv;
119 }

◆ parse_uint()

static uint32_t parse_uint ( const char *  str,
bool *  invalid 
)
static

Definition at line 121 of file amxp_cron_parser.c.

121  {
122  char* endptr = NULL;
123  int64_t value = 0;
124 
125  errno = 0;
126  *invalid = false;
127  if(str[0] == 0) {
128  *invalid = true;
129  } else {
130  value = strtol(str, &endptr, 10);
131  if((errno == ERANGE) || (*endptr != '\0') || (value < 0) || (value > INT32_MAX)) {
132  *invalid = true;
133  value = 0;
134  } else {
135  *invalid = false;
136  }
137  }
138  return (uint32_t) value;
139 }

◆ replace_ordinals()

static void replace_ordinals ( amxc_string_t *  value,
const char *const *  arr,
uint32_t  arr_len 
)
static

Definition at line 141 of file amxp_cron_parser.c.

143  {
144  char* cur = NULL;
145  amxc_var_t num;
146  amxc_var_init(&num);
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);
151  free(cur);
152  }
153  amxc_var_clean(&num);
154 }

◆ split_string()

static int split_string ( amxc_llist_t *  parts,
char *  str,
const char  sep,
uint32_t  expected_len 
)
static

Definition at line 156 of file amxp_cron_parser.c.

159  {
160  uint32_t len = 0;
161  int rv = -1;
162  amxc_string_t strfield;
163  amxc_string_init(&strfield, 0);
164 
165  amxc_string_push_buffer(&strfield, str, strlen(str) + 1);
166  amxc_string_split_to_llist(&strfield, parts, sep);
167 
168  len = amxc_llist_size(parts);
169  when_false(len == expected_len, exit);
170 
171  rv = 0;
172 
173 exit:
174  if(rv != 0) {
175  amxc_llist_clean(parts, amxc_string_list_it_free);
176  }
177 
178  amxc_string_take_buffer(&strfield);
179  amxc_string_clean(&strfield);
180  return rv;
181 }

Variable Documentation

◆ DAYS_ARR

const char* const DAYS_ARR[]
static
Initial value:
= {
"SUN", "MON", "TUE", "WED",
"THU", "FRI", "SAT"
}

Definition at line 77 of file amxp_cron_parser.c.

◆ DAYS_ARR_FULL

const char* const DAYS_ARR_FULL[]
static
Initial value:
= {
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
"THURSDAY", "FRIDAY", "SATURDAY"
}

Definition at line 82 of file amxp_cron_parser.c.

◆ MONTHS_ARR

const char* const MONTHS_ARR[]
static
Initial value:
= {
"FOO", "JAN", "FEB", "MAR", "APR",
"MAY", "JUN", "JUL", "AUG", "SEP",
"OCT", "NOV", "DEC"
}

Definition at line 71 of file amxp_cron_parser.c.