82char *option[N_OPTIONS] = {
95 "Usage: sddsbreak [<inputfile>] [<outputfile>]\n"
96 " [-pipe=[input][,output]]\n"
97 " [-gapin=<column-name>[,{amount=<value>|factor=<value>}]]\n"
98 " [-increaseof=<column-name>[,{amount=<value>}[,cumulative[,reset]]]]\n"
99 " [-decreaseof=<column-name>[,{amount=<value>}[,cumulative[,reset]]]]\n"
100 " [-changeof=<column-name>[,amount=<value>,base=<value>]] \n"
101 " [-matchto=<column-name>,<pattern>[,after]] \n"
102 " [-rowlimit=<integer>[,overlap=<integer>]]\n"
103 " [-pagesPerPage=<integer>]\n"
104 " [-majorOrder=row|column]\n"
106 " -pipe=[input][,output]\n"
107 " Use pipes for input and/or output.\n"
108 " -gapin=<column-name>[,{amount=<value> | factor=<value>}]\n"
109 " Break pages based on gaps in the specified column.\n"
110 " -increaseof=<column-name>[,amount=<value>[,cumulative][,reset]]\n"
111 " Break pages when the specified column increases by a certain amount.\n"
112 " -decreaseof=<column-name>[,amount=<value>[,cumulative][,reset]]\n"
113 " Break pages when the specified column decreases by a certain amount.\n"
114 " -changeof=<column-name>[,amount=<value>,base=<value>]\n"
115 " Break pages based on changes in the specified column relative to a base value.\n"
116 " -matchto=<column-name>,<pattern>[,after]\n"
117 " Break pages when a pattern is matched in the specified column.\n"
118 " -rowlimit=<integer>[,overlap=<integer>]\n"
119 " Limit the number of rows per subpage with an optional overlap.\n"
120 " -pagesPerPage=<integer>\n"
121 " Break each page into the given number of roughly equal-length pages.\n"
122 " -majorOrder=row|column\n"
123 " Specify the major order of data as row-major or column-major.\n"
125 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
127#define GAPIN_AMOUNT 0x0001U
128#define GAPIN_FACTOR 0x0002U
129char *gapinUsage =
"-gapin=<column-name>[,{amount=<value> | factor=<value>}]";
131#define CHANGEOF_AMOUNT 0x0001U
132#define CHANGEOF_BASE 0x0002U
133char *changeofUsage =
"-changeof=<column-name>[,amount=<value>,base=<value>]";
135#define INCREASEOF_AMOUNT 0x0001UL
136#define INCREASEOF_CUMULATIVE 0x0002UL
137#define INCREASEOF_RESET 0x0004UL
138char *increaseOfUsage =
"-increaseOf=<column-name>[,amount=<value>[,cumulative][,reset]]";
140#define DECREASEOF_AMOUNT 0x0001UL
141#define DECREASEOF_CUMULATIVE 0x0002UL
142#define DECREASEOF_RESET 0x0004UL
143char *decreaseOfUsage =
"-decreaseOf=<column-name>[,amount=<value>[,cumulative[,reset]]]";
145#define ROWLIMIT_OVERLAP 0x0001U
147int main(
int argc,
char **argv) {
151 char *input = NULL, *output = NULL, *columnName = NULL;
152 long mode = -1, matchCode, tmpfile_used;
153 int64_t i, j, rows, rowLimit, pagesPerPage=0;
155 double gapAmount = 0, gapFactor = 0, changeAmount, changeBase, *columnData = NULL;
156 char *matchPattern = NULL;
157 long matchPatternAfter = 0;
158 double increaseOfAmount = -1, decreaseOfAmount = -1;
162 unsigned long flags = 0, pipeFlags = 0, changeFlags = 0, decreaseOfFlags = 0, increaseOfFlags = 0;
163 unsigned long majorOrderFlag;
164 char **stringData = NULL;
165 short columnMajorOrder = -1;
168 argc =
scanargs(&scArg, argc, argv);
170 fprintf(stderr,
"%s", USAGE);
174 for (iArg = 1; iArg < argc; iArg++) {
175 if (scArg[iArg].arg_type == OPTION) {
176 switch (matchCode =
match_string(scArg[iArg].list[0], option, N_OPTIONS, 0)) {
177 case SET_MAJOR_ORDER:
179 scArg[iArg].n_items -= 1;
180 if (scArg[iArg].n_items > 0 &&
181 !
scanItemList(&majorOrderFlag, scArg[iArg].list + 1, &scArg[iArg].n_items, 0,
182 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
183 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)) {
184 SDDS_Bomb(
"invalid -majorOrder syntax/values");
186 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
187 columnMajorOrder = 1;
188 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
189 columnMajorOrder = 0;
193 if ((scArg[iArg].n_items -= 2) < 0 ||
194 !
scanItemList(&flags, scArg[iArg].list + 2, &scArg[iArg].n_items, 0,
195 "amount",
SDDS_DOUBLE, &gapAmount, 1, GAPIN_AMOUNT,
196 "factor",
SDDS_DOUBLE, &gapFactor, 1, GAPIN_FACTOR, NULL) ||
197 (flags & GAPIN_AMOUNT && gapAmount <= 0) ||
198 (flags & GAPIN_FACTOR && gapFactor <= 0)) {
199 fprintf(stderr,
"Error: invalid -gapin syntax/values\n");
202 columnName = scArg[iArg].list[1];
208 if (scArg[iArg].n_items < 2) {
209 fprintf(stderr,
"Error: invalid -increaseOf syntax\n");
212 scArg[iArg].n_items -= 2;
213 if (!
scanItemList(&increaseOfFlags, scArg[iArg].list + 2, &scArg[iArg].n_items, 0,
214 "amount",
SDDS_DOUBLE, &increaseOfAmount, 1, INCREASEOF_AMOUNT,
215 "cumulative", -1, NULL, 0, INCREASEOF_CUMULATIVE,
216 "reset", -1, NULL, 0, INCREASEOF_RESET, NULL) ||
217 ((flags & INCREASEOF_AMOUNT) && increaseOfAmount <= 0)) {
218 fprintf(stderr,
"Error: invalid -increaseOf syntax\n");
221 columnName = scArg[iArg].list[1];
227 if (scArg[iArg].n_items < 2) {
228 fprintf(stderr,
"Error: invalid -decreaseOf syntax\n");
231 scArg[iArg].n_items -= 2;
232 if (!
scanItemList(&decreaseOfFlags, scArg[iArg].list + 2, &scArg[iArg].n_items, 0,
233 "amount",
SDDS_DOUBLE, &decreaseOfAmount, 1, DECREASEOF_AMOUNT,
234 "cumulative", -1, NULL, 0, DECREASEOF_CUMULATIVE,
235 "reset", -1, NULL, 0, DECREASEOF_RESET, NULL) ||
236 ((flags & DECREASEOF_AMOUNT) && decreaseOfAmount <= 0)) {
237 fprintf(stderr,
"Error: invalid -decreaseOf syntax\n");
240 columnName = scArg[iArg].list[1];
245 if ((scArg[iArg].n_items -= 2) < 0 ||
246 !
scanItemList(&changeFlags, scArg[iArg].list + 2, &scArg[iArg].n_items, 0,
247 "amount",
SDDS_DOUBLE, &changeAmount, 1, CHANGEOF_AMOUNT,
248 "base",
SDDS_DOUBLE, &changeBase, 1, CHANGEOF_BASE, NULL) ||
249 (changeFlags & CHANGEOF_AMOUNT && changeAmount <= 0)) {
250 fprintf(stderr,
"Error: invalid -changeof syntax/values\n");
253 columnName = scArg[iArg].list[1];
258 if (scArg[iArg].n_items < 2) {
259 fprintf(stderr,
"Error: invalid -rowlimit syntax\n");
262 if (sscanf(scArg[iArg].list[1],
"%" SCNd64, &rowLimit) != 1 || rowLimit <= 0) {
263 fprintf(stderr,
"Error: invalid -rowlimit syntax\n");
266 if (scArg[iArg].n_items > 2) {
267 scArg[iArg].n_items -= 2;
268 if (!
scanItemList(&flags, scArg[iArg].list + 2, &scArg[iArg].n_items, 0,
269 "overlap",
SDDS_LONG, &overlap, 1, ROWLIMIT_OVERLAP, NULL) ||
271 fprintf(stderr,
"Error: invalid overlap given in -rowlimit syntax\n");
279 if (!
processPipeOption(scArg[iArg].list + 1, scArg[iArg].n_items - 1, &pipeFlags)) {
280 fprintf(stderr,
"Error: invalid -pipe syntax\n");
286 if ((scArg[iArg].n_items != 3 && scArg[iArg].n_items != 4) ||
287 strlen(columnName = scArg[iArg].list[1]) == 0 ||
288 strlen(matchPattern = scArg[iArg].list[2]) == 0) {
289 fprintf(stderr,
"Error: invalid -matchTo syntax\n");
292 if (scArg[iArg].n_items == 4) {
293 if (strncmp(scArg[iArg].list[3],
"after", strlen(scArg[iArg].list[3])) == 0)
294 matchPatternAfter = 1;
296 fprintf(stderr,
"Error: invalid -matchTo syntax\n");
303 case SET_PAGES_PER_PAGE:
304 if (scArg[iArg].n_items != 2) {
305 fprintf(stderr,
"Error: invalid -pagesPerPage syntax\n");
308 if (sscanf(scArg[iArg].list[1],
"%" SCNd64, &pagesPerPage) != 1 || pagesPerPage <= 0) {
309 fprintf(stderr,
"Error: invalid -pagesPerPage syntax\n");
316 fprintf(stderr,
"Error: unknown switch: %s\n", scArg[iArg].list[0]);
317 fprintf(stderr,
"%s", USAGE);
322 input = scArg[iArg].list[0];
323 else if (output == NULL)
324 output = scArg[iArg].list[0];
326 fprintf(stderr,
"Error: too many filenames given\n");
332 processFilenames(
"sddsbreak", &input, &output, pipeFlags, 0, &tmpfile_used);
335 fprintf(stderr,
"Error: no break mode specified\n");
345 SDDSnew.layout.data_mode.no_row_counts = 0;
346 if (columnMajorOrder != -1)
347 SDDSnew.layout.data_mode.column_major = columnMajorOrder;
349 SDDSnew.layout.data_mode.column_major = SDDSold.layout.data_mode.column_major;
356 if (mode != SET_ROWLIMIT && mode!=SET_PAGES_PER_PAGE) {
358 SDDS_SetError(
"Problem getting type information on given column");
362 if (mode == SET_MATCHTO) {
364 fprintf(stderr,
"Error: given column does not contain string data\n");
368 if (!(mode == SET_CHANGEOF && !(changeFlags & CHANGEOF_AMOUNT) && !(changeFlags & CHANGEOF_BASE))) {
369 fprintf(stderr,
"Error: given column does not contain numeric data\n");
377 SDDS_SetError(
"Problem getting number of rows of tabular data");
403 if (!gapAmount && rows > 1) {
404 double *gap =
tmalloc(
sizeof(*gap) * rows);
405 for (i = 1; i < rows; i++)
406 gap[i - 1] = fabs(columnData[i] - columnData[i - 1]);
408 fprintf(stderr,
"Error: unable to determine default gap amount--couldn't find median gap\n");
412 gapAmount *= (gapFactor ? gapFactor : 2);
416 int64_t newStart = 0;
417 for (i = 1; i <= rows; i++) {
418 if (i != rows && fabs(columnData[i] - columnData[i - 1]) < gapAmount)
440 int64_t newStart = 0;
441 if (increaseOfAmount <= 0) {
442 for (i = 1; i <= rows; i++) {
443 if (i != rows && columnData[i] <= columnData[i - 1])
454 if (increaseOfFlags & INCREASEOF_CUMULATIVE) {
456 for (i = 1; i <= rows; i++) {
457 if ((increaseOfFlags & INCREASEOF_RESET) && columnData[i] < columnData[iref])
459 if (i != rows && (columnData[i] - columnData[iref]) < increaseOfAmount)
468 if (increaseOfFlags & INCREASEOF_CUMULATIVE)
472 for (i = 1; i <= rows; i++) {
473 if (i != rows && (columnData[i] - columnData[i - 1]) < increaseOfAmount)
497 int64_t newStart = 0;
498 if (decreaseOfAmount <= 0) {
499 for (i = 1; i <= rows; i++) {
500 if (i != rows && columnData[i] >= columnData[i - 1])
511 if (decreaseOfFlags & DECREASEOF_CUMULATIVE) {
513 for (i = 1; i <= rows; i++) {
514 if ((decreaseOfFlags & DECREASEOF_RESET) && columnData[i] > columnData[iref])
516 if (i != rows && (columnData[iref] - columnData[i]) < decreaseOfAmount)
525 if (decreaseOfFlags & DECREASEOF_CUMULATIVE)
529 for (i = 1; i <= rows; i++) {
530 if (i != rows && (columnData[i - 1] - columnData[i]) < decreaseOfAmount)
563 int64_t newStart = 0;
565 for (i = 1; i <= rows; i++) {
567 ((dataType ==
SDDS_STRING && strcmp(stringData[i], stringData[i - 1]) == 0) ||
568 (dataType !=
SDDS_STRING && columnData[i] == columnData[i - 1])))
582 long region = 0, lastRegion = 0;
583 if (!(changeFlags & CHANGEOF_BASE) && rows >= 1)
584 changeBase = columnData[0];
586 lastRegion = (columnData[0] - changeBase) / changeAmount;
589 for (i = 1; i <= rows; i++) {
591 region = (columnData[i] - changeBase) / changeAmount;
592 if (i != rows && region == lastRegion)
622 int64_t newStart = 0;
624 for (i = 1; i <= rows; i++) {
625 if (i != rows && !breakNext) {
626 if (
wild_match(stringData[i], matchPattern)) {
627 if (matchPatternAfter) {
649 for (i = 0; i < rows; i += rowLimit - overlap) {
650 if ((j = i + rowLimit - 1) >= rows)
665 case SET_PAGES_PER_PAGE:
666 rowLimit = rows/pagesPerPage;
667 for (j=0; j<pagesPerPage; j++) {
668 int64_t iStart, iEnd;
670 iEnd = j==(pagesPerPage-1)? rows-1 : (j+1)*rowLimit-1;
683 fprintf(stderr,
"Error: unknown break mode code seen---this can't happen\n");
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_CopyRows(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, int64_t firstRow, int64_t lastRow)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in 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.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
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.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit 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.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
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)
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 wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.