56#define PARAMETER_MODE 1
60static char *mode_name[MODES] = {
75char *option[N_OPTIONS] = {
90#define CLO_LONGDOUBLE 8
119 "Usage: sddscast [<source-file>] [<target-file>] \n"
120 " [-pipe=<input>,<output>] \n"
122 " -cast=<mode>,<columnNames>,<typeNames>,<newType>\n\n"
124 " -pipe=<input>,<output> Specify input and/or output pipes.\n"
125 " -noWarnings Suppress warning messages.\n"
126 " -cast=<mode>,<names>,<types>,<newType>\n"
127 " Cast datatypes of specified columns, parameters, or arrays.\n"
128 " <mode>: one of 'column', 'parameter', or 'array'.\n"
129 " <names>: Comma-separated list of names (supports wildcards).\n"
130 " <types>: Comma-separated list of current types.\n"
131 " <newType>: Target datatype (long, ulong, long64, ulong64, short, ushort,\n"
132 " longdouble, double, float).\n\n"
134 " sddscast converts the numeric columns, parameters, or arrays from one datatype to another within an SDDS file.\n\n"
135 "Author: Hairong Shang\n"
136 "Compiled on " __DATE__
" at " __TIME__
", SVN revision: " SVN_VERSION
"\n";
141long add_casts(
char *old_type,
long sdds_type,
CAST_NAME *cast_name,
char *add_name,
char *new_type,
long index,
long noWarnings);
144int main(
int argc,
char **argv) {
147 char *inputfile, *outputfile;
148 long tmpfile_used, noWarnings, i, i_arg;
149 CAST_NAME column_cast, parameter_cast, array_cast;
150 CAST_REQUEST *col_request, *par_request, *array_request;
151 long col_requests, par_requests, array_requests, rows;
152 unsigned long pipeFlags, majorOrderFlag;
153 short columnMajorOrder = -1;
155 column_cast.n = parameter_cast.n = array_cast.n = 0;
156 column_cast.name = column_cast.new_type = NULL;
157 column_cast.index = parameter_cast.index = array_cast.index = 0;
158 parameter_cast.name = parameter_cast.new_type = NULL;
159 array_cast.name = array_cast.new_type = NULL;
160 col_request = par_request = array_request = NULL;
161 col_requests = par_requests = array_requests = rows = 0;
164 argc =
scanargs(&s_arg, argc, argv);
168 inputfile = outputfile = NULL;
169 noWarnings = tmpfile_used = pipeFlags = 0;
171 for (i_arg = 1; i_arg < argc; i_arg++) {
172 if (s_arg[i_arg].arg_type == OPTION) {
174 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
175 case SET_MAJOR_ORDER:
177 s_arg[i_arg].n_items -= 1;
178 if (s_arg[i_arg].n_items > 0 &&
179 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
180 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
181 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
182 SDDS_Bomb(
"invalid -majorOrder syntax/values");
183 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
184 columnMajorOrder = 1;
185 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
186 columnMajorOrder = 0;
192 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
196 if (s_arg[i_arg].n_items < 4)
198 if (
match_string(s_arg[i_arg].list[4], types, TYPES, MATCH_WHOLE_STRING) < 0) {
199 SDDS_Bomb(
"The new type to cast has to be a numeric type!");
201 switch (
match_string(s_arg[i_arg].list[1], mode_name, MODES, 0)) {
203 col_request =
SDDS_Realloc(col_request,
sizeof(*col_request) * (col_requests + 1));
204 col_request[col_requests].match_string = s_arg[i_arg].list[2];
205 col_request[col_requests].type_string = s_arg[i_arg].list[3];
206 col_request[col_requests].new_type = s_arg[i_arg].list[4];
210 par_request =
SDDS_Realloc(par_request,
sizeof(*par_request) * (par_requests + 1));
211 par_request[par_requests].match_string = s_arg[i_arg].list[2];
212 par_request[par_requests].type_string = s_arg[i_arg].list[3];
213 par_request[par_requests].new_type = s_arg[i_arg].list[4];
217 array_request =
SDDS_Realloc(array_request,
sizeof(*array_request) * (array_requests + 1));
218 array_request[array_requests].match_string = s_arg[i_arg].list[2];
219 array_request[array_requests].type_string = s_arg[i_arg].list[3];
220 array_request[array_requests].new_type = s_arg[i_arg].list[4];
233 if (inputfile == NULL)
234 inputfile = s_arg[i_arg].list[0];
235 else if (outputfile == NULL)
236 outputfile = s_arg[i_arg].list[0];
238 fprintf(stderr,
"Error: Too many filenames provided (sddscast).\n");
244 processFilenames(
"sddscast", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
254 if (columnMajorOrder != -1)
255 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
257 SDDS_output.layout.data_mode.column_major = SDDS_input.layout.data_mode.column_major;
259 process_cast_columns(&SDDS_input, &column_cast, col_request, col_requests, noWarnings);
260 process_cast_parameters(&SDDS_input, ¶meter_cast, par_request, par_requests, noWarnings);
261 process_cast_arrays(&SDDS_input, &array_cast, array_request, array_requests, noWarnings);
263 for (i = 0; i < column_cast.n; i++) {
264 if (!
SDDS_ChangeColumnInformation(&SDDS_output,
"type", column_cast.new_type[i], SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, column_cast.name[i])) {
269 for (i = 0; i < parameter_cast.n; i++) {
270 if (!
SDDS_ChangeParameterInformation(&SDDS_output,
"type", parameter_cast.new_type[i], SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, parameter_cast.name[i])) {
276 for (i = 0; i < array_cast.n; i++) {
277 if (!
SDDS_ChangeArrayInformation(&SDDS_output,
"type", array_cast.new_type[i], SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, array_cast.name[i])) {
302 cleanUpCast(&column_cast);
303 cleanUpCast(¶meter_cast);
304 cleanUpCast(&array_cast);
318 for (i = 0; i < cast_name->n; i++) {
319 free(cast_name->name[i]);
320 free(cast_name->new_type[i]);
321 cast_name->name[i] = NULL;
322 cast_name->new_type[i] = NULL;
324 free(cast_name->name);
325 free(cast_name->new_type);
326 free(cast_name->index);
327 cast_name->name = NULL;
328 cast_name->new_type = NULL;
329 cast_name->index = NULL;
333 char *ptr, **Names, **Match_string, **type_string;
334 long i, index, j, k, type, s1, s2;
342 Match_string = type_string = NULL;
344 for (i = 0; i < col_requests; i++) {
347 while (ptr != NULL) {
348 Match_string =
SDDS_Realloc(Match_string,
sizeof(
char *) * (s1 + 1));
351 ptr = strtok(NULL,
",");
353 ptr = strtok(col_request[i].type_string,
",");
354 while (ptr != NULL) {
355 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (s2 + 1));
358 ptr = strtok(NULL,
",");
361 for (j = s2; j < s1; j++) {
362 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (j + 1));
367 for (k = 0; k < s1; k++) {
372 fprintf(stderr,
"Warning: Column '%s' does not exist.\n", Match_string[k]);
376 add_casts(type_string[k], type, column_cast, Match_string[k], col_request[i].new_type, index, noWarnings);
383 fprintf(stderr,
"Warning: No columns match the pattern '%s'.\n", Match_string[k]);
385 for (j = 0; j < names; j++) {
388 add_casts(type_string[k], type, column_cast, Names[j], col_request[i].new_type, index, noWarnings);
400 Match_string = type_string = NULL;
405 char *ptr, **Names, **Match_string, **type_string;
406 long i, index, j, k, type, s1, s2;
414 Match_string = type_string = NULL;
418 fprintf(stderr,
"Warning: No parameters found in the input file.\n");
421 for (i = 0; i < par_requests; i++) {
424 while (ptr != NULL) {
425 Match_string =
SDDS_Realloc(Match_string,
sizeof(
char *) * (s1 + 1));
428 ptr = strtok(NULL,
",");
430 ptr = strtok(par_request[i].type_string,
",");
431 while (ptr != NULL) {
432 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (s2 + 1));
435 ptr = strtok(NULL,
",");
438 for (j = s2; j < s1; j++) {
439 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (j + 1));
444 for (k = 0; k < s1; k++) {
449 fprintf(stderr,
"Warning: Parameter '%s' does not exist in the input file.\n", Match_string[k]);
453 add_casts(type_string[k], type, parameter_cast, Match_string[k], par_request[i].new_type, index, noWarnings);
455 for (j = 0; j < names; j++) {
459 add_casts(type_string[k], type, parameter_cast, Names[j], par_request[i].new_type, index, noWarnings);
465 for (j = 0; j < s1; j++)
466 free(Match_string[j]);
470 for (j = 0; j < s2; j++)
471 free(type_string[j]);
474 Match_string = type_string = NULL;
476 for (i = 0; i < names; i++)
482 char *ptr, **Names, **Match_string, **type_string;
483 long i, index, j, k, type, s1, s2;
491 Match_string = type_string = NULL;
495 fprintf(stderr,
"Warning: Unable to retrieve array names from the input file.\n");
498 for (i = 0; i < array_requests; i++) {
501 while (ptr != NULL) {
502 Match_string =
SDDS_Realloc(Match_string,
sizeof(
char *) * (s1 + 1));
505 ptr = strtok(NULL,
",");
507 ptr = strtok(array_request[i].type_string,
",");
508 while (ptr != NULL) {
509 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (s2 + 1));
512 ptr = strtok(NULL,
",");
515 for (j = s2; j < s1; j++) {
516 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (j + 1));
521 for (k = 0; k < s1; k++) {
526 fprintf(stderr,
"Warning: Array '%s' does not exist in the input file.\n", Match_string[k]);
530 add_casts(type_string[k], type, array_cast, Match_string[k], array_request[i].new_type, index, noWarnings);
532 for (j = 0; j < names; j++) {
536 add_casts(type_string[k], type, array_cast, Names[j], array_request[i].new_type, index, noWarnings);
545 Match_string = type_string = NULL;
547 for (i = 0; i < names; i++)
552long add_casts(
char *old_type,
long sdds_type,
CAST_NAME *cast_name,
char *add_name,
char *new_type,
long index,
long noWarnings) {
557 fprintf(stderr,
"Warning: The type of '%s' is not numeric and cannot be cast to a numeric type.\n", add_name);
560 if (strcmp(old_type,
"*") == 0)
565 if (strcmp(old_type,
"longdouble") == 0)
569 if (strcmp(old_type,
"double") == 0)
573 if (strcmp(old_type,
"float") == 0)
577 if (strcmp(old_type,
"long64") == 0)
581 if (strcmp(old_type,
"ulong64") == 0)
585 if (strcmp(old_type,
"long") == 0)
589 if (strcmp(old_type,
"ulong") == 0)
593 if (strcmp(old_type,
"short") == 0)
597 if (strcmp(old_type,
"ushort") == 0)
606 fprintf(stderr,
"Warning: The type of '%s' does not match '%s'.\n", add_name, old_type);
609 cast_name->name =
SDDS_Realloc(cast_name->name,
sizeof(
char *) * (cast_name->n + 1));
610 cast_name->new_type =
SDDS_Realloc(cast_name->new_type,
sizeof(
char *) * (cast_name->n + 1));
613 cast_name->index =
SDDS_Realloc(cast_name->index,
sizeof(
long) * (cast_name->n + 1));
614 cast_name->index[cast_name->n] = index;
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_ChangeParameterInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a parameter definition within the SDDS dataset.
int32_t SDDS_ChangeArrayInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in an array definition within the SDDS dataset.
int32_t SDDS_ChangeColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a column definition within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
int32_t SDDS_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array in the SDDS dataset.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
int32_t SDDS_GetArrayType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of an array in the SDDS dataset by its index.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
char ** SDDS_GetArrayNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all arrays in the SDDS dataset.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
#define SDDS_FLOAT
Identifier for the float data type.
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_SHORT
Identifier for the signed short integer data type.
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
int has_wildcards(char *template)
Check if a template string contains any wildcard characters.
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.