#define LOG_PREFIX "input"
/** @endcond */
+#define CHUNK_SIZE (4 * 1024 * 1024)
+
/**
* @file
*
extern SR_PRIV struct sr_input_module input_vcd;
extern SR_PRIV struct sr_input_module input_wav;
extern SR_PRIV struct sr_input_module input_raw_analog;
+extern SR_PRIV struct sr_input_module input_logicport;
+extern SR_PRIV struct sr_input_module input_null;
/* @endcond */
static const struct sr_input_module *input_module_list[] = {
&input_vcd,
&input_wav,
&input_raw_analog,
+ &input_logicport,
+ &input_null,
NULL,
};
* Try to find an input module that can parse the given buffer.
*
* The buffer must contain enough of the beginning of the file for
- * the input modules to find a match. This is format-dependent, but
- * 128 bytes is normally enough.
+ * the input modules to find a match. This is format-dependent. When
+ * magic strings get checked, 128 bytes normally could be enough. Note
+ * that some formats try to parse larger header sections, and benefit
+ * from seeing a larger scope.
*
* If an input module is found, an instance is created into *in.
- * Otherwise, *in contains NULL.
+ * Otherwise, *in contains NULL. When multiple input moduless claim
+ * support for the format, the one with highest confidence takes
+ * precedence. Applications will see at most one input module spec.
*
* If an instance is created, it has the given buffer used for scanning
* already submitted to it, to be processed before more data is sent.
*/
SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in)
{
- const struct sr_input_module *imod;
+ const struct sr_input_module *imod, *best_imod;
GHashTable *meta;
unsigned int m, i;
+ unsigned int conf, best_conf;
int ret;
uint8_t mitem, avail_metadata[8];
avail_metadata[1] = 0;
*in = NULL;
- ret = SR_ERR;
+ best_imod = NULL;
+ best_conf = ~0;
for (i = 0; input_module_list[i]; i++) {
imod = input_module_list[i];
if (!imod->metadata[0]) {
continue;
}
sr_spew("Trying module %s.", imod->id);
- ret = imod->format_match(meta);
+ ret = imod->format_match(meta, &conf);
g_hash_table_destroy(meta);
if (ret == SR_ERR_DATA) {
/* Module recognized this buffer, but cannot handle it. */
- break;
+ continue;
} else if (ret == SR_ERR) {
/* Module didn't recognize this buffer. */
continue;
} else if (ret != SR_OK) {
/* Can be SR_ERR_NA. */
- return ret;
+ continue;
}
/* Found a matching module. */
- sr_spew("Module %s matched.", imod->id);
- *in = sr_input_new(imod, NULL);
+ sr_spew("Module %s matched, confidence %u.", imod->id, conf);
+ if (conf >= best_conf)
+ continue;
+ best_imod = imod;
+ best_conf = conf;
+ }
+
+ if (best_imod) {
+ *in = sr_input_new(best_imod, NULL);
g_string_insert_len((*in)->buf, 0, buf->str, buf->len);
- break;
+ return SR_OK;
}
- return ret;
+ return SR_ERR;
}
/**
* Try to find an input module that can parse the given file.
*
* If an input module is found, an instance is created into *in.
- * Otherwise, *in contains NULL.
+ * Otherwise, *in contains NULL. When multiple input moduless claim
+ * support for the format, the one with highest confidence takes
+ * precedence. Applications will see at most one input module spec.
*
*/
SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in)
{
int64_t filesize;
FILE *stream;
- const struct sr_input_module *imod;
+ const struct sr_input_module *imod, *best_imod;
GHashTable *meta;
GString *header;
size_t count;
unsigned int midx, i;
+ unsigned int conf, best_conf;
int ret;
uint8_t avail_metadata[8];
fclose(stream);
return SR_ERR;
}
- /* This actually allocates 256 bytes to allow for NUL termination. */
- header = g_string_sized_new(255);
+ header = g_string_sized_new(CHUNK_SIZE);
count = fread(header->str, 1, header->allocated_len - 1, stream);
-
- if (count != header->allocated_len - 1 && ferror(stream)) {
+ if (count < 1 || ferror(stream)) {
sr_err("Failed to read %s: %s", filename, g_strerror(errno));
fclose(stream);
g_string_free(header, TRUE);
avail_metadata[midx] = 0;
/* TODO: MIME type */
- ret = SR_ERR;
-
+ best_imod = NULL;
+ best_conf = ~0;
for (i = 0; input_module_list[i]; i++) {
imod = input_module_list[i];
if (!imod->metadata[0]) {
sr_dbg("Trying module %s.", imod->id);
- ret = imod->format_match(meta);
+ ret = imod->format_match(meta, &conf);
if (ret == SR_ERR) {
/* Module didn't recognize this buffer. */
continue;
} else if (ret != SR_OK) {
/* Module recognized this buffer, but cannot handle it. */
- break;
+ continue;
}
/* Found a matching module. */
- sr_dbg("Module %s matched.", imod->id);
-
- *in = sr_input_new(imod, NULL);
- break;
+ sr_dbg("Module %s matched, confidence %u.", imod->id, conf);
+ if (conf >= best_conf)
+ continue;
+ best_imod = imod;
+ best_conf = conf;
}
g_hash_table_destroy(meta);
g_string_free(header, TRUE);
- return ret;
+ if (best_imod) {
+ *in = sr_input_new(best_imod, NULL);
+ return SR_OK;
+ }
+
+ return SR_ERR;
}
/**
return in->module->end((struct sr_input *)in);
}
+/**
+ * Reset the input module's input handling structures.
+ *
+ * Causes the input module to reset its internal state so that we can re-send
+ * the input data from the beginning without having to re-create the entire
+ * input module.
+ *
+ * @since 0.5.0
+ */
+SR_API int sr_input_reset(const struct sr_input *in)
+{
+ if (!in->module->reset) {
+ sr_spew("Tried to reset %s module but no reset handler found.",
+ in->module->id);
+ return SR_OK;
+ }
+
+ sr_spew("Resetting %s module.", in->module->id);
+ return in->module->reset((struct sr_input *)in);
+}
+
/**
* Free the specified input instance and all associated resources.
*
if (in->module->cleanup)
in->module->cleanup((struct sr_input *)in);
- if (in->sdi)
- sr_dev_inst_free(in->sdi);
+ sr_dev_inst_free(in->sdi);
if (in->buf->len > 64) {
/* That seems more than just some sub-unitsize leftover... */
sr_warn("Found %" G_GSIZE_FORMAT