From: Michal MalĂ˝ Date: Wed, 10 Feb 2016 15:30:05 +0000 (+0100) Subject: Add support for old HP ChemStation data format X-Git-Url: https://gitweb.devoid-pointer.net/?a=commitdiff_plain;h=5b9826bf62965612262d433409eae8b256b357eb;p=libHPCS.git Add support for old HP ChemStation data format --- diff --git a/include/libhpcs.h b/include/libhpcs.h index a010aed..bfc7c77 100644 --- a/include/libhpcs.h +++ b/include/libhpcs.h @@ -17,6 +17,7 @@ extern "C" { #endif enum HPCS_FileType { + HPCS_TYPE_CE_ANALOG, HPCS_TYPE_CE_CCD, HPCS_TYPE_CE_CURRENT, HPCS_TYPE_CE_DAD, diff --git a/libhpcs.c b/libhpcs.c index 2f40d29..40baaea 100644 --- a/libhpcs.c +++ b/libhpcs.c @@ -134,7 +134,7 @@ enum HPCS_RetCode hpcs_read_mdata(const char* filename, struct HPCS_MeasuredData goto out; } - pret = read_file_type_description(datafile, &mdata->file_description); + pret = read_file_type_description(datafile, &mdata->file_description, gentype); if (pret != PARSE_OK) { ret = HPCS_E_PARSE_ERROR; goto out; @@ -146,32 +146,49 @@ enum HPCS_RetCode hpcs_read_mdata(const char* filename, struct HPCS_MeasuredData goto out; } - pret = read_file_header(datafile, &cs_ver, mdata); + pret = read_file_header(datafile, &cs_ver, mdata, gentype); if (pret != PARSE_OK) { PR_DEBUG("Cannot read the header\n"); ret = HPCS_E_PARSE_ERROR; goto out; } + + /* Old data formats do not containg sampling rate information, set it manually */ + if (OLD_FORMAT(gentype)) { + switch (mdata->file_type) { + case HPCS_TYPE_CE_DAD: + mdata->sampling_rate = 20.0; + break; + case HPCS_TYPE_CE_ANALOG: + mdata->sampling_rate = 10.0; + break; + default: + mdata->sampling_rate = CE_WORK_PARAM_SAMPRATE; + } + } switch (mdata->file_type) { + case HPCS_TYPE_CE_ANALOG: + pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_OLD_STEP, mdata->sampling_rate, gentype); + break; case HPCS_TYPE_CE_CCD: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_CCD_STEP, mdata->sampling_rate); + pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_CCD_STEP, mdata->sampling_rate, gentype); break; case HPCS_TYPE_CE_CURRENT: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, guess_current_step(cs_ver), mdata->sampling_rate); + pret = read_signal(datafile, &mdata->data, &mdata->data_count, guess_current_step(cs_ver, gentype), mdata->sampling_rate, gentype); break; case HPCS_TYPE_CE_DAD: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_DAD_STEP, mdata->sampling_rate); + pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_DAD_STEP, mdata->sampling_rate, gentype); break; case HPCS_TYPE_CE_POWER: case HPCS_TYPE_CE_VOLTAGE: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, guess_elec_sigstep(cs_ver, mdata->file_type), mdata->sampling_rate); + pret = read_signal(datafile, &mdata->data, &mdata->data_count, guess_elec_sigstep(cs_ver, mdata->file_type), mdata->sampling_rate, gentype); break; case HPCS_TYPE_CE_PRESSURE: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_STEP, mdata->sampling_rate); + pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_STEP, mdata->sampling_rate, gentype); break; case HPCS_TYPE_CE_TEMPERATURE: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_OLD_STEP * 10.0, mdata->sampling_rate); + pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_OLD_STEP * 10.0, mdata->sampling_rate, gentype); break; case HPCS_TYPE_UNKNOWN: ret = HPCS_E_UNKNOWN_TYPE; @@ -218,7 +235,7 @@ enum HPCS_RetCode hpcs_read_mheader(const char* filename, struct HPCS_MeasuredDa goto out; } - pret = read_file_type_description(datafile, &mdata->file_description); + pret = read_file_type_description(datafile, &mdata->file_description, gentype); if (pret != PARSE_OK) { ret = HPCS_E_PARSE_ERROR; goto out; @@ -230,7 +247,7 @@ enum HPCS_RetCode hpcs_read_mheader(const char* filename, struct HPCS_MeasuredDa goto out; } - pret = read_file_header(datafile, &cs_ver, mdata); + pret = read_file_header(datafile, &cs_ver, mdata, gentype); if (pret != PARSE_OK) ret = HPCS_E_PARSE_ERROR; else @@ -260,15 +277,25 @@ enum HPCS_RetCode hpcs_read_minfo(const char* filename, struct HPCS_MethodInfo* return HPCS_OK; } -static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileType* file_type, const bool p_means_pressure) +static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileType* file_type, const bool p_means_pressure, const enum HPCS_GenType gentype) { char* type_id; enum HPCS_ParseCode pret; + const HPCS_offset devsig_info_offset = OLD_FORMAT(gentype) ? DATA_OFFSET_DEVSIG_INFO_OLD : DATA_OFFSET_DEVSIG_INFO; - pret = read_string_at_offset(datafile, DATA_OFFSET_DEVSIG_INFO, &type_id); + pret = read_string_at_offset(datafile, devsig_info_offset, &type_id, gentype); if (pret != PARSE_OK) return pret; + if (!strcmp(type_id, FILE_TYPE_ID_ADC_A)) { + *file_type = HPCS_TYPE_CE_ANALOG; + goto out; + } + if (!strcmp(type_id, FILE_TYPE_ID_ADC_B)) { + *file_type = HPCS_TYPE_CE_ANALOG; + goto out; + } + if (strstr(type_id, FILE_TYPE_ID_DAD) == type_id) *file_type = HPCS_TYPE_CE_DAD; else if (strstr(type_id, FILE_TYPE_ID_HPCE) == type_id) { @@ -291,6 +318,7 @@ static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileTy } else *file_type = HPCS_TYPE_UNKNOWN; +out: free(type_id); return PARSE_OK; @@ -342,6 +370,7 @@ static bool file_type_description_is_readable(const char*const description) static bool gentype_is_readable(const enum HPCS_GenType gentype) { switch (gentype) { + case GENTYPE_ADC_LC: case GENTYPE_ADC_LC2: return true; default: @@ -349,12 +378,12 @@ static bool gentype_is_readable(const enum HPCS_GenType gentype) } } -static HPCS_step guess_current_step(const enum HPCS_ChemStationVer version) +static HPCS_step guess_current_step(const enum HPCS_ChemStationVer version, const enum HPCS_GenType gentype) { - if (version != CHEMSTAT_B0625) - return CE_CURRENT_STEP; + if (version == CHEMSTAT_B0625 || OLD_FORMAT(gentype)) + return CE_WORK_PARAM_OLD_STEP * 10.0; - return CE_WORK_PARAM_OLD_STEP * 10.0; + return CE_CURRENT_STEP; } static HPCS_step guess_elec_sigstep(const enum HPCS_ChemStationVer version, const enum HPCS_FileType file_type) @@ -482,17 +511,18 @@ static enum HPCS_ParseCode parse_native_method_info_line(char** name, char** val #endif } -static enum HPCS_ParseCode read_dad_wavelength(FILE* datafile, struct HPCS_Wavelength* const measured, struct HPCS_Wavelength* const reference) +static enum HPCS_ParseCode read_dad_wavelength(FILE* datafile, struct HPCS_Wavelength* const measured, struct HPCS_Wavelength* const reference, const enum HPCS_GenType gentype) { char* start_idx, *interv_idx, *end_idx, *temp, *str; size_t len, tmp_len; enum HPCS_ParseCode pret, ret; + const HPCS_offset devsig_info_offset = OLD_FORMAT(gentype) ? DATA_OFFSET_DEVSIG_INFO_OLD : DATA_OFFSET_DEVSIG_INFO; measured->wavelength = 0; measured->interval = 0; reference->wavelength = 0; reference->interval = 0; - pret = read_string_at_offset(datafile, DATA_OFFSET_DEVSIG_INFO, &str); + pret = read_string_at_offset(datafile, devsig_info_offset, &str, gentype); if (pret != PARSE_OK) return pret; @@ -615,7 +645,7 @@ out: first 127 characters from ISO-8859-1 charset. Under such assumption it is possible to treat UTF-8 strings as single-byte strings with ISO-8859-1 encoding */ -static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date) +static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date, const enum HPCS_GenType gentype) { char* date_str; char* date_time_delim; @@ -624,8 +654,9 @@ static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date) char temp[32]; size_t len; enum HPCS_ParseCode pret; + const HPCS_offset date_offset = OLD_FORMAT(gentype) ? DATA_OFFSET_DATE_OLD : DATA_OFFSET_DATE; - pret = read_string_at_offset(datafile, DATA_OFFSET_DATE, &date_str); + pret = read_string_at_offset(datafile, date_offset, &date_str, OLD_FORMAT(gentype)); if (pret != PARSE_OK) return pret; @@ -695,65 +726,78 @@ static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date) return PARSE_OK; } -static enum HPCS_ParseCode read_file_header(FILE* datafile, enum HPCS_ChemStationVer* cs_ver, struct HPCS_MeasuredData* mdata) +static enum HPCS_ParseCode read_file_header(FILE* datafile, enum HPCS_ChemStationVer* cs_ver, struct HPCS_MeasuredData* mdata, const enum HPCS_GenType gentype) { enum HPCS_ParseCode pret; + const bool old_format = OLD_FORMAT(gentype); + const HPCS_offset sample_info_offset = old_format ? DATA_OFFSET_SAMPLE_INFO_OLD : DATA_OFFSET_SAMPLE_INFO; + const HPCS_offset operator_name_offset = old_format ? DATA_OFFSET_OPERATOR_NAME_OLD : DATA_OFFSET_OPERATOR_NAME; + const HPCS_offset method_name_offset = old_format ? DATA_OFFSET_METHOD_NAME_OLD : DATA_OFFSET_METHOD_NAME; + const HPCS_offset y_units_offset = old_format ? DATA_OFFSET_Y_UNITS_OLD : DATA_OFFSET_Y_UNITS; - pret = read_string_at_offset(datafile, DATA_OFFSET_SAMPLE_INFO, &mdata->sample_info); + pret = read_string_at_offset(datafile, sample_info_offset, &mdata->sample_info, old_format); if (pret != PARSE_OK) { PR_DEBUG("Cannot read sample info\n"); return pret; } - pret = read_string_at_offset(datafile, DATA_OFFSET_OPERATOR_NAME, &mdata->operator_name); + pret = read_string_at_offset(datafile, operator_name_offset, &mdata->operator_name, old_format); if (pret != PARSE_OK) { PR_DEBUG("Cannot read operator name\n"); return pret; } - pret = read_string_at_offset(datafile, DATA_OFFSET_METHOD_NAME, &mdata->method_name); + pret = read_string_at_offset(datafile, method_name_offset, &mdata->method_name, old_format); if (pret != PARSE_OK) { PR_DEBUG("Cannot read method name\n"); return pret; } - pret = read_date(datafile, &mdata->date); + pret = read_date(datafile, &mdata->date, gentype); if (pret != PARSE_OK) { PR_DEBUG("Cannot read date of measurement\n"); return pret; } - pret = read_string_at_offset(datafile, DATA_OFFSET_CS_VER, &mdata->cs_ver); - if (pret != PARSE_OK) { - PR_DEBUG("Cannot read ChemStation software version\n"); - return pret; - } - pret = read_string_at_offset(datafile, DATA_OFFSET_Y_UNITS, &mdata->y_units); - if (pret != PARSE_OK) { - PR_DEBUG("Cannot read values of Y axis\n"); - return pret; + + if (!old_format) { + pret = read_string_at_offset(datafile, DATA_OFFSET_CS_VER, &mdata->cs_ver, old_format); + if (pret != PARSE_OK) { + PR_DEBUG("Cannot read ChemStation software version\n"); + return pret; + } + pret = read_string_at_offset(datafile, DATA_OFFSET_CS_REV, &mdata->cs_rev, old_format); + if (pret != PARSE_OK) { + PR_DEBUG("Cannot read ChemStation software revision\n"); + return pret; + } + } else { + mdata->cs_ver = DEFAULT_CS_VER; + mdata->cs_rev = DEFAULT_CS_REV; } - pret = read_string_at_offset(datafile, DATA_OFFSET_CS_REV, &mdata->cs_rev); + + pret = read_string_at_offset(datafile, y_units_offset, &mdata->y_units, old_format); if (pret != PARSE_OK) { - PR_DEBUG("Cannot read ChemStation software revision\n"); - return pret; + PR_DEBUG("Cannot read values of Y axis\n"); + return pret; } - pret = read_sampling_rate(datafile, &mdata->sampling_rate); + + pret = read_sampling_rate(datafile, &mdata->sampling_rate, old_format); if (pret != PARSE_OK) { PR_DEBUG("Cannot read sampling rate of the file\n"); return pret; } - *cs_ver = detect_chemstation_version(mdata->cs_ver); + *cs_ver = detect_chemstation_version(mdata->cs_ver); if (pret != PARSE_OK) { PR_DEBUG("Cannot detect ChemStation version\n"); return pret; } - pret = autodetect_file_type(datafile, &mdata->file_type, p_means_pressure(*cs_ver)); + pret = autodetect_file_type(datafile, &mdata->file_type, p_means_pressure(*cs_ver), old_format); if (pret != PARSE_OK) { PR_DEBUG("Cannot determine the type of file\n"); return pret; } if (mdata->file_type == HPCS_TYPE_CE_DAD) { - pret = read_dad_wavelength(datafile, &mdata->dad_wavelength_msr, &mdata->dad_wavelength_ref); + pret = read_dad_wavelength(datafile, &mdata->dad_wavelength_msr, &mdata->dad_wavelength_ref, gentype); if (pret != PARSE_OK && pret != PARSE_W_NO_DATA) { PR_DEBUG("Cannot read wavelength\n"); return pret; @@ -764,11 +808,12 @@ static enum HPCS_ParseCode read_file_header(FILE* datafile, enum HPCS_ChemStatio return PARSE_OK; } -static enum HPCS_ParseCode read_file_type_description(FILE* datafile, char** const description) +static enum HPCS_ParseCode read_file_type_description(FILE* datafile, char** const description, const enum HPCS_GenType gentype) { enum HPCS_ParseCode pret; + const HPCS_offset offset = OLD_FORMAT(gentype) ? DATA_OFFSET_FILE_DESC_OLD : DATA_OFFSET_FILE_DESC; - pret = read_string_at_offset(datafile, DATA_OFFSET_FILE_DESC, description); + pret = read_string_at_offset(datafile, offset, description, OLD_FORMAT(gentype)); if (pret != PARSE_OK) PR_DEBUG("Cannot read file description\n"); @@ -863,7 +908,7 @@ out: } static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pairs, size_t* pairs_count, - const HPCS_step step, const double sampling_rate) + const HPCS_step step, const double sampling_rate, const enum HPCS_GenType gentype) { const double time_step = 1 / (60 * sampling_rate); size_t alloc_size = (size_t)((60 * sampling_rate) + 0.5); @@ -873,11 +918,12 @@ static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pair size_t segments_read = 0; size_t data_segments_read = 0; size_t next_marker_idx = 0; + const HPCS_offset data_start_offset = OLD_FORMAT(gentype) ? DATA_OFFSET_DATA_START_OLD : DATA_OFFSET_DATA_START; char raw[2]; size_t r; enum HPCS_DataCheckCode dret; - fseek(datafile, DATA_OFFSET_DATA_START, SEEK_SET); + fseek(datafile, data_start_offset, SEEK_SET); if (feof(datafile)) return PARSE_E_OUT_OF_RANGE; if (ferror(datafile)) @@ -984,12 +1030,17 @@ static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pair return PARSE_OK; } -static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_rate) +static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_rate, const bool old_format) { char raw[2]; uint16_t number; size_t r; + if (old_format) { + *sampling_rate = 0.0; /* This information cannot be read from the datafile */ + return PARSE_OK; + } + fseek(datafile, DATA_OFFSET_SAMPLING_RATE, SEEK_SET); if (feof(datafile)) return PARSE_E_OUT_OF_RANGE; @@ -1007,7 +1058,56 @@ static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_r return PARSE_OK; } -static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offset offset, char** const result) +static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offset offset, char** const result, const bool old_format) +{ + if (old_format) + return __read_string_at_offset_v1(datafile, offset, result); + return __read_string_at_offset_v2(datafile, offset, result); +} + +static enum HPCS_ParseCode __read_string_at_offset_v1(FILE* datafile, const HPCS_offset offset, char** const result) +{ + size_t r; + char ch; + size_t str_length = 0; + + fseek(datafile, offset, SEEK_SET); + if (feof(datafile)) + return PARSE_E_OUT_OF_RANGE; + if (ferror(datafile)) + return PARSE_E_CANT_READ; + + /* Read the length of the string */ + while (true) { + r = fread(&ch, SMALL_SEGMENT_SIZE, 1, datafile); + if (r != 1) + return PARSE_E_CANT_READ; + + if (ch != '\0') + str_length++; + else + break; + } + + /* Allocate read buffer */ + *result = calloc(str_length + 1, SMALL_SEGMENT_SIZE); + if (*result == NULL) + return PARSE_E_NO_MEM; + + memset(*result, 0, (str_length + 1)); + + /* Rewind the file and read the string */ + fseek(datafile, offset, SEEK_SET); + r = fread(*result, SMALL_SEGMENT_SIZE, str_length, datafile); + if (r < str_length) { + free(*result); + return PARSE_E_CANT_READ; + } + + return PARSE_OK; +} + +static enum HPCS_ParseCode __read_string_at_offset_v2(FILE* datafile, const HPCS_offset offset, char** const result) { char* string; uint8_t str_length; @@ -1048,6 +1148,7 @@ static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offs /* Explicitly convert from UTF-16LE (internal WCHAR representation) */ ret = __unix_wchar_to_utf8(result, string, str_length * SEGMENT_SIZE); #endif + free(string); return ret; } @@ -1341,6 +1442,25 @@ static enum HPCS_ParseCode __unix_wchar_to_utf8(char** target, const char* bytes } #endif + +static char* __DEFAULT_CS_REV() +{ + static const char* s = "UNKNOWN_REVISION"; + char* ns = malloc(strlen(s) + 1); + memset(ns, 0, strlen(s) + 1); + strcpy(ns, s); + return ns; +} + +static char* __DEFAULT_CS_VER() +{ + static const char* s = "UNKNOWN_VERSION"; + char* ns = malloc(strlen(s) + 1); + memset(ns, 0, strlen(s) + 1); + strcpy(ns, s); + return ns; +} + #ifdef __cplusplus } #endif diff --git a/libhpcs_p.h b/libhpcs_p.h index bd5e826..5092b36 100644 --- a/libhpcs_p.h +++ b/libhpcs_p.h @@ -46,8 +46,8 @@ typedef size_t HPCS_offset; typedef double HPCS_step; typedef size_t HPCS_segsize; - -/* Identifiers of file types found at offset 0x1075 onward */ +const char FILE_TYPE_ID_ADC_A[] = "ADC CHANNEL A"; +const char FILE_TYPE_ID_ADC_B[] = "ADC CHANNEL B"; const char FILE_TYPE_ID_DAD[] = "DAD"; const char FILE_TYPE_ID_HPCE[] = "HPCE"; const char FILE_TYPE_HPCE_CCD = 'L'; @@ -103,6 +103,15 @@ const HPCS_offset DATA_OFFSET_SAMPLING_RATE = 0x101C; const HPCS_offset DATA_OFFSET_Y_UNITS = 0x104C; const HPCS_offset DATA_OFFSET_DEVSIG_INFO = 0x1075; const HPCS_offset DATA_OFFSET_DATA_START = 0x1800; +/* Offsets valid of old HP data format */ +const HPCS_offset DATA_OFFSET_FILE_DESC_OLD = 0x005; +const HPCS_offset DATA_OFFSET_SAMPLE_INFO_OLD = 0x019; +const HPCS_offset DATA_OFFSET_OPERATOR_NAME_OLD = 0x095; +const HPCS_offset DATA_OFFSET_DATE_OLD = 0x0B3; +const HPCS_offset DATA_OFFSET_METHOD_NAME_OLD = 0x0E5; +const HPCS_offset DATA_OFFSET_Y_UNITS_OLD = 0x245; +const HPCS_offset DATA_OFFSET_DEVSIG_INFO_OLD = 0x255; +const HPCS_offset DATA_OFFSET_DATA_START_OLD = 0x400; /* General data file types */ enum HPCS_GenType { @@ -159,11 +168,11 @@ UChar* EQUALITY_SIGN; UChar* CR_LF; #endif -static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileType* file_type, const bool p_means_pressure); +static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileType* file_type, const bool p_means_pressure, const enum HPCS_GenType gentype); static enum HPCS_DataCheckCode check_for_marker(const char* segment, size_t* const next_marker_idx); static enum HPCS_ChemStationVer detect_chemstation_version(const char*const version_string); static bool gentype_is_readable(const enum HPCS_GenType gentype); -static HPCS_step guess_current_step(const enum HPCS_ChemStationVer version); +static HPCS_step guess_current_step(const enum HPCS_ChemStationVer version, const enum HPCS_GenType gentype); static HPCS_step guess_elec_sigstep(const enum HPCS_ChemStationVer version, const enum HPCS_FileType file_type); static void guess_sampling_rate(const enum HPCS_ChemStationVer version, struct HPCS_MeasuredData* mdata); static bool file_type_description_is_readable(const char*const description); @@ -171,19 +180,21 @@ static enum HPCS_ParseCode next_native_line(HPCS_UFH fh, HPCS_NChar* line, int32 static HPCS_UFH open_data_file(const char* filename); static FILE* open_measurement_file(const char* filename); static enum HPCS_ParseCode parse_native_method_info_line(char** name, char** value, HPCS_NChar* line); -static enum HPCS_ParseCode read_dad_wavelength(FILE* datafile, struct HPCS_Wavelength* const measured, struct HPCS_Wavelength* const reference); +static enum HPCS_ParseCode read_dad_wavelength(FILE* datafile, struct HPCS_Wavelength* const measured, struct HPCS_Wavelength* const reference, const enum HPCS_GenType gentype); static uint8_t month_to_number(const char* month); static bool p_means_pressure(const enum HPCS_ChemStationVer version); -static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date); -static enum HPCS_ParseCode read_file_header(FILE* datafile, enum HPCS_ChemStationVer* cs_ver, struct HPCS_MeasuredData* mdata); -static enum HPCS_ParseCode read_file_type_description(FILE* datafile, char** const description); +static enum HPCS_ParseCode read_date(FILE* datafile, struct HPCS_Date* date, const enum HPCS_GenType gentype); +static enum HPCS_ParseCode read_file_header(FILE* datafile, enum HPCS_ChemStationVer* cs_ver, struct HPCS_MeasuredData* mdata, const enum HPCS_GenType gentype); +static enum HPCS_ParseCode read_file_type_description(FILE* datafile, char** const description, const enum HPCS_GenType gentype); static enum HPCS_ParseCode read_generic_type(FILE* datafile, enum HPCS_GenType* gentype); static enum HPCS_ParseCode read_method_info_file(HPCS_UFH fh, struct HPCS_MethodInfo* minfo); static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pairs, size_t* pairs_count, - const HPCS_step step, const double sampling_rate); -static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_rate); -static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offset, char** const result); + const HPCS_step step, const double sampling_rate, const enum HPCS_GenType gentype); +static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_rate, const bool old_format); +static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offset, char** const result, const bool read_as_wchar); static void remove_trailing_newline(HPCS_NChar* s); +static enum HPCS_ParseCode __read_string_at_offset_v1(FILE* datafile, const HPCS_offset offset, char** const result); +static enum HPCS_ParseCode __read_string_at_offset_v2(FILE* datafile, const HPCS_offset offset, char** const result); /** Platform-specific functions */ #ifdef _WIN32 @@ -201,6 +212,21 @@ static enum HPCS_ParseCode __unix_next_native_line(UFILE* fh, UChar* line, int32 static enum HPCS_ParseCode __unix_parse_native_method_info_line(char** name, char** value, UChar* line); static enum HPCS_ParseCode __unix_wchar_to_utf8(char** target, const char* bytes, const size_t bytes_count); +static char* __DEFAULT_CS_REV(); +static char* __DEFAULT_CS_VER(); +#define DEFAULT_CS_REV __DEFAULT_CS_REV() +#define DEFAULT_CS_VER __DEFAULT_CS_VER() + +static bool OLD_FORMAT(const enum HPCS_GenType gentype) +{ + switch (gentype) { + case GENTYPE_ADC_LC2: + return false; + default: + return true; + } +} + #define __ICU_INIT_STRING(dst, s) do { \ UChar temp[64]; \ int32_t length = u_unescape(s, temp, sizeof(temp)); \