SDDSlib
Loading...
Searching...
No Matches
sddsendian.c
Go to the documentation of this file.
1/**
2 * @file sddsendian.c
3 * @brief Converts between big-endian and little-endian formats for SDDS files.
4 *
5 * This program processes Self-Describing Data Sets (SDDS) to convert data
6 * between big-endian and little-endian byte orders. It supports both binary
7 * and ASCII SDDS files and provides options for handling data piping and
8 * specifying row or column major order.
9 *
10 * ### Features
11 * - Converts data between big-endian and little-endian formats.
12 * - Handles non-native byte order files with the `-nonNative` option.
13 * - Supports data piping with the `-pipe` option.
14 * - Allows specification of row or column major order using `-majorOrder`.
15 *
16 * ### Usage
17 * ```
18 * sddsendian [options] <input> <output>
19 * ```
20 * Options:
21 * - `-pipe=[input][,output]` Use pipe for input and/or output.
22 * - `-majorOrder=row|column` Set the major order to row or column.
23 * - `-nonNative` Handle non-native byte order files.
24 *
25 * @copyright
26 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
27 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
28 *
29 * @license
30 * This file is distributed under the terms of the Software License Agreement
31 * found in the file LICENSE included with this distribution.
32 *
33 * @author M. Borland, R. Soliday, H. Shang
34 */
35
36#include "mdb.h"
37#include "SDDS.h"
38#include "scan.h"
39
40/** Enumeration for supported command-line options */
41typedef enum {
42 SET_PIPE = 0,
43 NONNATIVE = 1,
44 SET_MAJOR_ORDER = 2
46
47#define N_OPTIONS 3
48
49/** Array of option names corresponding to the `OptionType` enum */
50char *option[N_OPTIONS] =
51 {
52 "pipe",
53 "nonNative",
54 "majorOrder",
55 };
56
57/** Usage string displayed for the program */
58char *USAGE = "Usage: sddsendian [options] <input> <output>\n\
59\nOptions:\n\
60 -pipe=[input][,output] Use pipe for input and/or output.\n\
61 -majorOrder=row|column Set the major order to row or column.\n\
62 -nonNative Handle non-native byte order files.\n\
63\nDescription:\n\
64 Converts between big-endian and little-endian formats.\n\
65 This program is designed to handle Self-Describing Data Sets (SDDS)\n\
66 efficiently, allowing for platform-independent data sharing.\n\
67\nAuthors:\n\
68 Michael Borland and Robert Soliday\n\
69\nVersion:\n\
70 Link date: " __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION "\n";
71
72int main(int argc, char **argv) {
73 SDDS_DATASET SDDSin, SDDSout;
74 long i_arg, tmpfile_used;
75 SCANNED_ARG *s_arg;
76 char *input, *output, *description_text, *description_contents;
77 unsigned long pipe_flags, major_order_flag;
78 long page_number, non_native = 0;
79 char *output_endianess = NULL;
80 char buffer[40];
81 short column_major_order = -1;
82
83 // Register the program name for SDDS utilities
85
86 // Parse command-line arguments
87 argc = scanargs(&s_arg, argc, argv);
88 if (argc < 2) // Ensure at least one argument is provided
89 bomb(NULL, USAGE);
90
91 // Initialize variables for input/output files and options
92 input = output = description_text = description_contents = NULL;
93 pipe_flags = 0;
94
95 // Process each command-line argument
96 for (i_arg = 1; i_arg < argc; i_arg++) {
97 if (s_arg[i_arg].arg_type == OPTION) {
98 delete_chars(s_arg[i_arg].list[0], "_"); // Normalize option string
99 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
100 case SET_MAJOR_ORDER:
101 major_order_flag = 0;
102 s_arg[i_arg].n_items--;
103 // Parse major order option
104 if (s_arg[i_arg].n_items > 0 && (!scanItemList(&major_order_flag, s_arg[i_arg].list + 1,
105 &s_arg[i_arg].n_items, 0, "row", -1, NULL, 0,
106 SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0,
107 SDDS_COLUMN_MAJOR_ORDER, NULL)))
108 SDDS_Bomb("invalid -majorOrder syntax/values");
109 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER)
110 column_major_order = 1; // Set column major order
111 else if (major_order_flag & SDDS_ROW_MAJOR_ORDER)
112 column_major_order = 0; // Set row major order
113 break;
114 case SET_PIPE:
115 // Parse pipe option
116 if (!processPipeOption(s_arg[i_arg].list + 1,
117 s_arg[i_arg].n_items - 1, &pipe_flags))
118 SDDS_Bomb("invalid -pipe syntax");
119 break;
120 case NONNATIVE:
121 non_native = 1; // Enable non-native byte order handling
122 break;
123 default:
124 // Handle unknown options
125 fprintf(stderr, "Error (%s): unknown switch: %s\n", argv[0],
126 s_arg[i_arg].list[0]);
127 exit(1);
128 break;
129 }
130 } else {
131 // Assign input and output filenames
132 if (input == NULL)
133 input = s_arg[i_arg].list[0];
134 else if (output == NULL)
135 output = s_arg[i_arg].list[0];
136 else
137 SDDS_Bomb("too many filenames");
138 }
139 }
140
141 // Process filenames and handle temporary files
142 processFilenames("sddsendian", &input, &output, pipe_flags, 0,
143 &tmpfile_used);
144
145 // Check and clear output endianess environment variable
146 output_endianess = getenv("SDDS_OUTPUT_ENDIANESS");
147
148 if (output_endianess) {
149 putenv("SDDS_OUTPUT_ENDIANESS=");
150 }
151
152 // Initialize the input SDDS dataset
153 if (!SDDS_InitializeInput(&SDDSin, input)) {
154 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
155 exit(1);
156 }
157
158 // Retrieve description text if available
159 if (!description_text)
160 SDDS_GetDescription(&SDDSin, &description_text, &description_contents);
161
162 // Initialize the output SDDS dataset and set data mode
163 if (!SDDS_InitializeCopy(&SDDSout, &SDDSin, output, "w") || !SDDS_SetDataMode(&SDDSout, non_native ? SDDS_BINARY : -SDDS_BINARY)) {
164 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
165 exit(1);
166 }
167
168 // Set column/row major order based on parsed options
169 if (column_major_order != -1)
170 SDDSout.layout.data_mode.column_major = column_major_order;
171 else
172 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
173
174 // Write the layout of the output file
175 if (!SDDS_WriteLayout(&SDDSout)) {
176 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
177 exit(1);
178 }
179
180 // Process pages in the input file and write to the output file
181 if (non_native) {
182 while ((page_number = SDDS_ReadNonNativePage(&SDDSin)) >= 0) {
183 if (!SDDS_CopyPage(&SDDSout, &SDDSin) || !SDDS_WritePage(&SDDSout)) {
184 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
185 exit(1);
186 }
187 }
188 } else {
189 while ((page_number = SDDS_ReadPage(&SDDSin)) >= 0) {
190 if (!SDDS_CopyPage(&SDDSout, &SDDSin) || !SDDS_WriteNonNativeBinaryPage(&SDDSout)) {
191 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
192 exit(1);
193 }
194 }
195 }
196
197 // Terminate the input and output datasets
198 if (!SDDS_Terminate(&SDDSin) || !SDDS_Terminate(&SDDSout)) {
199 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
200 exit(1);
201 }
202
203 // Replace temporary files if necessary
204 if (tmpfile_used && !replaceFileAndBackUp(input, output))
205 exit(1);
206
207 // Restore output endianess environment variable if it was set
208 if (output_endianess) {
209 sprintf(buffer, "SDDS_OUTPUT_ENDIANESS=%s", output_endianess);
210 putenv(buffer);
211 }
212
213 return 0; // Return success
214}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_WriteNonNativeBinaryPage(SDDS_DATASET *SDDS_dataset)
Writes a non-native endian binary page to an SDDS dataset.
int32_t SDDS_ReadNonNativePage(SDDS_DATASET *SDDS_dataset)
Reads a non-native endian page from an SDDS dataset.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
int32_t SDDS_GetDescription(SDDS_DATASET *SDDS_dataset, char **text, char **contents)
Retrieves the text and contents descriptions from an SDDS dataset.
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *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_SetDataMode(SDDS_DATASET *SDDS_dataset, int32_t newmode)
Sets the data mode (ASCII or Binary) for the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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.
Definition replacefile.c:75
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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.
char * option[N_OPTIONS]
Definition sddsendian.c:50
OptionType
Definition sddsendian.c:41
char * USAGE
Definition sddsendian.c:58