SDDSlib
Loading...
Searching...
No Matches
sddssequence.c File Reference

Generates an SDDS file with equispaced indices in a column. More...

#include <stdlib.h>
#include "mdb.h"
#include "SDDS.h"
#include "scan.h"

Go to the source code of this file.

Classes

struct  SEQUENCE
 
struct  DEFINITION
 

Macros

#define SEQ_END_GIVEN   0x0001
 
#define SEQ_BEGIN_GIVEN   0x0002
 
#define SEQ_NUMBER_GIVEN   0x0004
 
#define SEQ_DELTA_GIVEN   0x0008
 
#define SEQ_INTERVAL_GIVEN   0x0010
 
#define SEQ_ENDplusDELTA   (SEQ_END_GIVEN + SEQ_DELTA_GIVEN)
 
#define SEQ_ENDplusNUMBER   (SEQ_END_GIVEN + SEQ_NUMBER_GIVEN)
 
#define SEQ_DELTAplusNUMBER   (SEQ_DELTA_GIVEN + SEQ_NUMBER_GIVEN)
 

Enumerations

enum  option_type {
  SET_PIPE , SET_DEFINE , SET_SEQUENCE , SET_REPEAT ,
  SET_MAJOR_ORDER , SET_BREAK , N_OPTIONS
}
 

Functions

void addSequence (char **item, long items, DEFINITION *definition)
 
void addDefinition (char **item, long items, DEFINITION **definition, long *definitions)
 
void generateOutput (SDDS_DATASET *outputTable, DEFINITION *definition, long definitions, long doBreak)
 
void setupOutputFile (SDDS_DATASET *outputTable, char *output, DEFINITION *definition, long definitions, short columnMajorOrder)
 
void createColumn (SDDS_DATASET *outputTable, DEFINITION *definition)
 
int main (int argc, char **argv)
 

Variables

char * option [N_OPTIONS]
 
static char * USAGE
 

Detailed Description

Generates an SDDS file with equispaced indices in a column.

This program creates an SDDS file containing a single page with one or more columns of data. The columns can be defined, and sequences of values can be generated using user-specified parameters. Multiple sequences, repeats, and page breaks are supported.

Key Features:

  • Define columns using the -define option.
  • Generate sequences with the -sequence option, specifying start, end, delta, and interval values.
  • Repeat data sequences with the -repeat option.
  • Insert page breaks between repeats with the -break option.
  • Support row-major and column-major order for data storage with the -majorOrder option.

Usage:

sddssequence [<outputfile>] \
[-pipe=<output>] \
-define=<columnName>[,<definitionEntries>] \
[-repeat=<number>] \
[-break] \
-sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] \
[-sequence=...] [-majorOrder=row|column]
  • Options:
    • -define: Define columns and their attributes.
    • -sequence: Specify sequences of data with flexible parameters.
    • -repeat: Repeat sequences a specified number of times.
    • -break: Insert page breaks between repeats.
    • -majorOrder: Choose between row-major or column-major data storage.
  • Example:
    sddssequence output.sdds -define=x -sequence=begin=0,delta=1,number=10
    Generates a file output.sdds with a column x containing values 0 to 9.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, L. Emery, R. Soliday, H. Shang

Definition in file sddssequence.c.

Macro Definition Documentation

◆ SEQ_BEGIN_GIVEN

#define SEQ_BEGIN_GIVEN   0x0002

Definition at line 105 of file sddssequence.c.

◆ SEQ_DELTA_GIVEN

#define SEQ_DELTA_GIVEN   0x0008

Definition at line 107 of file sddssequence.c.

◆ SEQ_DELTAplusNUMBER

#define SEQ_DELTAplusNUMBER   (SEQ_DELTA_GIVEN + SEQ_NUMBER_GIVEN)

Definition at line 113 of file sddssequence.c.

◆ SEQ_END_GIVEN

#define SEQ_END_GIVEN   0x0001

Definition at line 104 of file sddssequence.c.

◆ SEQ_ENDplusDELTA

#define SEQ_ENDplusDELTA   (SEQ_END_GIVEN + SEQ_DELTA_GIVEN)

Definition at line 111 of file sddssequence.c.

◆ SEQ_ENDplusNUMBER

#define SEQ_ENDplusNUMBER   (SEQ_END_GIVEN + SEQ_NUMBER_GIVEN)

Definition at line 112 of file sddssequence.c.

◆ SEQ_INTERVAL_GIVEN

#define SEQ_INTERVAL_GIVEN   0x0010

Definition at line 108 of file sddssequence.c.

◆ SEQ_NUMBER_GIVEN

#define SEQ_NUMBER_GIVEN   0x0004

Definition at line 106 of file sddssequence.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 58 of file sddssequence.c.

58 {
59 SET_PIPE,
60 SET_DEFINE,
61 SET_SEQUENCE,
62 SET_REPEAT,
63 SET_MAJOR_ORDER,
64 SET_BREAK,
65 N_OPTIONS
66};

Function Documentation

◆ addDefinition()

void addDefinition ( char ** item,
long items,
DEFINITION ** definition,
long * definitions )

Definition at line 247 of file sddssequence.c.

247 {
248 if (items < 1) {
249 SDDS_Bomb("unable to add definition--supply column name");
250 }
251 *definition = SDDS_Realloc(*definition, sizeof(**definition) * (*definitions + 1));
252 if (!(*definition)) {
253 SDDS_Bomb("unable to add definition---allocation failure");
254 }
255
256 (*definition)[*definitions].columnName = item[0];
257 (*definition)[*definitions].item = item + 1;
258 (*definition)[*definitions].items = items - 1;
259 (*definition)[*definitions].sequence = NULL;
260 (*definition)[*definitions].sequences = 0;
261 (*definition)[*definitions].rows = 0;
262 (*definition)[*definitions].data = NULL;
263 (*definition)[*definitions].repeats = 1;
264 (*definitions)++;
265}
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677

◆ addSequence()

void addSequence ( char ** item,
long items,
DEFINITION * definition )

Definition at line 267 of file sddssequence.c.

267 {
268 SEQUENCE *sequence;
269 long i;
270
271 definition->sequence = SDDS_Realloc(definition->sequence, sizeof(*definition->sequence) * (definition->sequences + 1));
272 if (!definition->sequence) {
273 SDDS_Bomb("unable to add sequence--memory allocation failure");
274 }
275
276 sequence = &definition->sequence[definition->sequences];
277 sequence->interval = 1;
278
279 if (!scanItemList(&sequence->flags, item, &items, 0,
280 "begin", SDDS_DOUBLE, &sequence->begin, 1, SEQ_BEGIN_GIVEN,
281 "end", SDDS_DOUBLE, &sequence->end, 1, SEQ_END_GIVEN,
282 "number", SDDS_LONG64, &sequence->number, 1, SEQ_NUMBER_GIVEN,
283 "delta", SDDS_DOUBLE, &sequence->delta, 1, SEQ_DELTA_GIVEN,
284 "interval", SDDS_LONG64, &sequence->interval, 1, SEQ_INTERVAL_GIVEN,
285 NULL)) {
286 SDDS_Bomb("invalid -sequence syntax");
287 }
288
289 if ((sequence->flags & SEQ_NUMBER_GIVEN) && sequence->number <= 0) {
290 SDDS_Bomb("number <= 0 is not valid for -sequence");
291 }
292
293 if ((sequence->flags & SEQ_DELTA_GIVEN) && sequence->delta == 0) {
294 SDDS_Bomb("delta == 0 is not valid for -sequence");
295 }
296
297 if (!(sequence->flags & SEQ_BEGIN_GIVEN)) {
298 if (definition->sequences == 0) {
299 SDDS_Bomb("you must give begin point for the first sequence of a definition");
300 }
301 if (!(sequence->flags & SEQ_DELTA_GIVEN)) {
302 SDDS_Bomb("you must give delta with implied begin point");
303 }
304 sequence->begin = definition->sequence[definition->sequences - 1].end + sequence->delta;
305 }
306
307 if ((sequence->flags & SEQ_INTERVAL_GIVEN) && sequence->interval <= 0) {
308 SDDS_Bomb("interval for sequence must be > 0");
309 }
310
311 if ((sequence->flags & SEQ_ENDplusDELTA) == SEQ_ENDplusDELTA) {
312 sequence->number = ((long)((sequence->end - sequence->begin) / sequence->delta + 1.5)) * sequence->interval;
313 if (sequence->number <= 0) {
314 SDDS_Bomb("given (start, end, delta) implies number of points <= 0");
315 }
316 } else if ((sequence->flags & SEQ_ENDplusNUMBER) == SEQ_ENDplusNUMBER) {
317 if (sequence->number == 1) {
318 sequence->delta = 0;
319 } else {
320 sequence->delta = (sequence->end - sequence->begin) / (sequence->number - 1) * sequence->interval;
321 }
322 } else if ((sequence->flags & SEQ_DELTAplusNUMBER) == SEQ_DELTAplusNUMBER) {
323 sequence->end = (sequence->delta / sequence->interval) * (sequence->number - 1) + sequence->begin;
324 } else {
325 SDDS_Bomb("you must supply (end, delta), (end, number), or (delta, number)");
326 }
327
328 definition->data = SDDS_Realloc(definition->data, sizeof(*definition->data) * (definition->rows + sequence->number));
329 if (!definition->data) {
330 SDDS_Bomb("unable to generate sequence data--allocation failure");
331 }
332
333 for (i = 0; i < sequence->number; i++) {
334 definition->data[definition->rows + i] = sequence->begin + (i / sequence->interval) * sequence->delta;
335 }
336
337 definition->rows += sequence->number;
338 definition->sequences++;
339}
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
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.

◆ createColumn()

void createColumn ( SDDS_DATASET * outputTable,
DEFINITION * definition )

Definition at line 426 of file sddssequence.c.

426 {
427 char s[SDDS_MAXLINE];
428 char *ptr;
429 long i;
430
431 if (!definition->columnName) {
432 SDDS_Bomb("column name is null");
433 }
434 if (SDDS_GetColumnIndex(outputTable, definition->columnName) >= 0) {
435 SDDS_Bomb("column name already exists (sddssequence)");
436 }
437
438 /* Initialize the column definition string */
439 snprintf(s, sizeof(s), "&column name=%s, ", definition->columnName);
440
441 for (i = 0; i < definition->items; i++) {
442 ptr = strchr(definition->item[i], '=');
443 if (!ptr) {
444 fprintf(stderr, "error: invalid definition-entry: %s\n", definition->item[i]);
445 exit(EXIT_FAILURE);
446 }
447 *ptr = '\0';
448 strcat(s, definition->item[i]);
449 strcat(s, "=\"");
450 strcat(s, ptr + 1);
451 strcat(s, "\", ");
452 }
453
454 /* Ensure type is specified, default to double if not */
455 if (!strstr(s, ", type=")) {
456 strcat(s, " type=\"double\", ");
457 }
458
459 strcat(s, "&end");
460
461 if (!SDDS_ProcessColumnString(outputTable, s, 0)) {
462 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
463 }
464}
int32_t SDDS_ProcessColumnString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode)
Process a column definition string.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in 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

◆ generateOutput()

void generateOutput ( SDDS_DATASET * outputTable,
DEFINITION * definition,
long definitions,
long doBreak )

Definition at line 341 of file sddssequence.c.

341 {
342 long idef, row, rows = 0, totalRows = 0;
343
344 if (!doBreak) {
345 for (idef = 0; idef < definitions; idef++) {
346 totalRows = definition[idef].rows * definition[idef].repeats;
347 if (idef && totalRows != rows) {
348 fputs("warning: sequences are of different length (sddssequence)\n", stderr);
349 }
350 if (totalRows > rows) {
351 rows = totalRows;
352 }
353 }
354
355 if (rows == 0) {
356 SDDS_Bomb("total number of points in sequence is zero");
357 }
358
359 if (!SDDS_StartPage(outputTable, rows)) {
360 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
361 }
362
363 for (idef = 0; idef < definitions; idef++) {
364 if (definition[idef].rows != totalRows) {
365 /* repeats are carried out here */
366 definition[idef].data = SDDS_Realloc(definition[idef].data, sizeof(*definition[idef].data) * rows);
367 if (!definition[idef].data) {
368 SDDS_Bomb("unable to generate output--allocation failure");
369 }
370 for (row = definition[idef].rows; row < rows; row++) {
371 definition[idef].data[row] = definition[idef].data[row % definition[idef].rows];
372 }
373 }
374 if (!SDDS_SetColumnFromDoubles(outputTable, SDDS_BY_NAME, definition[idef].data, rows, definition[idef].columnName)) {
375 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
376 }
377 }
378
379 if (!SDDS_WritePage(outputTable)) {
380 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
381 }
382 } else {
383 long irep;
384 rows = definition[0].rows;
385 if (rows == 0) {
386 SDDS_Bomb("number of points in sequence is zero");
387 }
388 for (idef = 1; idef < definitions; idef++) {
389 if (rows != definition[idef].rows) {
390 fputs("warning: sequences are of different length (sddssequence)\n", stderr);
391 }
392 }
393 for (irep = 0; irep < definition[0].repeats; irep++) {
394 if (!SDDS_StartPage(outputTable, rows)) {
395 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
396 }
397 for (idef = 0; idef < definitions; idef++) {
398 if (!SDDS_SetColumnFromDoubles(outputTable, SDDS_BY_NAME, definition[idef].data, rows, definition[idef].columnName)) {
399 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
400 }
401 }
402 if (!SDDS_WritePage(outputTable)) {
403 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
404 }
405 }
406 }
407}
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.

◆ main()

int main ( int argc,
char ** argv )

Definition at line 138 of file sddssequence.c.

138 {
139 SDDS_DATASET outputTable;
140 SCANNED_ARG *s_arg;
141 long i_arg, i;
142 DEFINITION *definition = NULL;
143 long definitions = 0;
144 long doBreak = 0;
145
146 char *output = NULL;
147 unsigned long pipeFlags = 0, majorOrderFlag;
148 short columnMajorOrder = 0;
149
151 argc = scanargs(&s_arg, argc, argv);
152 if (argc < 2) {
153 bomb(NULL, USAGE);
154 }
155
156 for (i_arg = 1; i_arg < argc; i_arg++) {
157 if (s_arg[i_arg].arg_type == OPTION) {
158 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
159 case SET_MAJOR_ORDER:
160 majorOrderFlag = 0;
161 s_arg[i_arg].n_items--;
162 if (s_arg[i_arg].n_items > 0 &&
163 !scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
164 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
165 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
166 SDDS_Bomb("invalid -majorOrder syntax/values");
167 }
168 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER) {
169 columnMajorOrder = 1;
170 } else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER) {
171 columnMajorOrder = 0;
172 }
173 break;
174
175 case SET_DEFINE:
176 addDefinition(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &definition, &definitions);
177 break;
178
179 case SET_REPEAT:
180 if (definitions == 0) {
181 SDDS_Bomb("can't give a repeat specifier prior to a definition");
182 }
183 if (s_arg[i_arg].n_items != 2 ||
184 sscanf(s_arg[i_arg].list[1], "%ld", &definition[definitions - 1].repeats) != 1 ||
185 definition[definitions - 1].repeats <= 0) {
186 SDDS_Bomb("invalid -repeat syntax/value");
187 }
188 break;
189
190 case SET_BREAK:
191 doBreak = 1;
192 break;
193
194 case SET_SEQUENCE:
195 if (definitions == 0) {
196 SDDS_Bomb("can't create a sequence prior to defining the variable");
197 }
198 addSequence(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, definition + definitions - 1);
199 break;
200
201 case SET_PIPE:
202 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
203 SDDS_Bomb("invalid -pipe syntax");
204 }
205 break;
206
207 default:
208 fprintf(stderr, "error: unknown/ambiguous option: %s\n", s_arg[i_arg].list[0]);
209 exit(EXIT_FAILURE);
210 break;
211 }
212 } else {
213 if (output == NULL) {
214 output = s_arg[i_arg].list[0];
215 } else {
216 SDDS_Bomb("too many filenames");
217 }
218 }
219 }
220
221 if (output == NULL && !(pipeFlags & USE_STDOUT)) {
222 SDDS_Bomb("no output specified");
223 }
224
225 if (!definitions) {
226 SDDS_Bomb("no sequences defined");
227 }
228
229 setupOutputFile(&outputTable, output, definition, definitions, columnMajorOrder);
230 generateOutput(&outputTable, definition, definitions, doBreak);
231
232 if (!SDDS_Terminate(&outputTable)) {
233 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
234 exit(EXIT_FAILURE);
235 }
236
237 for (i = 0; i < definitions; i++) {
238 free(definition[i].sequence);
239 free(definition[i].data);
240 }
241 free(definition);
242 free_scanargs(&s_arg, argc);
243
244 return EXIT_SUCCESS;
245}
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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.
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 free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584

◆ setupOutputFile()

void setupOutputFile ( SDDS_DATASET * outputTable,
char * output,
DEFINITION * definition,
long definitions,
short columnMajorOrder )

Definition at line 409 of file sddssequence.c.

409 {
410 long i;
411
412 if (!SDDS_InitializeOutput(outputTable, SDDS_BINARY, 0, NULL, "sddssequence output", output)) {
413 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
414 }
415
416 for (i = 0; i < definitions; i++) {
417 createColumn(outputTable, &definition[i]);
418 }
419
420 outputTable->layout.data_mode.column_major = columnMajorOrder;
421 if (!SDDS_WriteLayout(outputTable)) {
422 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
423 }
424}
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.

Variable Documentation

◆ option

char* option[N_OPTIONS]
Initial value:
= {
"pipe",
"define",
"sequence",
"repeat",
"majorOrder",
"break",
}

Definition at line 68 of file sddssequence.c.

68 {
69 "pipe",
70 "define",
71 "sequence",
72 "repeat",
73 "majorOrder",
74 "break",
75};

◆ USAGE

char* USAGE
static
Initial value:
=
"Usage: sddssequence [<outputfile>] \\\n"
" [-pipe=<output>] \\\n"
" -define=<columnName>[,<definitionEntries>] \\\n"
" [-repeat=<number>] \\\n"
" [-break] \\\n"
" -sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] \\\n"
" [-sequence=begin=<value>[,number=<integer>][,end=<value>][,delta=<value>][,interval=<integer>] ...] \\\n"
" [-majorOrder=row|column]\n\n"
"Generates an SDDS file with a single page and several columns of data.\n"
"Options:\n"
" <outputfile> Specify the output SDDS file. If omitted, standard output is used.\n"
" -pipe=<output> Define pipe output options.\n"
" -define=<columnName>,<entries> Define a column with the given name and entries.\n"
" -repeat=<number> Repeat the sequence the specified number of times.\n"
" -break Insert a page break between repeats.\n"
" -sequence=begin=<val>,number=<n>,end=<val>,delta=<val>,interval=<n>\n"
" Define a sequence with specified parameters. Multiple -sequence options can be used.\n"
" -majorOrder=row|column Set the major order of data storage.\n\n"
"Notes:\n"
" - The default data type is double. To specify a different type, use type=<typeName> in -define.\n"
" - Each column is specified with a -define option followed by any number of -sequence options.\n"
" - The default value of delta is 1.\n"
" - The default beginning value is the ending value of the last sequence plus the delta of the last sequence.\n\n"
"Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"

Definition at line 78 of file sddssequence.c.