static gboolean check_params(const SDFile *sdfile, guint len, GError **error) { if (sdfile->data_type >= SDF_NTYPES) { err_DATA_TYPE(error, sdfile->data_type); return FALSE; } if (err_DIMENSION(error, sdfile->xres) || err_DIMENSION(error, sdfile->yres)) return FALSE; if (err_SIZE_MISMATCH(error, sdfile->expected_size, len, FALSE)) return FALSE; if (sdfile->compression) { err_UNSUPPORTED(error, "Compression"); return FALSE; } if (sdfile->check_type) { err_UNSUPPORTED(error, "CheckType"); return FALSE; } return TRUE; }
static GwyContainer* unisoku_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { UnisokuFile ufile; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gchar *text = NULL; gsize i, size = 0; GError *err = NULL; GwyDataField *dfield = NULL; gchar *data_name; if (!g_file_get_contents(filename, &text, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } for (i = 0; i < size; i++) { if (!text[i]) text[i] = ' '; } gwy_clear(&ufile, 1); if (!unisoku_read_header(text, &ufile, error)) { unisoku_file_free(&ufile); g_free(text); return NULL; } g_free(text); if (ufile.data_type < UNISOKU_UINT8 || ufile.data_type > UNISOKU_FLOAT || type_sizes[ufile.data_type] == 0) { err_DATA_TYPE(error, ufile.data_type); unisoku_file_free(&ufile); return NULL; } if (!(data_name = unisoku_find_data_name(filename))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("No corresponding data file was found for header file.")); unisoku_file_free(&ufile); return NULL; } if (!gwy_file_get_contents(data_name, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); unisoku_file_free(&ufile); g_free(data_name); return NULL; } dfield = unisoku_read_data_field(buffer, size, &ufile, error); gwy_file_abandon_contents(buffer, size, NULL); if (!dfield) { unisoku_file_free(&ufile); g_free(data_name); return NULL; } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); gwy_app_channel_title_fall_back(container, 0); meta = unisoku_get_metadata(&ufile); gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); gwy_file_channel_import_log_add(container, 0, NULL, data_name); unisoku_file_free(&ufile); g_free(data_name); return container; }
static GwyContainer* sensofar_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { SensofarDataDesc data_desc; GwyContainer *container = NULL; GwyDataField *dfield, *mfield; GwyGraphModel *gmodel; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; const guchar *p; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < HEADER_SIZE + 12) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("File header is truncated")); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } /* Date block */ p = buffer; memcpy(&data_desc.date.str, p, DATE_SIZE); data_desc.date.str[DATE_SIZE-1] = '\0'; p += DATE_SIZE; data_desc.date.t = gwy_get_guint32_le(&p); /* Comment block */ memcpy(&data_desc.user_comment, p, COMMENT_SIZE); data_desc.user_comment[COMMENT_SIZE-1] = '\0'; p += COMMENT_SIZE; /* Calbration block */ data_desc.axes_config.yres = gwy_get_guint32_le(&p); data_desc.axes_config.xres = gwy_get_guint32_le(&p); data_desc.axes_config.N_tall = gwy_get_guint32_le(&p); data_desc.axes_config.dy_multip = gwy_get_gfloat_le(&p); data_desc.axes_config.mppx = gwy_get_gfloat_le(&p); data_desc.axes_config.mppy = gwy_get_gfloat_le(&p); data_desc.axes_config.x_0 = gwy_get_gfloat_le(&p); data_desc.axes_config.y_0 = gwy_get_gfloat_le(&p); data_desc.axes_config.mpp_tall = gwy_get_gfloat_le(&p); data_desc.axes_config.z_0 = gwy_get_gfloat_le(&p); /* Measurement block */ data_desc.measure_config.type = gwy_get_guint32_le(&p); data_desc.measure_config.algorithm = gwy_get_guint32_le(&p); data_desc.measure_config.method = gwy_get_guint32_le(&p); data_desc.measure_config.objective = gwy_get_guint32_le(&p); data_desc.measure_config.area = gwy_get_guint32_le(&p); data_desc.measure_config.xres_area = gwy_get_guint32_le(&p); data_desc.measure_config.yres_area = gwy_get_guint32_le(&p); data_desc.measure_config.xres = gwy_get_guint32_le(&p); data_desc.measure_config.yres = gwy_get_guint32_le(&p); data_desc.measure_config.na = gwy_get_guint32_le(&p); data_desc.measure_config.incr_z = gwy_get_gdouble_le(&p); data_desc.measure_config.range = gwy_get_gfloat_le(&p); data_desc.measure_config.n_planes = gwy_get_guint32_le(&p); data_desc.measure_config.tpc_umbral_F = gwy_get_guint32_le(&p); data_desc.measure_config.restore = gwy_get_gboolean8(&p); data_desc.measure_config.num_layers = *(p++); data_desc.measure_config.version = *(p++); data_desc.measure_config.config_hardware = *(p++); data_desc.measure_config.stack_im_num = *(p++); data_desc.measure_config.reserved = *(p++); p += 2; // struct padding data_desc.measure_config.factor_delmacio = gwy_get_guint32_le(&p); gwy_debug("File date=<%s>, data type=%d, xres=%d, yres=%d, version=%d", data_desc.date.str, data_desc.measure_config.type, data_desc.measure_config.xres, data_desc.measure_config.yres, data_desc.measure_config.version); switch (data_desc.measure_config.type) { case MES_TOPO: case MES_IMATGE: dfield = sensofar_read_data_field(&data_desc, &mfield, &p, size - (p - buffer), error); if (!dfield) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield); g_object_unref(dfield); if (mfield) { gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0), mfield); g_object_unref(mfield); } gwy_app_channel_title_fall_back(container, 0); break; case MES_PERFIL: case MES_GRUIX: gmodel = sensofar_read_profile(&data_desc, &p, size - (p - buffer), error); if (!gmodel) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } container = gwy_container_new(); gwy_container_set_object(container, gwy_app_get_graph_key_for_id(0), gmodel); g_object_unref(gmodel); break; default: err_DATA_TYPE(error, data_desc.measure_config.type); break; } return container; }
static gboolean cdffile_read_var_array(NetCDFVar **pvars, gint *pnvars, NetCDFVersion version, const guchar *buf, gsize size, const guchar **p, GError **error) { NetCDFVar *vars; gint nvars, n, i, ts, offset_size; if (!cdffile_check_size(error, "var_array", buf, size, *p, 8)) return FALSE; n = gwy_get_guint32_be(p); gwy_debug("vars (%d)", n); if (n != 0 && n != NC_VARIABLE) { err_CDF_EXPECTED(error, "NC_VARIABLE"); return FALSE; } nvars = gwy_get_guint32_be(p); if (nvars && !n) { err_CDF_ZELEMENTS(error, "var_array"); return FALSE; } gwy_debug("nvars: %d", nvars); if (!nvars) return TRUE; switch (version) { case NETCDF_CLASSIC: offset_size = 4; break; case NETCDF_64BIT: offset_size = 8; break; default: g_return_val_if_reached(FALSE); break; } vars = g_new0(NetCDFVar, nvars); *pvars = vars; *pnvars = nvars; for (i = 0; i < nvars; i++) { if (!cdffile_check_size(error, "var_array", buf, size, *p, 4)) return FALSE; n = gwy_get_guint32_be(p); ALIGN4(n); if (!cdffile_check_size(error, "var_array", buf, size, *p, n + 4)) return FALSE; vars[i].name = g_strndup((const gchar*)*p, n); *p += n; vars[i].ndims = gwy_get_guint32_be(p); gwy_debug("var_array[%d]: <%s> %d", i, vars[i].name, vars[i].ndims); if (!cdffile_check_size(error, "var_array", buf, size, *p, 4*vars[i].ndims)) return FALSE; vars[i].dimids = g_new(gint, vars[i].ndims); for (n = 0; n < vars[i].ndims; n++) { vars[i].dimids[n] = gwy_get_guint32_be(p); gwy_debug("var_array[%d][%d]: %d", i, n, vars[i].dimids[n]); } if (!cdffile_read_attr_array(&vars[i].attrs, &vars[i].nattrs, buf, size, p, error)) return FALSE; if (!cdffile_check_size(error, "var_array", buf, size, *p, 8 + offset_size)) return FALSE; vars[i].type = gwy_get_guint32_be(p); ts = cdffile_type_size(vars[i].type); if (!ts) { err_DATA_TYPE(error, vars[i].type); return FALSE; } vars[i].vsize = gwy_get_guint32_be(p); switch (version) { case NETCDF_CLASSIC: vars[i].begin = gwy_get_guint32_be(p); break; case NETCDF_64BIT: vars[i].begin = gwy_get_guint64_be(p); break; } } return TRUE; }
static gboolean cdffile_read_attr_array(NetCDFAttr **pattrs, gint *pnattrs, const guchar *buf, gsize size, const guchar **p, GError **error) { NetCDFAttr *attrs; gint nattrs, n, ts, i; if (!cdffile_check_size(error, "attr_array", buf, size, *p, 8)) return FALSE; n = gwy_get_guint32_be(p); gwy_debug("attrs (%d)", n); if (n != 0 && n != NC_ATTRIBUTE) { err_CDF_EXPECTED(error, "NC_ATTRIBUTE"); return FALSE; } nattrs = gwy_get_guint32_be(p); if (nattrs && !n) { err_CDF_ZELEMENTS(error, "attr_array"); return FALSE; } gwy_debug("nattrs: %d", nattrs); if (!nattrs) return TRUE; attrs = g_new0(NetCDFAttr, nattrs); *pattrs = attrs; *pnattrs = nattrs; for (i = 0; i < nattrs; i++) { if (!cdffile_check_size(error, "attr_array", buf, size, *p, 4)) return FALSE; n = gwy_get_guint32_be(p); n += (4 - n % 4) % 4; if (!cdffile_check_size(error, "attr_array", buf, size, *p, n + 8)) return FALSE; attrs[i].name = g_strndup((const gchar*)*p, n); *p += n; attrs[i].type = gwy_get_guint32_be(p); attrs[i].nelems = gwy_get_guint32_be(p); gwy_debug("attr_array[%d]: <%s> %d of %d", i, attrs[i].name, attrs[i].nelems, attrs[i].type); ts = cdffile_type_size(attrs[i].type); if (!ts) { err_DATA_TYPE(error, attrs[i].type); return FALSE; } n = ts*attrs[i].nelems; ALIGN4(n); if (!cdffile_check_size(error, "attr_array", buf, size, *p, n)) return FALSE; attrs[i].values = *p; *p += n; } return TRUE; }
static GwyContainer* igor_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *meta = NULL, *container = NULL; GwyDataField *dfield = NULL, *maskfield = NULL; GwyTextHeaderParser parser; IgorFile igorfile; IgorWaveHeader5 *wave5; GError *err = NULL; guchar *p, *buffer = NULL; gint xres, yres; gsize expected_size, size = 0; gchar *note = NULL; const gchar *value; gchar key[64]; guint i, chid; GQuark quark; guint nlabels; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } gwy_clear(&igorfile, 1); if (!igor_read_headers(&igorfile, buffer, size, FALSE, error)) goto fail; /* Only accept v5 files because older do not support 2D data */ if (igorfile.header.version != 5) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Format version is %d. Only version 5 is supported."), igorfile.header.version); goto fail; } /* Detect Asylum research files, leave it at generic if not detected. */ if (memcmp(buffer + size-5, "MFP3D", 5) == 0) igorfile.variant = IGOR_ASYLUM_MPF3D; else if (memcmp(buffer + size-5, "Force", 5) == 0) igorfile.variant = IGOR_ASYLUM_FORCE; gwy_debug("producer variant %u", igorfile.variant); /* Must have exactly 3 dims: xres, yres, nchannels */ wave5 = &igorfile.wave5; xres = wave5->n_dim[0]; yres = wave5->n_dim[1]; igorfile.nchannels = wave5->n_dim[2]; if (igorfile.nchannels==0) igorfile.nchannels=1; if (!xres || !yres || !igorfile.nchannels || wave5->n_dim[3]) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional data are supported.")); goto fail; } igorfile.type_size = igor_data_type_size(wave5->type); if (!igorfile.type_size) { err_DATA_TYPE(error, wave5->type); goto fail; } if (wave5->npts != xres*yres*igorfile.nchannels) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Number of data points %u does not match resolutions " "%u×%u×%u."), wave5->npts, xres, yres, igorfile.nchannels); goto fail; } if (igorfile.header.wfm_size <= igorfile.wave_header_size) { err_INVALID(error, "wfmSize"); goto fail; } expected_size = igorfile.header.wfm_size - igorfile.wave_header_size; if (expected_size != wave5->npts*igorfile.type_size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Data size %u does not match " "the number of data points %u×%u."), (guint)expected_size, wave5->npts, igorfile.type_size); } if (err_SIZE_MISMATCH(error, expected_size + igorfile.headers_size, size, FALSE)) goto fail; p = buffer + igorfile.headers_size + expected_size; gwy_debug("remaning data size: %lu", (gulong)(size - (p - buffer))); p += igorfile.header.formula_size; if ((igorfile.variant == IGOR_ASYLUM_FORCE || igorfile.variant == IGOR_ASYLUM_MPF3D) && igorfile.header.note_size && (p - buffer) + igorfile.header.note_size <= size) { note = g_strndup((const gchar*)p, size); gwy_clear(&parser, 1); parser.key_value_separator = ":"; igorfile.meta = gwy_text_header_parse(note, &parser, NULL, NULL); } p += igorfile.header.note_size; /* FIXME: Support extended units for non-Asylum files! */ p += igorfile.header.data_e_units_size; for (i = 0; i < MAXDIMS; i++) p += igorfile.header.dim_e_units_size[i]; /* Skip labels of x and y dimension, we don't know what to do with them. */ for (i = 0; i < 2; i++) p += igorfile.header.dim_labels_size[i]; /* FIXME: The labels are mandatory only in Asylum Research files. */ nlabels = igorfile.header.dim_labels_size[2]/(MAX_WAVE_NAME5+1); expected_size = (MAX_WAVE_NAME5 + 1)*(nlabels); if ((p - buffer) + expected_size > size ) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Cannot read channel labels.")); goto fail; } igorfile.titles = read_channel_labels(p, igorfile.nchannels+1, nlabels); p += igorfile.header.dim_labels_size[2]; if (igorfile.meta) { igorfile.channel_info = g_new0(AsylumChannelInfo, igorfile.nchannels); for (i = 0; i < igorfile.nchannels; i++) { AsylumChannelInfo *chinfo = igorfile.channel_info + i; const gchar *title = g_ptr_array_index(igorfile.titles, i+1); if (title) { chinfo->name = canonicalize_title(title); g_snprintf(key, sizeof(key), "%sUnit", chinfo->name); value = g_hash_table_lookup(igorfile.meta, key); if (value) chinfo->units = value; else chinfo->units = channel_title_to_units(chinfo->name); } } } container = gwy_container_new(); for (i = chid = 0; i < igorfile.nchannels; i++, chid++) { const gchar *title = g_ptr_array_index(igorfile.titles, i+1); const gchar *zunits = NULL; if (igorfile.channel_info) { AsylumChannelInfo *chinfo = igorfile.channel_info + i; zunits = chinfo->units; meta = igor_get_metadata(&igorfile, i + 1); } dfield = igor_read_data_field(&igorfile, buffer, i, zunits, FALSE); maskfield = gwy_app_channel_mask_of_nans(dfield, TRUE); quark = gwy_app_get_data_key_for_id(chid); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); if (maskfield) { g_snprintf(key, sizeof(key), "/%d/mask", chid); gwy_container_set_object_by_name(container, key, maskfield); } if (meta) { g_snprintf(key, sizeof(key), "/%d/meta", chid); gwy_container_set_object_by_name(container, key, meta); } if (title) { g_snprintf(key, sizeof(key), "/%d/data/title", chid); gwy_container_set_string_by_name(container, key, g_strdup(title)); } gwy_app_channel_title_fall_back(container,chid); if (wave5->type & IGOR_COMPLEX) { chid++; dfield = igor_read_data_field(&igorfile, buffer, i, zunits, TRUE); quark = gwy_app_get_data_key_for_id(chid); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); if (meta) { g_snprintf(key, sizeof(key), "/%d/meta", chid); /* container still holds a reference */ g_object_unref(meta); meta = gwy_container_duplicate(meta); gwy_container_set_object_by_name(container, key, meta); } if (maskfield) { g_snprintf(key, sizeof(key), "/%d/mask", chid); /* container still holds a reference */ g_object_unref(maskfield); maskfield = gwy_data_field_duplicate(maskfield); gwy_container_set_object_by_name(container, key, maskfield); } if (title) { g_snprintf(key, sizeof(key), "/%d/data/title", chid); gwy_container_set_string_by_name(container, key, g_strdup(title)); }; gwy_app_channel_title_fall_back(container,chid); } gwy_object_unref(meta); gwy_object_unref(maskfield); gwy_file_channel_import_log_add(container, chid, NULL, filename); } fail: gwy_file_abandon_contents(buffer, size, NULL); g_free(note); if (igorfile.channel_info) { for (i = 0; i < igorfile.nchannels; i++) g_free(igorfile.channel_info[i].name); g_free(igorfile.channel_info); } if (igorfile.meta) g_hash_table_destroy(igorfile.meta); if (igorfile.titles) { g_ptr_array_foreach(igorfile.titles, (GFunc)g_free, NULL); g_ptr_array_free(igorfile.titles, TRUE); } return container; }