59#define PARAMETER_MODE 1
63static char *mode_name[MODES] = {
78char *option[N_OPTIONS] = {
93#define CLO_LONGDOUBLE 8
122 "sddscast [<source-file>] [<target-file>] \n"
123 " [-pipe=[<input>][,<output>]] \n"
125 " -cast=<mode>,<columnNames>,<typeNames>,<newType>\n"
126 " [-majorOrder=row|column]\n"
128 " -pipe=[<input>][,<output>] Specify input and/or output pipes.\n"
129 " -noWarnings Suppress warning messages.\n"
130 " -cast=<mode>,<names>,<types>,<newType>\n"
131 " Cast datatypes of specified columns, parameters, or arrays.\n"
132 " <mode>: one of 'column', 'parameter', or 'array'.\n"
133 " <names>: Comma-separated list of names (supports wildcards).\n"
134 " <types>: Comma-separated list of current types.\n"
135 " <newType>: Target datatype (long, ulong, long64, ulong64, short, ushort,\n"
136 " longdouble, double, float).\n\n"
138 " sddscast converts the numeric columns, parameters, or arrays from one datatype to another within an SDDS file.\n\n"
139 "Author: Hairong Shang\n"
140 "Compiled on " __DATE__
" at " __TIME__
", SVN revision: " SVN_VERSION
"\n";
145long add_casts(
char *old_type,
long sdds_type,
CAST_NAME *cast_name,
char *add_name,
char *new_type,
long index,
long noWarnings);
148int main(
int argc,
char **argv) {
151 char *inputfile, *outputfile;
152 long tmpfile_used, noWarnings, i, i_arg;
153 CAST_NAME column_cast, parameter_cast, array_cast;
154 CAST_REQUEST *col_request, *par_request, *array_request;
155 long col_requests, par_requests, array_requests, rows;
156 unsigned long pipeFlags, majorOrderFlag;
157 short columnMajorOrder = -1;
159 column_cast.n = parameter_cast.n = array_cast.n = 0;
160 column_cast.name = column_cast.new_type = NULL;
161 column_cast.index = parameter_cast.index = array_cast.index = 0;
162 parameter_cast.name = parameter_cast.new_type = NULL;
163 array_cast.name = array_cast.new_type = NULL;
164 col_request = par_request = array_request = NULL;
165 col_requests = par_requests = array_requests = rows = 0;
168 argc =
scanargs(&s_arg, argc, argv);
172 inputfile = outputfile = NULL;
173 noWarnings = tmpfile_used = pipeFlags = 0;
175 for (i_arg = 1; i_arg < argc; i_arg++) {
176 if (s_arg[i_arg].arg_type == OPTION) {
178 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
179 case SET_MAJOR_ORDER:
181 s_arg[i_arg].n_items -= 1;
182 if (s_arg[i_arg].n_items > 0 &&
183 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
184 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
185 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
186 SDDS_Bomb(
"invalid -majorOrder syntax/values");
187 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
188 columnMajorOrder = 1;
189 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
190 columnMajorOrder = 0;
196 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
200 if (s_arg[i_arg].n_items < 4)
202 if (
match_string(s_arg[i_arg].list[4], types, TYPES, MATCH_WHOLE_STRING) < 0) {
203 SDDS_Bomb(
"The new type to cast has to be a numeric type!");
205 switch (
match_string(s_arg[i_arg].list[1], mode_name, MODES, 0)) {
207 col_request =
SDDS_Realloc(col_request,
sizeof(*col_request) * (col_requests + 1));
208 col_request[col_requests].match_string = s_arg[i_arg].list[2];
209 col_request[col_requests].type_string = s_arg[i_arg].list[3];
210 col_request[col_requests].new_type = s_arg[i_arg].list[4];
214 par_request =
SDDS_Realloc(par_request,
sizeof(*par_request) * (par_requests + 1));
215 par_request[par_requests].match_string = s_arg[i_arg].list[2];
216 par_request[par_requests].type_string = s_arg[i_arg].list[3];
217 par_request[par_requests].new_type = s_arg[i_arg].list[4];
221 array_request =
SDDS_Realloc(array_request,
sizeof(*array_request) * (array_requests + 1));
222 array_request[array_requests].match_string = s_arg[i_arg].list[2];
223 array_request[array_requests].type_string = s_arg[i_arg].list[3];
224 array_request[array_requests].new_type = s_arg[i_arg].list[4];
237 if (inputfile == NULL)
238 inputfile = s_arg[i_arg].list[0];
239 else if (outputfile == NULL)
240 outputfile = s_arg[i_arg].list[0];
242 fprintf(stderr,
"Error: Too many filenames provided (sddscast).\n");
248 processFilenames(
"sddscast", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
258 if (columnMajorOrder != -1)
259 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
261 SDDS_output.layout.data_mode.column_major = SDDS_input.layout.data_mode.column_major;
263 process_cast_columns(&SDDS_input, &column_cast, col_request, col_requests, noWarnings);
264 process_cast_parameters(&SDDS_input, ¶meter_cast, par_request, par_requests, noWarnings);
265 process_cast_arrays(&SDDS_input, &array_cast, array_request, array_requests, noWarnings);
267 for (i = 0; i < column_cast.n; i++) {
268 if (!
SDDS_ChangeColumnInformation(&SDDS_output,
"type", column_cast.new_type[i], SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, column_cast.name[i])) {
273 for (i = 0; i < parameter_cast.n; i++) {
274 if (!
SDDS_ChangeParameterInformation(&SDDS_output,
"type", parameter_cast.new_type[i], SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, parameter_cast.name[i])) {
280 for (i = 0; i < array_cast.n; i++) {
281 if (!
SDDS_ChangeArrayInformation(&SDDS_output,
"type", array_cast.new_type[i], SDDS_PASS_BY_STRING | SDDS_SET_BY_NAME, array_cast.name[i])) {
306 cleanUpCast(&column_cast);
307 cleanUpCast(¶meter_cast);
308 cleanUpCast(&array_cast);
322 for (i = 0; i < cast_name->n; i++) {
323 free(cast_name->name[i]);
324 free(cast_name->new_type[i]);
325 cast_name->name[i] = NULL;
326 cast_name->new_type[i] = NULL;
328 free(cast_name->name);
329 free(cast_name->new_type);
330 free(cast_name->index);
331 cast_name->name = NULL;
332 cast_name->new_type = NULL;
333 cast_name->index = NULL;
337 char *ptr, **Names, **Match_string, **type_string;
338 long i, index, j, k, type, s1, s2;
346 Match_string = type_string = NULL;
348 for (i = 0; i < col_requests; i++) {
351 while (ptr != NULL) {
352 Match_string =
SDDS_Realloc(Match_string,
sizeof(
char *) * (s1 + 1));
355 ptr = strtok(NULL,
",");
357 ptr = strtok(col_request[i].type_string,
",");
358 while (ptr != NULL) {
359 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (s2 + 1));
362 ptr = strtok(NULL,
",");
365 for (j = s2; j < s1; j++) {
366 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (j + 1));
371 for (k = 0; k < s1; k++) {
376 fprintf(stderr,
"Warning: Column '%s' does not exist.\n", Match_string[k]);
380 add_casts(type_string[k], type, column_cast, Match_string[k], col_request[i].new_type, index, noWarnings);
387 fprintf(stderr,
"Warning: No columns match the pattern '%s'.\n", Match_string[k]);
389 for (j = 0; j < names; j++) {
392 add_casts(type_string[k], type, column_cast, Names[j], col_request[i].new_type, index, noWarnings);
404 Match_string = type_string = NULL;
409 char *ptr, **Names, **Match_string, **type_string;
410 long i, index, j, k, type, s1, s2;
418 Match_string = type_string = NULL;
422 fprintf(stderr,
"Warning: No parameters found in the input file.\n");
425 for (i = 0; i < par_requests; i++) {
428 while (ptr != NULL) {
429 Match_string =
SDDS_Realloc(Match_string,
sizeof(
char *) * (s1 + 1));
432 ptr = strtok(NULL,
",");
434 ptr = strtok(par_request[i].type_string,
",");
435 while (ptr != NULL) {
436 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (s2 + 1));
439 ptr = strtok(NULL,
",");
442 for (j = s2; j < s1; j++) {
443 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (j + 1));
448 for (k = 0; k < s1; k++) {
453 fprintf(stderr,
"Warning: Parameter '%s' does not exist in the input file.\n", Match_string[k]);
457 add_casts(type_string[k], type, parameter_cast, Match_string[k], par_request[i].new_type, index, noWarnings);
459 for (j = 0; j < names; j++) {
463 add_casts(type_string[k], type, parameter_cast, Names[j], par_request[i].new_type, index, noWarnings);
469 for (j = 0; j < s1; j++)
470 free(Match_string[j]);
474 for (j = 0; j < s2; j++)
475 free(type_string[j]);
478 Match_string = type_string = NULL;
480 for (i = 0; i < names; i++)
486 char *ptr, **Names, **Match_string, **type_string;
487 long i, index, j, k, type, s1, s2;
495 Match_string = type_string = NULL;
499 fprintf(stderr,
"Warning: Unable to retrieve array names from the input file.\n");
502 for (i = 0; i < array_requests; i++) {
505 while (ptr != NULL) {
506 Match_string =
SDDS_Realloc(Match_string,
sizeof(
char *) * (s1 + 1));
509 ptr = strtok(NULL,
",");
511 ptr = strtok(array_request[i].type_string,
",");
512 while (ptr != NULL) {
513 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (s2 + 1));
516 ptr = strtok(NULL,
",");
519 for (j = s2; j < s1; j++) {
520 type_string =
SDDS_Realloc(type_string,
sizeof(
char *) * (j + 1));
525 for (k = 0; k < s1; k++) {
530 fprintf(stderr,
"Warning: Array '%s' does not exist in the input file.\n", Match_string[k]);
534 add_casts(type_string[k], type, array_cast, Match_string[k], array_request[i].new_type, index, noWarnings);
536 for (j = 0; j < names; j++) {
540 add_casts(type_string[k], type, array_cast, Names[j], array_request[i].new_type, index, noWarnings);
549 Match_string = type_string = NULL;
551 for (i = 0; i < names; i++)
556long add_casts(
char *old_type,
long sdds_type,
CAST_NAME *cast_name,
char *add_name,
char *new_type,
long index,
long noWarnings) {
561 fprintf(stderr,
"Warning: The type of '%s' is not numeric and cannot be cast to a numeric type.\n", add_name);
564 if (strcmp(old_type,
"*") == 0)
569 if (strcmp(old_type,
"longdouble") == 0)
573 if (strcmp(old_type,
"double") == 0)
577 if (strcmp(old_type,
"float") == 0)
581 if (strcmp(old_type,
"long64") == 0)
585 if (strcmp(old_type,
"ulong64") == 0)
589 if (strcmp(old_type,
"long") == 0)
593 if (strcmp(old_type,
"ulong") == 0)
597 if (strcmp(old_type,
"short") == 0)
601 if (strcmp(old_type,
"ushort") == 0)
610 fprintf(stderr,
"Warning: The type of '%s' does not match '%s'.\n", add_name, old_type);
613 cast_name->name =
SDDS_Realloc(cast_name->name,
sizeof(
char *) * (cast_name->n + 1));
614 cast_name->new_type =
SDDS_Realloc(cast_name->new_type,
sizeof(
char *) * (cast_name->n + 1));
617 cast_name->index =
SDDS_Realloc(cast_name->index,
sizeof(
long) * (cast_name->n + 1));
618 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.