Skip to content

Commit 626c388

Browse files
committed
input/csv: rearrange text to logic data conversion and datafeed
Move the helper routines which arrange for the data feed to an earlier spot, so that references resolve without forward declarations. Rename routines to reflect that they deal with logic data. Slightly unobfuscate column text to logic data conversion, and reduce redundancy. Move sample data preset to a central location. Rephrase error messages, provide stronger hints as to why the input text for a conversion was considered invalid.
1 parent dbc3838 commit 626c388

File tree

1 file changed

+99
-92
lines changed

1 file changed

+99
-92
lines changed

src/input/csv.c

Lines changed: 99 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,84 @@ struct context {
174174
GSList *prev_sr_channels;
175175
};
176176

177+
/*
178+
* Primitive operations to handle sample sets:
179+
* - Keep a buffer for datafeed submission, capable of holding many
180+
* samples (reduces call overhead, improves throughput).
181+
* - Have a "current sample set" pointer reference one position in that
182+
* large samples buffer.
183+
* - Clear the current sample set before text line inspection, then set
184+
* the bits which are found active in the current line of text input.
185+
* Phrase the API such that call sites can be kept simple. Advance to
186+
* the next sample set between lines, flush the larger buffer as needed
187+
* (when it is full, or upon EOF).
188+
*/
189+
190+
static void clear_logic_samples(struct context *inc)
191+
{
192+
inc->sample_buffer = &inc->datafeed_buffer[inc->datafeed_buf_fill];
193+
memset(inc->sample_buffer, 0, inc->sample_unit_size);
194+
}
195+
196+
static void set_logic_level(struct context *inc, size_t ch_idx, int on)
197+
{
198+
size_t byte_idx, bit_idx;
199+
uint8_t bit_mask;
200+
201+
if (ch_idx >= inc->num_channels)
202+
return;
203+
if (!on)
204+
return;
205+
206+
byte_idx = ch_idx / 8;
207+
bit_idx = ch_idx % 8;
208+
bit_mask = 1 << bit_idx;
209+
inc->sample_buffer[byte_idx] |= bit_mask;
210+
}
211+
212+
static int flush_logic_samples(const struct sr_input *in)
213+
{
214+
struct context *inc;
215+
struct sr_datafeed_packet packet;
216+
struct sr_datafeed_logic logic;
217+
int rc;
218+
219+
inc = in->priv;
220+
if (!inc->datafeed_buf_fill)
221+
return SR_OK;
222+
223+
memset(&packet, 0, sizeof(packet));
224+
memset(&logic, 0, sizeof(logic));
225+
packet.type = SR_DF_LOGIC;
226+
packet.payload = &logic;
227+
logic.unitsize = inc->sample_unit_size;
228+
logic.length = inc->datafeed_buf_fill;
229+
logic.data = inc->datafeed_buffer;
230+
231+
rc = sr_session_send(in->sdi, &packet);
232+
if (rc != SR_OK)
233+
return rc;
234+
235+
inc->datafeed_buf_fill = 0;
236+
return SR_OK;
237+
}
238+
239+
static int queue_logic_samples(const struct sr_input *in)
240+
{
241+
struct context *inc;
242+
int rc;
243+
244+
inc = in->priv;
245+
246+
inc->datafeed_buf_fill += inc->sample_unit_size;
247+
if (inc->datafeed_buf_fill == inc->datafeed_buf_size) {
248+
rc = flush_logic_samples(in);
249+
if (rc != SR_OK)
250+
return rc;
251+
}
252+
return SR_OK;
253+
}
254+
177255
/*
178256
* Primitive operations for text input: Strip comments off text lines.
179257
* Split text lines into columns. Process input text for individual
@@ -210,25 +288,22 @@ static void strip_comment(char *buf, const GString *prefix)
210288
static int parse_binstr(const char *str, struct context *inc)
211289
{
212290
gsize i, j, length;
291+
char c;
213292

214293
length = strlen(str);
215-
216294
if (!length) {
217295
sr_err("Column %zu in line %zu is empty.", inc->single_column,
218296
inc->line_number);
219297
return SR_ERR;
220298
}
221299

222-
/* Clear buffer in order to set bits only. */
223-
memset(inc->sample_buffer, 0, inc->sample_unit_size);
224-
225300
i = inc->first_channel;
226-
227301
for (j = 0; i < length && j < inc->num_channels; i++, j++) {
228-
if (str[length - i - 1] == '1') {
229-
inc->sample_buffer[j / 8] |= (1 << (j % 8));
230-
} else if (str[length - i - 1] != '0') {
231-
sr_err("Invalid value '%s' in column %zu in line %zu.",
302+
c = str[length - i - 1];
303+
if (c == '1') {
304+
set_logic_level(inc, j, 1);
305+
} else if (c != '0') {
306+
sr_err("Invalid text '%s' in binary column %zu in line %zu.",
232307
str, inc->single_column, inc->line_number);
233308
return SR_ERR;
234309
}
@@ -256,37 +331,26 @@ static int parse_hexstr(const char *str, struct context *inc)
256331
char c;
257332

258333
length = strlen(str);
259-
260334
if (!length) {
261335
sr_err("Column %zu in line %zu is empty.", inc->single_column,
262336
inc->line_number);
263337
return SR_ERR;
264338
}
265339

266-
/* Clear buffer in order to set bits only. */
267-
memset(inc->sample_buffer, 0, inc->sample_unit_size);
268-
269340
/* Calculate the position of the first hexadecimal digit. */
270341
i = inc->first_channel / 4;
271-
272342
for (j = 0; i < length && j < inc->num_channels; i++) {
273343
c = str[length - i - 1];
274-
275344
if (!g_ascii_isxdigit(c)) {
276-
sr_err("Invalid value '%s' in column %zu in line %zu.",
345+
sr_err("Invalid text '%s' in hex column %zu in line %zu.",
277346
str, inc->single_column, inc->line_number);
278347
return SR_ERR;
279348
}
280349

281350
value = g_ascii_xdigit_value(c);
282-
283351
k = (inc->first_channel + j) % 4;
284-
285-
for (; j < inc->num_channels && k < 4; k++) {
286-
if (value & (1 << k))
287-
inc->sample_buffer[j / 8] |= (1 << (j % 8));
288-
289-
j++;
352+
for (; j < inc->num_channels && k < 4; j++, k++) {
353+
set_logic_level(inc, j, value & (1 << k));
290354
}
291355
}
292356

@@ -312,37 +376,26 @@ static int parse_octstr(const char *str, struct context *inc)
312376
char c;
313377

314378
length = strlen(str);
315-
316379
if (!length) {
317380
sr_err("Column %zu in line %zu is empty.", inc->single_column,
318381
inc->line_number);
319382
return SR_ERR;
320383
}
321384

322-
/* Clear buffer in order to set bits only. */
323-
memset(inc->sample_buffer, 0, inc->sample_unit_size);
324-
325385
/* Calculate the position of the first octal digit. */
326386
i = inc->first_channel / 3;
327-
328387
for (j = 0; i < length && j < inc->num_channels; i++) {
329388
c = str[length - i - 1];
330-
331389
if (c < '0' || c > '7') {
332-
sr_err("Invalid value '%s' in column %zu in line %zu.",
390+
sr_err("Invalid text '%s' in oct column %zu in line %zu.",
333391
str, inc->single_column, inc->line_number);
334392
return SR_ERR;
335393
}
336394

337395
value = g_ascii_xdigit_value(c);
338-
339396
k = (inc->first_channel + j) % 3;
340-
341-
for (; j < inc->num_channels && k < 3; k++) {
342-
if (value & (1 << k))
343-
inc->sample_buffer[j / 8] |= (1 << (j % 8));
344-
345-
j++;
397+
for (; j < inc->num_channels && k < 3; j++, k++) {
398+
set_logic_level(inc, j, value & (1 << k));
346399
}
347400
}
348401

@@ -441,19 +494,16 @@ static int parse_multi_columns(char **columns, struct context *inc)
441494
gsize i;
442495
char *column;
443496

444-
/* Clear buffer in order to set bits only. */
445-
memset(inc->sample_buffer, 0, inc->sample_unit_size);
446-
447497
for (i = 0; i < inc->num_channels; i++) {
448498
column = columns[i];
449499
if (strcmp(column, "1") == 0) {
450-
inc->sample_buffer[i / 8] |= (1 << (i % 8));
500+
set_logic_level(inc, i, 1);
451501
} else if (!strlen(column)) {
452502
sr_err("Column %zu in line %zu is empty.",
453503
inc->first_channel + i, inc->line_number);
454504
return SR_ERR;
455505
} else if (strcmp(column, "0") != 0) {
456-
sr_err("Invalid value '%s' in column %zu in line %zu.",
506+
sr_err("Invalid text '%s' in bit column %zu in line %zu.",
457507
column, inc->first_channel + i,
458508
inc->line_number);
459509
return SR_ERR;
@@ -463,50 +513,6 @@ static int parse_multi_columns(char **columns, struct context *inc)
463513
return SR_OK;
464514
}
465515

466-
static int flush_samples(const struct sr_input *in)
467-
{
468-
struct context *inc;
469-
struct sr_datafeed_packet packet;
470-
struct sr_datafeed_logic logic;
471-
int rc;
472-
473-
inc = in->priv;
474-
if (!inc->datafeed_buf_fill)
475-
return SR_OK;
476-
477-
memset(&packet, 0, sizeof(packet));
478-
memset(&logic, 0, sizeof(logic));
479-
packet.type = SR_DF_LOGIC;
480-
packet.payload = &logic;
481-
logic.unitsize = inc->sample_unit_size;
482-
logic.length = inc->datafeed_buf_fill;
483-
logic.data = inc->datafeed_buffer;
484-
485-
rc = sr_session_send(in->sdi, &packet);
486-
if (rc != SR_OK)
487-
return rc;
488-
489-
inc->datafeed_buf_fill = 0;
490-
return SR_OK;
491-
}
492-
493-
static int queue_samples(const struct sr_input *in)
494-
{
495-
struct context *inc;
496-
int rc;
497-
498-
inc = in->priv;
499-
500-
inc->datafeed_buf_fill += inc->sample_unit_size;
501-
if (inc->datafeed_buf_fill == inc->datafeed_buf_size) {
502-
rc = flush_samples(in);
503-
if (rc != SR_OK)
504-
return rc;
505-
}
506-
inc->sample_buffer = &inc->datafeed_buffer[inc->datafeed_buf_fill];
507-
return SR_OK;
508-
}
509-
510516
static int init(struct sr_input *in, GHashTable *options)
511517
{
512518
struct context *inc;
@@ -731,15 +737,14 @@ static int initial_parse(const struct sr_input *in, GString *buf)
731737
* Calculate the minimum buffer size to store the set of samples
732738
* of all channels (unit size). Determine a larger buffer size
733739
* for datafeed submission that is a multiple of the unit size.
734-
* Allocate the larger buffer, and have the "sample buffer" point
735-
* to a location within that large buffer.
740+
* Allocate the larger buffer, the "sample buffer" will point
741+
* to a location within that large buffer later.
736742
*/
737743
inc->sample_unit_size = (inc->num_channels + 7) / 8;
738744
inc->datafeed_buf_size = CHUNK_SIZE;
739745
inc->datafeed_buf_size *= inc->sample_unit_size;
740746
inc->datafeed_buffer = g_malloc(inc->datafeed_buf_size);
741747
inc->datafeed_buf_fill = 0;
742-
inc->sample_buffer = &inc->datafeed_buffer[inc->datafeed_buf_fill];
743748

744749
out:
745750
if (columns)
@@ -919,6 +924,8 @@ static int process_buffer(struct sr_input *in, gboolean is_eof)
919924
return SR_ERR;
920925
}
921926

927+
clear_logic_samples(inc);
928+
922929
if (inc->multi_column_mode)
923930
ret = parse_multi_columns(columns, inc);
924931
else
@@ -929,8 +936,8 @@ static int process_buffer(struct sr_input *in, gboolean is_eof)
929936
return SR_ERR;
930937
}
931938

932-
/* Send sample data to the session bus. */
933-
ret = queue_samples(in);
939+
/* Send sample data to the session bus (buffered). */
940+
ret = queue_logic_samples(in);
934941
if (ret != SR_OK) {
935942
sr_err("Sending samples failed.");
936943
g_strfreev(columns);
@@ -984,7 +991,7 @@ static int end(struct sr_input *in)
984991
if (ret != SR_OK)
985992
return ret;
986993

987-
ret = flush_samples(in);
994+
ret = flush_logic_samples(in);
988995
if (ret != SR_OK)
989996
return ret;
990997

0 commit comments

Comments
 (0)