static int irange_to_string_convert(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { int r; struct sol_irange in_value; struct string_converter *mdata = data; struct sol_buffer out = SOL_BUFFER_INIT_EMPTY; mdata->node = node; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); r = do_integer_markup(node, mdata->format, in_value, &out); SOL_INT_CHECK_GOTO(r, < 0, end); r = sol_flow_send_string_slice_packet(node, SOL_FLOW_NODE_TYPE_FORMAT_INT_TO_STRING__OUT__OUT, sol_buffer_get_slice(&out)); end: sol_buffer_fini(&out); return r; }
static int operator_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct irange_arithmetic_data *mdata = data; struct sol_irange value; int r; r = sol_flow_packet_get_irange(packet, &value); SOL_INT_CHECK(r, < 0, r); if (port == 0) { if (mdata->var0_initialized && sol_irange_equal(&mdata->var0, &value)) return 0; mdata->var0 = value; mdata->var0_initialized = true; } else { if (mdata->var1_initialized && sol_irange_equal(&mdata->var1, &value)) return 0; mdata->var1 = value; mdata->var1_initialized = true; } if (!(mdata->var0_initialized && mdata->var1_initialized)) return 0; r = mdata->func(&mdata->var0, &mdata->var1, &value); if (r < 0) { sol_flow_send_error_packet(node, -r, sol_util_strerrora(-r)); return r; } return sol_flow_send_irange_packet(node, mdata->port, &value); }
static int irange_map_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct irange_map_data *mdata = data; struct sol_irange in_value; int32_t out_value; int r; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); if (mdata->use_input_range) { if (in_value.min >= in_value.max) { SOL_WRN("Invalid range: input max must to be bigger than min"); return -EINVAL; } r = _map(in_value.val, in_value.min, in_value.max, mdata->output.min, mdata->output.max, mdata->output_value.step, &out_value); } else r = _map(in_value.val, mdata->input.min, mdata->input.max, mdata->output.min, mdata->output.max, mdata->output_value.step, &out_value); SOL_INT_CHECK(r, < 0, r); mdata->output_value.val = out_value; return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_MAP__OUT__OUT, &mdata->output_value); }
int int_validator_process( struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct int_validator_data *mdata = data; struct sol_irange val; int32_t *op; bool match; int r; if (mdata->done) { sol_flow_send_error_packet(node, ECANCELED, "Input stream already deviated from expected data, ignoring packets."); return 0; } r = sol_flow_packet_get_irange(packet, &val); SOL_INT_CHECK(r, < 0, r); op = sol_vector_get(&mdata->values, mdata->next_index); match = val.val == *op; mdata->next_index++; if (mdata->next_index == mdata->values.len || !match) { sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_TEST_INT_VALIDATOR__OUT__OUT, match); mdata->done = true; } return 0; }
static int int_writer_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct unix_socket_data *mdata = data; struct sol_irange val; int r; r = sol_flow_packet_get_irange(packet, &val); SOL_INT_CHECK(r, < 0, r); return unix_socket_write(mdata->un_socket, &val, sizeof(val)); }
static int system_clock_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct sol_irange irange; int r; r = sol_flow_packet_get_irange(packet, &irange); SOL_INT_CHECK(r, < 0, r); r = sol_platform_set_system_clock(irange.val); SOL_INT_CHECK(r, < 0, r); return 0; }
static int logic_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { int r; struct sol_irange in_value; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); r = sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_CUSTOM_NODE_TYPES_LOGIC__IN__IN, in_value.val % 2 == 0); return 0; }
static int timer_interval_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct timer_data *mdata = data; struct sol_irange val; int r; r = sol_flow_packet_get_irange(packet, &val); SOL_INT_CHECK(r, < 0, r); if (mdata->interval == val.val) return 0; mdata->interval = val.val; return start_timer(mdata); }
static int int_writer_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct ipm_data *mdata = data; struct sol_blob *blob; struct sol_irange in_value; int r; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); blob = SOL_BLOB_NEW_DUP(in_value); SOL_NULL_CHECK(blob, -ENOMEM); SEND_BLOB(blob, mdata->id, node); return 0; }
static int int_filter_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct sol_irange value; int r; struct int_filter_data *mdata = data; r = sol_flow_packet_get_irange(packet, &value); SOL_INT_CHECK(r, < 0, r); if (value.val >= mdata->min && value.val <= mdata->max ) { if (mdata->range_override) { value.min = mdata->min; value.max = mdata->max; value.step = 1; } return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_FILTER__OUT__OUT, &value); } return 0; }
static int irange_constrain_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct irange_constrain_data *mdata = data; int r; struct sol_irange value; r = sol_flow_packet_get_irange(packet, &value); SOL_INT_CHECK(r, < 0, r); if (!mdata->use_input_range) { value.min = mdata->val.min; value.max = mdata->val.max; value.step = mdata->val.step; } irange_constrain(&value); mdata->val = value; return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_CONSTRAIN__OUT__OUT, &mdata->val); }
static int not_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { int r; struct sol_irange in_value; struct sol_irange out_value = { .min = INT32_MIN, .step = 1, .max = INT32_MAX }; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); out_value.val = ~in_value.val; return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_BITWISE_NOT__OUT__OUT, &out_value); } // ============================================================================= // IRANGE COMPARISON // ============================================================================= struct irange_comparison_data { bool (*func) (int32_t var0, int32_t var1); int32_t var0; int32_t var1; uint16_t port; bool var0_initialized : 1; bool var1_initialized : 1; }; static bool irange_val_equal(int32_t var0, int32_t var1) { return var0 == var1; } static int equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_comparison_data *mdata = data; mdata->port = SOL_FLOW_NODE_TYPE_INT_EQUAL__OUT__OUT; mdata->func = irange_val_equal; return 0; } static bool irange_val_less(int32_t var0, int32_t var1) { return var0 < var1; } static int less_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_comparison_data *mdata = data; mdata->port = SOL_FLOW_NODE_TYPE_INT_LESS__OUT__OUT; mdata->func = irange_val_less; return 0; } static bool irange_val_less_or_equal(int32_t var0, int32_t var1) { return var0 <= var1; } static int less_or_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_comparison_data *mdata = data; mdata->port = SOL_FLOW_NODE_TYPE_INT_LESS_OR_EQUAL__OUT__OUT; mdata->func = irange_val_less_or_equal; return 0; } static bool irange_val_greater(int32_t var0, int32_t var1) { return var0 > var1; } static int greater_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_comparison_data *mdata = data; mdata->port = SOL_FLOW_NODE_TYPE_INT_GREATER__OUT__OUT; mdata->func = irange_val_greater; return 0; } static bool irange_val_greater_or_equal(int32_t var0, int32_t var1) { return var0 >= var1; } static int greater_or_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_comparison_data *mdata = data; mdata->port = SOL_FLOW_NODE_TYPE_INT_EQUAL__OUT__OUT; mdata->func = irange_val_greater_or_equal; return 0; } static bool irange_val_not_equal(int32_t var0, int32_t var1) { return var0 != var1; } static int not_equal_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_comparison_data *mdata = data; mdata->port = SOL_FLOW_NODE_TYPE_INT_NOT_EQUAL__OUT__OUT; mdata->func = irange_val_not_equal; return 0; } static int comparison_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct irange_comparison_data *mdata = data; int r; struct sol_irange in_value; bool output; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); if (port == 0) { mdata->var0_initialized = true; mdata->var0 = in_value.val; } else if (port == 1) { mdata->var1_initialized = true; mdata->var1 = in_value.val; } /* only send something after both variables values are received */ if (!(mdata->var0_initialized && mdata->var1_initialized)) return 0; output = mdata->func(mdata->var0, mdata->var1); return sol_flow_send_boolean_packet(node, mdata->port, output); } // ============================================================================= // IRANGE MAP // ============================================================================= struct irange_map_data { struct sol_irange input; struct sol_irange output; struct sol_irange output_value; bool use_input_range : 1; }; static int irange_map_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { struct irange_map_data *mdata = data; const struct sol_flow_node_type_int_map_options *opts; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_INT_MAP_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_int_map_options *)options; mdata->use_input_range = opts->use_input_range; mdata->input = opts->input_range; if (!mdata->use_input_range && (mdata->input.min >= mdata->input.max)) { SOL_WRN("Invalid range: input max must to be bigger than min"); return -EINVAL; } mdata->output = opts->output_range; /* We allow output.min > output.max to invert range, but * when sending the packet, min and max must to be in correct * order */ if (mdata->output.min < mdata->output.max) { mdata->output_value.min = mdata->output.min; mdata->output_value.max = mdata->output.max; } else { mdata->output_value.max = mdata->output.min; mdata->output_value.min = mdata->output.max; } if (opts->output_range.step < 1) { SOL_WRN("Output step need to be > 0"); return -EDOM; } mdata->output_value.step = opts->output_range.step; return 0; } static int _map(int64_t in_value, int64_t in_min, int64_t in_max, int64_t out_min, int64_t out_max, int64_t out_step, int32_t *out_value) { int64_t result; if ((in_max - in_min) == out_min) { SOL_WRN("Input max - input min == output min"); return -EDOM; } result = (in_value - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; result -= (result - out_min) % out_step; *out_value = result; return 0; }
static int two_port_process(struct sol_flow_node *node, void *data, uint16_t port_in, uint16_t port_out, const struct sol_flow_packet *packet, int (*func)(int, int)) { struct bitwise_data *mdata = data; int r; struct sol_irange in_value; struct sol_irange out_value = { .min = INT32_MIN, .step = 1, .max = INT32_MAX }; r = sol_flow_packet_get_irange(packet, &in_value); SOL_INT_CHECK(r, < 0, r); if (port_in) { mdata->in1 = in_value.val; mdata->in1_init = true; } else { mdata->in0 = in_value.val; mdata->in0_init = true; } if (!(mdata->in0_init && mdata->in1_init)) return 0; out_value.val = func(mdata->in0, mdata->in1); if (out_value.val == mdata->result && mdata->sent_first) return 0; mdata->result = out_value.val; mdata->sent_first = true; return sol_flow_send_irange_packet(node, port_out, &out_value); } static int and_func(int in0, int in1) { return in0 & in1; } static int and_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_BITWISE_AND__OUT__OUT, packet, and_func); } static int or_func(int in0, int in1) { return in0 | in1; } static int or_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_BITWISE_OR__OUT__OUT, packet, or_func); } static int xor_func(int in0, int in1) { return in0 ^ in1; } static int xor_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_BITWISE_XOR__OUT__OUT, packet, xor_func); } static int validate_shift(const struct sol_flow_packet *packet) { struct sol_irange in; int r; r = sol_flow_packet_get_irange(packet, &in); SOL_INT_CHECK(r, < 0, r); if ((unsigned)in.val > (sizeof(in.val) * CHAR_BIT - 1) || in.val < 0) return -EINVAL; return 0; } static int shift_left_func(int in0, int in1) { return in0 << in1; } static int shift_left_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { int r = 0; if (port == SOL_FLOW_NODE_TYPE_INT_SHIFT_LEFT__IN__SHIFT) r = validate_shift(packet); if (r < 0) return r; return two_port_process(node, data, port, SOL_FLOW_NODE_TYPE_INT_SHIFT_LEFT__OUT__OUT, packet, shift_left_func); }
static void inspector_show_packet_value(const struct sol_flow_packet *packet) { const struct sol_flow_packet_type *type = sol_flow_packet_get_type(packet); if (type == SOL_FLOW_PACKET_TYPE_EMPTY) { fputs("<empty>", stdout); return; } else if (type == SOL_FLOW_PACKET_TYPE_ANY) { fputs("<any>", stdout); return; } else if (type == SOL_FLOW_PACKET_TYPE_ERROR) { int code; const char *msg; if (sol_flow_packet_get_error(packet, &code, &msg) == 0) { fprintf(stdout, "<error:%d \"%s\">", code, msg ? msg : ""); return; } } else if (type == SOL_FLOW_PACKET_TYPE_BOOL) { bool v; if (sol_flow_packet_get_bool(packet, &v) == 0) { fprintf(stdout, "<%s>", v ? "true" : "false"); return; } } else if (type == SOL_FLOW_PACKET_TYPE_BYTE) { unsigned char v; if (sol_flow_packet_get_byte(packet, &v) == 0) { fprintf(stdout, "<%#x>", v); return; } } else if (type == SOL_FLOW_PACKET_TYPE_IRANGE) { struct sol_irange v; if (sol_flow_packet_get_irange(packet, &v) == 0) { fprintf(stdout, "<val:%d|min:%d|max:%d|step:%d>", v.val, v.min, v.max, v.step); return; } } else if (type == SOL_FLOW_PACKET_TYPE_DRANGE) { struct sol_drange v; if (sol_flow_packet_get_drange(packet, &v) == 0) { fprintf(stdout, "<val:%g|min:%g|max:%g|step:%g>", v.val, v.min, v.max, v.step); return; } } else if (type == SOL_FLOW_PACKET_TYPE_STRING) { const char *v; if (sol_flow_packet_get_string(packet, &v) == 0) { fprintf(stdout, "<\"%s\">", v); return; } } else if (type == SOL_FLOW_PACKET_TYPE_BLOB) { struct sol_blob *v; if (sol_flow_packet_get_blob(packet, &v) == 0) { fprintf(stdout, "<mem=%p|size=%zd|refcnt=%hu|type=%p|parent=%p>", v->mem, v->size, v->refcnt, v->type, v->parent); return; } } else if (type == SOL_FLOW_PACKET_TYPE_JSON_OBJECT) { struct sol_blob *v; if (sol_flow_packet_get_json_object(packet, &v) == 0) { fprintf(stdout, "<%.*s>", SOL_STR_SLICE_PRINT(sol_str_slice_from_blob(v))); return; } } else if (type == SOL_FLOW_PACKET_TYPE_JSON_ARRAY) { struct sol_blob *v; if (sol_flow_packet_get_json_array(packet, &v) == 0) { fprintf(stdout, "<%.*s>", SOL_STR_SLICE_PRINT(sol_str_slice_from_blob(v))); return; } } else if (type == SOL_FLOW_PACKET_TYPE_RGB) { struct sol_rgb v; if (sol_flow_packet_get_rgb(packet, &v) == 0) { fprintf(stdout, "<red=%u|green=%u|blue=%u" "|red_max=%u|green_max=%u|blue_max=%u>", v.red, v.green, v.blue, v.red_max, v.green_max, v.blue_max); return; } } else if (type == SOL_FLOW_PACKET_TYPE_DIRECTION_VECTOR) { struct sol_direction_vector v; if (sol_flow_packet_get_direction_vector(packet, &v) == 0) { fprintf(stdout, "<x=%g|y=%g|z=%g|min=%g|max=%g>", v.x, v.y, v.z, v.min, v.max); return; } } else if (type == SOL_FLOW_PACKET_TYPE_LOCATION) { struct sol_location v; if (sol_flow_packet_get_location(packet, &v) == 0) { fprintf(stdout, "<lat=%g|lon=%g|alt=%g>", v.lat, v.lon, v.alt); return; } } else if (type == SOL_FLOW_PACKET_TYPE_TIMESTAMP) { struct timespec v; if (sol_flow_packet_get_timestamp(packet, &v) == 0) { struct tm cur_time; char buf[32]; tzset(); if (gmtime_r(&v.tv_sec, &cur_time)) { if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &cur_time) > 0) { fprintf(stdout, "<%s>", buf); return; } } } } else if (type == SOL_FLOW_PACKET_TYPE_HTTP_RESPONSE) { int code; const char *url, *content_type; const struct sol_blob *content; struct sol_vector headers, cookies; if (sol_flow_packet_get_http_response(packet, &code, &url, &content_type, &content, &cookies, &headers) == 0) { fprintf(stdout, "<response_code:%d|content type:%s|url:%s|", code, content_type, url); fprintf(stdout, "|cookies: {"); inpector_print_key_value_array(&cookies); fprintf(stdout, "}|headers:{"); inpector_print_key_value_array(&headers); fprintf(stdout, "}|content:{mem=%p|size=%zd|refcnt=%hu|type=%p|parent=%p}>", content->mem, content->size, content->refcnt, content->type, content->parent); } return; } fputs("<?>", stdout); }