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 void read_cb(void *cb_data, struct sol_aio *aio, int32_t ret) { struct sol_irange i; struct aio_data *mdata = cb_data; SOL_NULL_CHECK(mdata); i.val = ret; if (i.val < 0) { sol_flow_send_error_packet(mdata->node, EINVAL, "AIO (%s): Failed on read operation: %s.", mdata->pin, sol_util_strerrora(i.val)); return; } if (mdata->is_first || i.val != mdata->last_value) { mdata->is_first = false; mdata->last_value = i.val; i.max = mdata->mask; i.min = 0; i.step = 1; sol_flow_send_irange_packet(mdata->node, SOL_FLOW_NODE_TYPE_AIO_READER__OUT__OUT, &i); } mdata->pending = NULL; }
static int common_get_progress(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct update_data *mdata = data; struct update_node_type *type; struct sol_irange irange = { .step = 1, .min = 0, .max = 100 }; type = (struct update_node_type *)sol_flow_node_get_type(node); if (mdata->handle) { irange.val = sol_update_get_progress(mdata->handle); if (irange.val >= 0 && irange.val <= 100) sol_flow_send_irange_packet(node, type->progress_port, &irange); else sol_flow_send_error_packet(node, EINVAL, "Could not get progress of task"); } else { SOL_DBG("No current operation in process, ignoring request to get progress"); } return 0; }
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); }
static void int_receiver(void *data, uint32_t id, struct sol_blob *message) { struct sol_flow_node *node = data; sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_IPM_INT_READER__OUT__OUT, message->mem); sol_blob_unref(message); }
static int reset_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct accumulator_data *mdata = data; mdata->val.val = mdata->init_val; return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OUT, &mdata->val); }
/* *----------------------- int -------------------------- */ static void int_read_data(void *data, int fd) { struct unix_socket_data *mdata = data; struct sol_irange val; if (FILL_BUFFER(fd, val) < 0) return; sol_flow_send_irange_packet(mdata->node, SOL_FLOW_NODE_TYPE_UNIX_SOCKET_INT_READER__OUT__OUT, &val); }
/* * WARNING: Do NOT use it for anything else than test purposes. */ static int random_int_generate(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct sol_irange value = { 0, 0, INT32_MAX, 1 }; struct random_node_data *mdata = data; int r; r = sol_random_get_int32(mdata->engine, &value.val); if (r < 0) return r; return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_RANDOM_INT__OUT__OUT, &value); }
static int counter_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct sol_irange val = { 0, 0, INT32_MAX, 1 }; struct counter_data *mdata = data; enum state *s; bool packet_val; int r; r = sol_flow_packet_get_boolean(packet, &packet_val); SOL_INT_CHECK(r, < 0, r); s = sol_vector_get(&mdata->map, conn_id); if (*s == packet_val) return 0; if (packet_val) { mdata->true_count++; if (*s != NA) mdata->false_count--; } else { mdata->false_count++; if (*s != NA) mdata->true_count--; } *s = packet_val; val.val = mdata->true_count; sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_BOOLEAN_COUNTER__OUT__TRUE, &val); val.val = mdata->false_count; sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_BOOLEAN_COUNTER__OUT__FALSE, &val); return 0; }
static bool timer_tick(void *data) { struct sol_flow_node *node = data; struct int_generator_data *mdata = sol_flow_node_get_private_data(node); struct sol_irange output = { }; int32_t *val; val = sol_vector_get(&mdata->values, mdata->next_index); output.val = *val; output.step = 1; sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TEST_INT_GENERATOR__OUT__OUT, &output); mdata->next_index++; return mdata->next_index != mdata->values.len; }
static void on_slider_changed(GtkRange *range, gpointer data) { struct gtk_common_data *mdata = data; GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(mdata->widget)); struct sol_irange val; val.val = gtk_range_get_value(GTK_RANGE(mdata->widget)); val.min = (int)gtk_adjustment_get_lower(adj); val.max = (int)gtk_adjustment_get_upper(adj); val.step = (int)gtk_adjustment_get_step_increment(adj); sol_flow_send_irange_packet(mdata->node, SOL_FLOW_NODE_TYPE_GTK_SLIDER__OUT__OUT, &val); }
static int inc_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct accumulator_data *mdata = data; mdata->val.val += mdata->val.step; if (mdata->val.val > mdata->val.max) { mdata->val.val = mdata->val.min; sol_flow_send_empty_packet(node, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OVERFLOW); } return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OUT, &mdata->val); }
static int constant_irange_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { const struct sol_flow_node_type_constant_int_options *opts; struct sol_irange value; int r; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK(options, SOL_FLOW_NODE_TYPE_CONSTANT_INT_OPTIONS_API_VERSION, -EINVAL); opts = (const struct sol_flow_node_type_constant_int_options *)options; r = sol_irange_compose(&opts->value_spec, opts->value, &value); SOL_INT_CHECK(r, < 0, r); return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_CONSTANT_INT__OUT__OUT, &value); }
static int accumulator_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options) { int32_t tmp; struct accumulator_data *mdata = data; const struct sol_flow_node_type_int_accumulator_options *opts = (const struct sol_flow_node_type_int_accumulator_options *)options; SOL_FLOW_NODE_OPTIONS_SUB_API_CHECK (options, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR_OPTIONS_API_VERSION, -EINVAL); mdata->val = opts->setup_value; // Sanitizing options input if (mdata->val.max < mdata->val.min) { SOL_WRN("Max (%" PRId32 ") should be greater than Min (%" PRId32 "). Switching both values.", mdata->val.max, mdata->val.min); tmp = mdata->val.max; mdata->val.max = mdata->val.min; mdata->val.min = tmp; } if (mdata->val.val > mdata->val.max || mdata->val.val < mdata->val.min) { SOL_WRN("Value (%" PRId32 ") should be in %" PRId32 " - %" PRId32 " range," " switching it to %" PRId32 "", mdata->val.val, mdata->val.min, mdata->val.max, mdata->val.min); mdata->val.val = mdata->val.min; } if (!mdata->val.step) { mdata->val.step = 1; SOL_WRN("Step can't be zero. Using (%" PRId32 ") instead.", mdata->val.step); } else if (mdata->val.step < 0) { mdata->val.step = -mdata->val.step; SOL_WRN("Step (-%" PRId32 ") can't be a negative value. Using (%" PRId32 ") instead.", mdata->val.step, mdata->val.step); } mdata->init_val = opts->setup_value.val; return sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_INT_ACCUMULATOR__OUT__OUT, &mdata->val); }
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 system_clock_send(const void *timestamp, struct sol_flow_node *node) { struct sol_irange irange = SOL_IRANGE_INIT(); int r; if (!timestamp) { int64_t ts; ts = sol_platform_get_system_clock(); if (ts > INT32_MAX) { sol_flow_send_error_packet(node, EOVERFLOW, "The timestamp %" PRId64 " can not be expressed using 32 bits", ts); return -EOVERFLOW; } irange.val = ts; } else irange.val = (*((int64_t *)timestamp)); r = sol_flow_send_irange_packet(node, 0, &irange); SOL_INT_CHECK(r, < 0, r); 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 localtime_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct timespec value; struct tm split_time; struct sol_irange year = { 0, 0, INT32_MAX, 1 }; struct sol_irange mon = { 0, 0, 11, 1 }; struct sol_irange mday = { 0, 1, 31, 1 }; struct sol_irange hour = { 0, 0, 23, 1 }; struct sol_irange min = { 0, 0, 59, 1 }; struct sol_irange sec = { 0, 0, 59, 1 }; struct sol_irange nsec = { 0, 0, 999999999, 1 }; struct sol_irange wday = { 0, 0, 6, 1 }; struct sol_irange yday = { 0, 0, 365, 1 }; int r; r = sol_flow_packet_get_timestamp(packet, &value); SOL_INT_CHECK(r, < 0, r); tzset(); if (!localtime_r(&value.tv_sec, &split_time)) { sol_flow_send_error_packet(node, EINVAL, "Could not convert time."); return 0; } year.val = split_time.tm_year + 1900; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__YEAR, &year); SOL_INT_CHECK(r, < 0, r); mon.val = split_time.tm_mon + 1; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MONTH, &mon); SOL_INT_CHECK(r, < 0, r); mday.val = split_time.tm_mday; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MONTH_DAY, &mday); SOL_INT_CHECK(r, < 0, r); hour.val = split_time.tm_hour; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__HOUR, &hour); SOL_INT_CHECK(r, < 0, r); min.val = split_time.tm_min; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__MINUTE, &min); SOL_INT_CHECK(r, < 0, r); sec.val = split_time.tm_sec; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__SECOND, &sec); SOL_INT_CHECK(r, < 0, r); nsec.val = value.tv_nsec; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__NANO_SECOND, &nsec); SOL_INT_CHECK(r, < 0, r); wday.val = split_time.tm_wday; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__WEEK_DAY, &wday); SOL_INT_CHECK(r, < 0, r); yday.val = split_time.tm_yday; r = sol_flow_send_irange_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__YEAR_DAY, &yday); SOL_INT_CHECK(r, < 0, r); if (split_time.tm_isdst < 0) SOL_DBG("Daylight saving time information not available."); else { r = sol_flow_send_boolean_packet(node, SOL_FLOW_NODE_TYPE_TIMESTAMP_SPLIT_TIME__OUT__DAYLIGHT_SAVING_TIME, !!split_time.tm_isdst); SOL_INT_CHECK(r, < 0, r); } return 0; }
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); }