SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddssequence.c File Reference

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.

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

Required Description
-define Define a column with the given name and its entries.
-sequence Specify a sequence with flexible parameters (start, end, delta, interval).
Optional Description
-pipe Define pipe output options.
-repeat Repeat the sequence a specified number of times.
-break Insert a page break between repeats.
-majorOrder Specify the major order for data storage (row or column).

Incompatibilities

  • -break requires -repeat=<number>.
  • -sequence parameters must conform to one of these combinations:
    • end and delta
    • end and number
    • delta and number
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
  • M. Borland
  • C. Saunders
  • L. Emery
  • R. Soliday
  • H. Shang

Definition in file sddssequence.c.

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

Go to the source code of this file.

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)
 

Function Documentation

◆ addDefinition()

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

Definition at line 251 of file sddssequence.c.

251 {
252 if (items < 1) {
253 SDDS_Bomb("unable to add definition--supply column name");
254 }
255 *definition = SDDS_Realloc(*definition, sizeof(**definition) * (*definitions + 1));
256 if (!(*definition)) {
257 SDDS_Bomb("unable to add definition---allocation failure");
258 }
259
260 (*definition)[*definitions].columnName = item[0];
261 (*definition)[*definitions].item = item + 1;
262 (*definition)[*definitions].items = items - 1;
263 (*definition)[*definitions].sequence = NULL;
264 (*definition)[*definitions].sequences = 0;
265 (*definition)[*definitions].rows = 0;
266 (*definition)[*definitions].data = NULL;
267 (*definition)[*definitions].repeats = 1;
268 (*definitions)++;
269}
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 271 of file sddssequence.c.

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

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

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

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

413 {
414 long i;
415
416 if (!SDDS_InitializeOutput(outputTable, SDDS_BINARY, 0, NULL, "sddssequence output", output)) {
417 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
418 }
419
420 for (i = 0; i < definitions; i++) {
421 createColumn(outputTable, &definition[i]);
422 }
423
424 outputTable->layout.data_mode.column_major = columnMajorOrder;
425 if (!SDDS_WriteLayout(outputTable)) {
426 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
427 }
428}
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.