static bool check_string(struct sol_json_scanner *scanner, struct sol_json_token *token) { static const char escapable_chars[] = { '"', '\\', '/', 'b', 'f', 'n', 'r', 't', 'u' }; bool escaped = false; token->start = scanner->current; for (scanner->current++; scanner->current < scanner->mem_end; scanner->current++) { char c = scanner->current[0]; if (escaped) { escaped = false; if (!memchr(escapable_chars, c, sizeof(escapable_chars))) { SOL_ERR("%zu: cannot escape %#x (%c)", sol_json_scanner_get_mem_offset(scanner, scanner->current), scanner->current[0], scanner->current[0]); token->start = NULL; errno = EINVAL; return false; } } else if (c == '\\') { escaped = true; } else if (c == '"') { token->end = scanner->current + 1; scanner->current = token->end; return true; } } SOL_ERR("%zu: unfinished string.", sol_json_scanner_get_mem_offset(scanner, scanner->current)); token->start = NULL; errno = EINVAL; return false; }
static void mission_reached_cb(void *data, struct sol_mavlink *mavlink) { int err; enum sol_mavlink_mode mode; struct sol_mavlink_position home; mode = sol_mavlink_get_mode(mavlink); err = sol_mavlink_get_home_position(mavlink, &home); if (err < 0) { SOL_ERR("Could not get home position: %s", sol_util_strerrora(-err)); return; } if (mode != SOL_MAVLINK_MODE_GUIDED) return; err = sol_mavlink_land(mavlink, &home); if (err < 0) { SOL_ERR("Could not land vehicle: %s", sol_util_strerrora(-err)); return; } printf(">>>> Successful takeoff, now landing.\n"); }
static inline const void * sol_mavlink_parse_addr_protocol(const char *str, struct sol_str_slice *addr, int *port) { struct sol_vector tokens; struct sol_str_slice slice = sol_str_slice_from_str(str); const void *init; tokens = sol_str_slice_split(slice, ":", 0); if (tokens.len <= 1) { SOL_ERR("Invalid addr string, it must specify at least <prot>:<addr>"); return NULL; } init = sol_str_table_ptr_lookup_fallback (protocol_table, STR_SLICE_VAL(sol_vector_get(&tokens, 0)), sol_mavlink_init_tcp); if (!init) { SOL_ERR("Invalid protocol"); goto err; } *addr = STR_SLICE_VAL(sol_vector_get(&tokens, 1)); if (tokens.len >= 3) sol_str_slice_to_int(STR_SLICE_VAL(sol_vector_get(&tokens, 2)), port); sol_vector_clear(&tokens); return init; err: sol_vector_clear(&tokens); return NULL; }
static void mavlink_connect_cb(void *data, struct sol_mavlink *mavlink) { int err; enum sol_mavlink_mode mode; SOL_INF("mavlink connection stablished"); mode = sol_mavlink_get_mode(mavlink); if (mode != SOL_MAVLINK_MODE_GUIDED) { err = sol_mavlink_set_mode(mavlink, SOL_MAVLINK_MODE_GUIDED); if (err < 0) { SOL_ERR("Could not set mode: %s", sol_util_strerrora(-err)); } return; } if (!sol_mavlink_check_armed(mavlink)) { err = sol_mavlink_set_armed(mavlink, true); if (err < 0) { SOL_ERR("Could not arm vechicle: %s", sol_util_strerrora(-err)); } return; } takeoff(mavlink); }
static bool check_symbol(struct sol_json_scanner *scanner, struct sol_json_token *token, const char *symname, unsigned symlen) { if (sol_json_scanner_get_size_remaining(scanner) < (size_t)symlen) { SOL_ERR("%zu: premature end of buffer: %zu available, " "need sizeof(%s)=%u", sol_json_scanner_get_mem_offset(scanner, scanner->current), sol_json_scanner_get_size_remaining(scanner), symname, symlen); errno = EINVAL; return false; } if (memcmp(scanner->current, symname, symlen) != 0) { SOL_ERR("%zu: expected token \"%s\", have \"%.*s\"", sol_json_scanner_get_mem_offset(scanner, scanner->current), symname, symlen, scanner->current); errno = EINVAL; return false; } token->start = scanner->current; token->end = scanner->current + symlen; scanner->current = token->end; return true; }
static int sol_mavlink_init_tcp(struct sol_mavlink *mavlink) { struct hostent *server; struct sockaddr_in serveraddr = { 0 }; char *hostname; int err, tcp_flag = 1; mavlink->fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (mavlink->fd == -1) { SOL_ERR("Could not create a socket to specified address - %s", sol_util_strerrora(errno)); return -errno; } hostname = sol_str_slice_to_str(*mavlink->address); if (!hostname) { SOL_ERR("Could not format hostname string - %s", sol_util_strerrora(errno)); goto err; } server = gethostbyname(hostname); if (!server) { SOL_ERR("No such host: %s - (%s)", hostname, sol_util_strerrora(h_errno)); errno = h_errno; goto err; } serveraddr.sin_family = AF_INET; memcpy(server->h_addr, &serveraddr.sin_addr.s_addr, server->h_length); serveraddr.sin_port = htons(mavlink->port); err = setsockopt (mavlink->fd, IPPROTO_TCP, TCP_NODELAY, &tcp_flag, sizeof(int)); if (err < 0) { SOL_ERR("Could not set NODELAY option to tcp socket - (%s)", sol_util_strerrora(errno)); goto sock_err; } err = connect(mavlink->fd, &serveraddr, sizeof(serveraddr)); if (err < 0) { SOL_ERR("Could not stablish connection to: %s:%d - (%s)", hostname, mavlink->port, sol_util_strerrora(errno)); goto sock_err; } free(hostname); return 0; sock_err: free(hostname); err: close(mavlink->fd); return -errno; }
static int wave_generator_sinusoidal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct drange_wave_generator_sinusoidal_data *mdata = data; const struct sol_flow_node_type_wave_generator_sinusoidal_options *opts = (const struct sol_flow_node_type_wave_generator_sinusoidal_options *)options; uint32_t tick_start; struct s_state *s_state; struct sol_drange *val; unsigned i; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(opts, SOL_FLOW_NODE_TYPE_WAVE_GENERATOR_SINUSOIDAL_OPTIONS_API_VERSION, -EINVAL); if (islessequal(opts->amplitude.val, 0)) { SOL_ERR("Sinusoidal wave generator's multiplier must be greater " "than zero"); return -EDOM; } if (opts->ticks_per_period.val < 1) { SOL_ERR("Sinusoidal wave generator's ticks_per_period value (%d) cannot" " be less than 1)", opts->ticks_per_period.val); return -EDOM; } if (opts->tick_start.val < 0) { SOL_ERR("Sinusoidal wave generator's tick_start value (%d) cannot" " be less than 0)", opts->tick_start.val); return -EDOM; } mdata->amplitude = opts->amplitude.val; s_state = &mdata->s_state; val = &s_state->val; s_state->did_first = false; val->min = mdata->amplitude * -1.0; val->max = mdata->amplitude; mdata->rad_step = 2 * M_PI / opts->ticks_per_period.val; /* calculating starting val from tick_start */ val->val = 0; tick_start = opts->tick_start.val % opts->ticks_per_period.val; for (i = 0; i < tick_start; i++) sinusoidal_calc_next(mdata); return 0; }
SOL_API struct sol_mavlink * sol_mavlink_connect(const char *addr, const struct sol_mavlink_config *config, const void *data) { struct sol_mavlink *mavlink; struct sol_str_slice address; int port; int (*init) (struct sol_mavlink *mavlink); SOL_NULL_CHECK(addr, NULL); init = sol_mavlink_parse_addr_protocol(addr, &address, &port); SOL_NULL_CHECK(init, NULL); mavlink = calloc(1, sizeof(*mavlink)); SOL_NULL_CHECK(mavlink, NULL); mavlink->address = &address; SOL_NULL_CHECK_GOTO(mavlink->address, err); mavlink->port = port; SOL_NULL_CHECK_GOTO(mavlink->port, err); mavlink->config = config; mavlink->data = data; memset(&mavlink->curr_position, 0, sizeof(mavlink->curr_position)); memset(&mavlink->home_position, 0, sizeof(mavlink->home_position)); if (init(mavlink) < 0) { SOL_ERR("Could not initialize mavlink connection."); goto err; } mavlink->watch = sol_fd_add(mavlink->fd, SOL_FD_FLAGS_IN, sol_mavlink_fd_handler, mavlink); SOL_NULL_CHECK_GOTO(mavlink->watch, err); if (!setup_data_stream(mavlink)) { SOL_ERR("Could not setup data stream"); goto err; } return mavlink; err: sol_mavlink_free(mavlink); return NULL; }
SOL_API bool sol_json_scanner_get_dict_pair(struct sol_json_scanner *scanner, struct sol_json_token *key, struct sol_json_token *value) { const char *start; if (sol_json_mem_get_type(key->start) != SOL_JSON_TYPE_STRING) { SOL_ERR("offset %zu: unexpected token '%c' (want string)", sol_json_scanner_get_mem_offset(scanner, key->start), key->start[0]); errno = EINVAL; return false; } if (!sol_json_scanner_next(scanner, value)) { SOL_ERR("offset %zu: unexpected end of file (want pair separator)", sol_json_scanner_get_mem_offset(scanner, scanner->current)); errno = EINVAL; return false; } if (sol_json_token_get_type(value) != SOL_JSON_TYPE_PAIR_SEP) { SOL_ERR("offset %zu: unexpected token '%c' (want pair separator)", sol_json_scanner_get_mem_offset(scanner, value->start), value->start[0]); errno = EINVAL; return false; } if (!sol_json_scanner_next(scanner, value)) { SOL_ERR("offset %zu: unexpected end of file (want pair value)", sol_json_scanner_get_mem_offset(scanner, scanner->current)); errno = EINVAL; return false; } start = value->start; if (!sol_json_scanner_skip(scanner, value)) { SOL_ERR("offset %zu: unexpected end of file (want pair value to skip over)", sol_json_scanner_get_mem_offset(scanner, scanner->current)); errno = EINVAL; return false; } value->start = start; return true; }
static void fail(const struct sol_flow_node *node) { mark_done(node); SOL_ERR("test/result node '%s' failed", sol_flow_node_get_id(node)); sol_quit_with_code(EXIT_FAILURE); }
SOL_API bool sol_http_param_add(struct sol_http_params *params, struct sol_http_param_value value) { struct sol_http_param_value *ptr; SOL_NULL_CHECK(params, -EINVAL); #ifndef SOL_NO_API_VERSION if (params->api_version != SOL_HTTP_PARAM_API_VERSION) { SOL_ERR("API version mistmatch; expected %u, got %u", SOL_HTTP_PARAM_API_VERSION, params->api_version); return false; } #endif ptr = sol_vector_append(¶ms->params); if (!ptr) { SOL_WRN("Could not append option to parameter vector"); return false; } memcpy(ptr, &value, sizeof(value)); return true; }
static const char * find_getty_cmd(void) { static const char *cmds[] = { "/usr/bin/agetty", "/usr/sbin/agetty", "/bin/agetty", "/sbin/agetty", "/usr/bin/getty", "/usr/sbin/getty", "/bin/getty", "/sbin/getty", }; const char **itr, **itr_end; itr = cmds; itr_end = itr + ARRAY_SIZE(cmds); for (; itr < itr_end; itr++) { if (access(*itr, R_OK | X_OK) == 0) return *itr; } SOL_ERR("no getty command found"); return NULL; }
int blob_validator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct blob_validator_data *mdata = data; const struct sol_flow_node_type_test_blob_validator_options *opts = (const struct sol_flow_node_type_test_blob_validator_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_BLOB_VALIDATOR_OPTIONS_API_VERSION, -EINVAL); mdata->done = false; if (opts->expected == NULL || *opts->expected == '\0') { SOL_ERR("Option 'expected' is either NULL or empty."); return -EINVAL; } mdata->expected.mem = strdup(opts->expected); SOL_NULL_CHECK(mdata->expected.mem, -errno); mdata->expected.size = strlen(opts->expected); if (opts->expect_terminating_null_byte) mdata->expected.size++; return 0; }
static bool startup(void *data) { bool finished = true; int result = EXIT_FAILURE; the_runner = runner_new(args.filename); if (!the_runner) goto end; if (args.check_only) { printf("file: '%s' - Syntax OK\n", args.filename); result = EXIT_SUCCESS; goto end; } if (runner_run(the_runner) < 0) { SOL_ERR("Failed to run"); goto end; } finished = false; end: if (finished) sol_quit_with_code(result); return false; }
int boolean_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct boolean_generator_data *mdata = data; const struct sol_flow_node_type_test_boolean_generator_options *opts = (const struct sol_flow_node_type_test_boolean_generator_options *)options; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -1; } mdata->it = mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK(mdata->sequence, -errno); if (opts->interval.val < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval.val >= 0 ? opts->interval.val : 0; mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; error: free(mdata->sequence); return -ENOMEM; }
int boolean_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct boolean_generator_data *mdata = data; const struct sol_flow_node_type_test_boolean_generator_options *opts = (const struct sol_flow_node_type_test_boolean_generator_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_BOOLEAN_GENERATOR_OPTIONS_API_VERSION, -EINVAL); if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } mdata->it = mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK(mdata->sequence, -errno); if (opts->interval < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval >= 0 ? opts->interval : 0; mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; error: free(mdata->sequence); return -ENOMEM; }
static bool startup(void *data) { bool finished = true; int result = EXIT_FAILURE; struct sol_ptr_vector *memory_maps; str_arena = sol_arena_new(); if (!str_arena) { fprintf(stderr, "Cannot create str arena\n"); goto end; } if (args.execute_type) { the_runner = runner_new_from_type(args.name, args.options); } else { the_runner = runner_new_from_file(args.name, args.options, &args.fbp_search_paths); } if (!the_runner) goto end; if (args.check_only) { printf("'%s' - Syntax OK\n", args.name); result = EXIT_SUCCESS; goto end; } if (args.provide_sim_nodes) { int err; err = runner_attach_simulation(the_runner); if (err < 0) { fprintf(stderr, "Cannot attach simulation nodes\n"); goto end; } } if (sol_conffile_resolve_memmap(&memory_maps)) { SOL_ERR("Couldn't resolve memory mappings on config file"); goto end; } if (memory_maps) load_memory_maps(memory_maps); if (runner_run(the_runner) < 0) { fprintf(stderr, "Failed to run\n"); goto end; } finished = false; end: if (finished) sol_quit_with_code(result); return false; }
static void mission_reached_cb(void *data, struct sol_mavlink *mavlink) { int err; enum sol_mavlink_mode mode; struct sol_mavlink_position home, curr; struct sol_mavlink_position dest = { DEST_LAT, DEST_LONG, DEST_ALT }; mode = sol_mavlink_get_mode(mavlink); err = sol_mavlink_get_curr_position(mavlink, &curr); if (err < 0) { SOL_ERR("Could not get current position: %s", sol_util_strerrora(-err)); return; } if (mode != SOL_MAVLINK_MODE_GUIDED) return; if (GT_MARGIN(curr.altitude, DEST_ALT)) { printf(">>>> Going back home.\n"); err = sol_mavlink_get_home_position(mavlink, &home); if (err < 0) { SOL_ERR("Could not get home position: %s", sol_util_strerrora(-err)); return; } err = sol_mavlink_land(mavlink, &home); if (err < 0) { SOL_ERR("Could not land vehicle: %s", sol_util_strerrora(-err)); } } else if (GT_MARGIN(curr.altitude, TAKEOFF_ALT)) { err = sol_mavlink_goto(mavlink, &dest); if (err < 0) { SOL_ERR("Could not send vehicle to: (%f, %f, %f) - %s", dest.latitude, dest.longitude, dest.altitude, sol_util_strerrora(-err)); return; } printf(">>>> Successful takeoff, starting a new mission, heading to: " "(%f, %f, %f)\n", dest.latitude, dest.longitude, dest.altitude); } }
int int_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct int_generator_data *mdata = data; const struct sol_flow_node_type_test_int_generator_options *opts = (const struct sol_flow_node_type_test_int_generator_options *)options; const char *it; char *tail; int32_t *val; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } it = opts->sequence; if (opts->interval.val < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval.val >= 0 ? opts->interval.val : 0; mdata->next_index = 0; sol_vector_init(&mdata->values, sizeof(int32_t)); do { val = sol_vector_append(&mdata->values); SOL_NULL_CHECK_GOTO(val, no_memory); errno = 0; *val = strtol(it, &tail, 10); if (errno) { SOL_WRN("Failed do convert option 'sequence' to int %s: %d", it, errno); goto error; } if (it == tail) { SOL_WRN("Failed to convert option 'sequence' to int %s", it); errno = -EINVAL; goto error; } it = tail; } while (*tail != '\0'); mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; no_memory: errno = -ENOMEM; error: sol_vector_clear(&mdata->values); return errno; }
static void on_connect(void *data, struct sol_mqtt *mqtt) { if (sol_mqtt_get_connection_status(mqtt) != SOL_MQTT_CONNECTED) { SOL_WRN("Unable to connect, retrying..."); sol_timeout_add(1000, try_reconnect, mqtt); return; } if (sol_mqtt_subscribe(mqtt, topic, SOL_MQTT_QOS_AT_MOST_ONCE)) SOL_ERR("Unable to subscribe to topic %s", topic); }
int float_validator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct float_validator_data *mdata = data; const struct sol_flow_node_type_test_float_validator_options *opts = (const struct sol_flow_node_type_test_float_validator_options *)options; const char *it; char *tail; double *val; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_FLOAT_VALIDATOR_OPTIONS_API_VERSION, -EINVAL); mdata->done = false; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } sol_vector_init(&mdata->values, sizeof(double)); it = opts->sequence; do { val = sol_vector_append(&mdata->values); SOL_NULL_CHECK_GOTO(val, no_memory); *val = sol_util_strtod_n(it, &tail, -1, false); if (errno) { SOL_WRN("Failed do convert option 'sequence' to double %s: %d", it, errno); goto error; } if (it == tail) { SOL_WRN("Failed to convert option 'sequence' to double %s", it); errno = EINVAL; goto error; } it = tail; } while (*tail != '\0'); return 0; no_memory: errno = ENOMEM; error: sol_vector_clear(&mdata->values); return -errno; }
SOL_API bool sol_json_scanner_next(struct sol_json_scanner *scanner, struct sol_json_token *token) { token->start = NULL; token->end = NULL; for (; scanner->current < scanner->mem_end; scanner->current++) { enum sol_json_type type = sol_json_mem_get_type(scanner->current); switch (type) { case SOL_JSON_TYPE_UNKNOWN: if (!isspace((uint8_t)scanner->current[0])) { SOL_ERR("%zu: unexpected symbol %#x (%c)", sol_json_scanner_get_mem_offset(scanner, scanner->current), scanner->current[0], scanner->current[0]); errno = EINVAL; return false; } break; case SOL_JSON_TYPE_OBJECT_START: case SOL_JSON_TYPE_OBJECT_END: case SOL_JSON_TYPE_ARRAY_START: case SOL_JSON_TYPE_ARRAY_END: case SOL_JSON_TYPE_ELEMENT_SEP: case SOL_JSON_TYPE_PAIR_SEP: token->start = scanner->current; token->end = scanner->current + 1; scanner->current = token->end; return true; case SOL_JSON_TYPE_TRUE: return check_symbol(scanner, token, "true", sizeof("true") - 1); case SOL_JSON_TYPE_FALSE: return check_symbol(scanner, token, "false", sizeof("false") - 1); case SOL_JSON_TYPE_NULL: return check_symbol(scanner, token, "null", sizeof("null") - 1); case SOL_JSON_TYPE_STRING: return check_string(scanner, token); case SOL_JSON_TYPE_NUMBER: return check_number(scanner, token); } } errno = 0; return false; }
static void mode_changed_cb(void *data, struct sol_mavlink *mavlink) { int err; enum sol_mavlink_mode mode = sol_mavlink_get_mode(mavlink); bool armed = sol_mavlink_check_armed(mavlink); if (mode == SOL_MAVLINK_MODE_GUIDED && !armed) { err = sol_mavlink_set_armed(mavlink, true); if (err < 0) { SOL_ERR("Could not arm vechicle: %s", sol_util_strerrora(-err)); } } }
static void takeoff(struct sol_mavlink *mavlink) { int err; struct sol_mavlink_position takeoff = { 0 }; takeoff.altitude = TAKEOFF_ALT; err = sol_mavlink_takeoff(mavlink, &takeoff); if (err < 0) { SOL_ERR("Could not takeoff: %s", sol_util_strerrora(-err)); return; } printf(">>>> Taking off.\n"); }
static void position_changed_cb(void *data, struct sol_mavlink *mavlink) { int err; struct sol_mavlink_position pos; err = sol_mavlink_get_curr_position(mavlink, &pos); if (err < 0) { SOL_ERR("Could not get current position: %s", sol_util_strerrora(-err)); return; } if (sol_mavlink_check_armed(mavlink)) printf("lat: %f, long: %f, alt: %f\n", pos.latitude, pos.longitude, pos.altitude); }
int byte_validator_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct byte_validator_data *mdata = data; const struct sol_flow_node_type_test_byte_validator_options *opts = (const struct sol_flow_node_type_test_byte_validator_options *)options; mdata->done = false; if (opts->sequence == NULL || opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } return _populate_values(data, opts->sequence); }
SOL_API struct sol_gpio * sol_gpio_open(uint32_t pin, const struct sol_gpio_config *config) { struct sol_gpio *gpio; _log_init(); SOL_NULL_CHECK(config, NULL); gpio = sol_gpio_open_raw(pin, config); #ifdef USE_PIN_MUX if (gpio && sol_pin_mux_setup_gpio(pin, config)) { SOL_ERR("Pin Multiplexer Recipe for gpio=%d found, but couldn't be applied.", pin); sol_gpio_close(gpio); gpio = NULL; } #endif return gpio; }
int string_generator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct string_generator_data *mdata = data; const struct sol_flow_node_type_test_string_generator_options *opts = (const struct sol_flow_node_type_test_string_generator_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_TEST_STRING_GENERATOR_OPTIONS_API_VERSION, -EINVAL); sol_vector_init(&mdata->values, sizeof(struct sol_str_slice)); if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK_GOTO(mdata->sequence, no_memory); if (opts->interval < 0) SOL_WRN("Option 'interval' < 0, setting it to 0."); mdata->interval = opts->interval >= 0 ? opts->interval : 0; mdata->next_index = 0; mdata->values = sol_str_slice_split(sol_str_slice_from_str (mdata->sequence), opts->separator, SIZE_MAX); mdata->timer = sol_timeout_add(mdata->interval, timer_tick, node); SOL_NULL_CHECK_GOTO(mdata->timer, error); return 0; no_memory: errno = -ENOMEM; error: sol_vector_clear(&mdata->values); return errno; }
int boolean_validator_open( struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct boolean_validator_data *mdata = data; const struct sol_flow_node_type_test_boolean_validator_options *opts = (const struct sol_flow_node_type_test_boolean_validator_options *)options; mdata->done = false; if (opts->sequence == NULL || *opts->sequence == '\0') { SOL_ERR("Option 'sequence' is either NULL or empty."); return -EINVAL; } mdata->it = mdata->sequence = strdup(opts->sequence); SOL_NULL_CHECK(mdata->sequence, -errno); return 0; }
static bool check_number(struct sol_json_scanner *scanner, struct sol_json_token *token) { const char *frac = NULL; const char *exp = NULL; token->start = scanner->current; for (scanner->current++; scanner->current < scanner->mem_end; scanner->current++) { char c = scanner->current[0]; if (c >= '0' && c <= '9') continue; if (exp) break; if (c == 'e' || c == 'E') { if (scanner->current + 1 < scanner->mem_end) { c = scanner->current[1]; if (c == '-' || c == '+') scanner->current++; } exp = scanner->current; } else if (!frac && c == '.') { frac = scanner->current; } else { break; } } if (frac == scanner->current || exp == scanner->current) { SOL_ERR("%zu: missing trailing digits in number", sol_json_scanner_get_mem_offset(scanner, scanner->current)); token->start = NULL; errno = EINVAL; return false; } token->end = scanner->current; return true; }