Changeset 42408 for trunk/Ohana/src/opihi/cmd.data
- Timestamp:
- Mar 10, 2023, 4:03:44 PM (3 years ago)
- File:
-
- 1 edited
-
trunk/Ohana/src/opihi/cmd.data/queue2book.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/opihi/cmd.data/queue2book.c
r41341 r42408 1 1 # include "pantasks.h" 2 2 3 # define FREEKEYS \4 if (keys) { for (i = 0; i < Nkeys; i++) { free (keys[i]); } free (keys); } \5 for (i = 0; i < setWordN; i++) { free (setWordList[i]); free (setWordValue[i]); } \3 # define FREEKEYS \ 4 if (keys) { for (int ix = 0; ix < Nkeys; ix++) { free (keys[ix]); } free (keys); } \ 5 for (int ix = 0; ix < setWordN; ix++) { free (setWordList[ix]); free (setWordValue[ix]); } \ 6 6 free (setWordValue); free (setWordList); 7 7 8 // convert the named queue with ipptool metadata output into book format 8 // USAGE: queue2book (queue) (book) 9 // convert the named queue into book format 10 // the output book will use the name supplied as the second argument 11 // the input queue should either use the ippTools metadata format OR 12 // the input queue should consist of a set of lines with white-space 13 // separated columns of data. 14 15 // **** MD format **** 16 // In MD format, the queue starts with a line of the form "BOOKNAME MULTI" 17 // following this, there will be a series of METADATA blocks. the 18 // value BOOKNAME in the first line much match the names of the METADATA blocks 19 // note that the BOOKNAME is not actually used to set the output book name, 20 // and is not required to have any specific value other than matching the 21 // following METADATA blocks. 22 23 // the METADATA blocks are used to create pages within the book (one page per block) 24 // the key / value pairs within the METADATA blocks are used to set the values 25 // words within each page. 26 27 // option: -key (word[:word[:word..]]) 28 // pages are given names of the form 'page.NNN' unless -key options are supplied. 29 // if one or more -key options are supplied, the value of the associated word is used 30 // to set the pagename. If multiple keys are supplied, the words are joined with colons. 31 32 // option: -uniq 33 // if -uniq is supplied, any new pages which match existing pages will be dropped / ignored 34 35 // option: -setword 36 // additional words may be added to the pages of the book when they are created. 37 38 // **** Raw Column format **** 39 40 // In Raw Column format, each line in the queue is converted to a new page. The white-space separated 41 // words in each line are interpretted as the values of words on this page. The names of these 42 // columns (words) are specified on the first line of the queue. Thus a valid input must consist of 43 // at least two lines. 44 45 // we need these in both parsing blocks 46 int Unique; 47 int RawColumns; 48 49 char **setWordList; 50 char **setWordValue; 51 int setWordN; 52 53 int Nkeys; 54 char **keys; 55 56 int queue2book_rawcolumns (Queue *queue, Book *book); 57 int queue2book_setpages (Book *book, Page *page); 58 int queue2book_addwords (Book *book, Page *page); 59 int queue2book_uniquify (Book *book, Page *page); 60 9 61 int queue2book (int argc, char **argv) { 10 62 11 int i, N, onPage, found, Unique, Nkeys, NKEYS;63 int N, onPage; 12 64 char *line, *tmpword, *tmpvalue; 13 65 char pagename[512]; // XXX this should be made dynamic, though it is an unlikey problem 14 char *bookName, **keys, *p, *q;15 char **setWordList;16 char **setWordValue;17 int setWordN, setWordNalloc;18 19 Page *page = NULL;20 Book *book = NULL;21 Queue *queue = NULL;22 66 23 67 /* supply additional constant words */ 24 68 setWordN = 0; 25 setWordNalloc = 10;69 int setWordNalloc = 10; 26 70 ALLOCATE (setWordList, char *, setWordNalloc); 27 71 ALLOCATE (setWordValue, char *, setWordNalloc); … … 46 90 } 47 91 92 RawColumns = FALSE; 93 if ((N = get_argument (argc, argv, "-raw-columns"))) { 94 remove_argument (N, &argc, argv); 95 RawColumns = TRUE; 96 } 97 98 // keys are used to define the page names (otherwise page.NNN is used) 48 99 Nkeys = 0; 49 keys = NULL;100 keys = NULL; 50 101 if ((N = get_argument (argc, argv, "-key"))) { 51 102 remove_argument (N, &argc, argv); 52 103 53 104 /* parse the key (word:word:word) into constituents */ 54 NKEYS = 10;105 int NKEYS = 10; 55 106 ALLOCATE (keys, char *, NKEYS); 56 107 57 p = q = argv[N]; 108 char *p = argv[N]; 109 char *q = p; 58 110 while (q != NULL) { 59 111 q = strchr (p, ':'); … … 67 119 68 120 if (argc != 3) { 69 gprint (GP_ERR, "USAGE: queue2book (queue) (book) [-uniq] [-key key[:key..]] \n");121 gprint (GP_ERR, "USAGE: queue2book (queue) (book) [-uniq] [-key key[:key..]] [-setword (word) (value)] [-raw-columns] \n"); 70 122 gprint (GP_ERR, " converts the named queue with ipptool metadata output into book format\n"); 71 123 FREEKEYS; … … 73 125 } 74 126 75 queue = FindQueue (argv[1]);127 Queue *queue = FindQueue (argv[1]); 76 128 if (queue == NULL) { 77 129 gprint (GP_ERR, "queue %s not found\n", argv[1]); … … 80 132 } 81 133 82 book = CreateBook (argv[2]); 134 Book *book = CreateBook (argv[2]); 135 136 if (RawColumns) { 137 int status = queue2book_rawcolumns (queue, book); 138 return status; 139 } 83 140 84 141 /* the first non-whitespace line of the queue should contain: … … 101 158 free (line); 102 159 } 103 bookName = thisword (line);160 char *bookName = thisword (line); 104 161 tmpword = nextword (line); 105 162 163 // check for BookName MULTI 106 164 if (!tmpword || strcmp(tmpword, "MULTI")) { 107 165 gprint (GP_ERR, "ERROR: missing metadata output name on first line\n"); 108 free (bookName); 109 free (line); 110 FREEKEYS; 111 return (TRUE); 166 goto escape; 112 167 } 113 168 free (line); 114 169 170 // loop over lines, checking for new pages and words in the page 115 171 onPage = FALSE; 172 Page *page = NULL; 116 173 while (TRUE) { 117 174 line = PopQueue (queue); 118 if (!line) { 175 if (!line) { // we have reached the end of the queue 176 if (onPage) { gprint (GP_ERR, "ERROR: unterminated metadata\n"); } 119 177 free (bookName); 120 if (onPage) {121 gprint (GP_ERR, "ERROR: unterminated metadata\n");122 FREEKEYS;123 return (TRUE);124 }125 178 FREEKEYS; 126 179 return (TRUE); 127 180 } 128 181 stripwhite (line); 129 if (!*line) { 130 free (line); 131 continue; 132 } 133 if (line[0] == '#') { 134 free (line); 135 continue; 136 } 182 183 // skip empty lines and commented-out lines 184 if (!*line) { free (line); continue; } 185 if (line[0] == '#') { free (line); continue; } 137 186 187 // parse the words on this line 138 188 tmpword = thisword (line); 139 189 if (tmpword == NULL) abort(); // should not happen if line exists … … 142 192 if (strcmp(tmpword, bookName)) { 143 193 gprint (GP_ERR, "ERROR: unexpected metadata name %s\n", tmpword); 144 free (line);145 194 free (tmpword); 146 free (bookName); 147 FREEKEYS; 148 return (TRUE); 195 goto escape; 149 196 } 150 197 free (tmpword); … … 152 199 if (strcmp(tmpword, "METADATA")) { 153 200 gprint (GP_ERR, "ERROR: missing METADATA tag\n"); 154 free (line);155 201 free (tmpword); 156 free (bookName); 157 FREEKEYS; 158 return TRUE; 202 goto escape; 159 203 } 160 204 onPage = TRUE; 161 // we don't know the page name until we load its data? 205 // we don't know the page name until we load its data, so set temporary name. 206 // this name will be used if no keys are supplied 162 207 sprintf (pagename, "page.%03d", book[0].Npages); 163 208 page = CreatePage (book, pagename); … … 167 212 } 168 213 169 /* close out the page */ 214 // if we are here, we are within the page 215 216 // if we have hit the end of the page, we have some special work to do 170 217 if (!strcmp(tmpword, "END")) { 171 218 // XXX set the page name based on the contents … … 173 220 free (line); 174 221 175 if (keys) { 176 memset (pagename, 0, 512); 177 for (i = 0; i < Nkeys; i++) { 178 tmpword = BookGetWord (page, keys[i]); 179 if (tmpword == NULL) { 180 gprint (GP_ERR, "ERROR: missing key %s for ID\n", keys[i]); 181 FREEKEYS; 182 return (TRUE); 183 } 184 if (i > 0) strcat (pagename, ":"); 185 strcat (pagename, tmpword); 186 } 187 free (page[0].name); 188 page[0].name = strcreate (pagename); 189 } 190 191 // add the fixed words to the page 192 for (i = 0; i < setWordN; i++) { 193 BookSetWord (page, setWordList[i], setWordValue[i]); 194 } 195 196 if (Unique) { 197 /* search for an existing page with this name 198 delete this one if one is found */ 199 /* XXX don't attach this page to the book until this step is passed */ 200 201 found = FALSE; 202 for (i = 0; !found && (i < book[0].Npages); i++) { 203 if (book[0].pages[i] == page) continue; 204 if (!strcmp (book[0].pages[i][0].name, page[0].name)) { 205 found = TRUE; 206 } 207 } 208 if (found) { 209 DeletePage (book, page); 210 } 211 } 222 if (!queue2book_setpages (book, page)) return (FALSE); 223 queue2book_addwords (book, page); 224 queue2book_uniquify (book, page); 212 225 213 226 onPage = FALSE; … … 219 232 gprint (GP_ERR, "ERROR: missing value for %s\n", tmpword); 220 233 free (tmpword); 221 free (line); 222 free (bookName); 223 FREEKEYS; 224 return (TRUE); 234 goto escape; 225 235 } 226 236 BookSetWord (page, tmpword, tmpvalue); … … 231 241 FREEKEYS; 232 242 return (TRUE); 233 } 243 244 escape: 245 free (line); 246 free (bookName); 247 FREEKEYS; 248 return (TRUE); 249 } 250 251 int queue2book_rawcolumns (Queue *queue, Book *book) { 252 253 Page *idxPage = NULL; 254 char pagename[512]; 255 256 while (TRUE) { 257 char *line = PopQueue (queue); 258 if (!line) { // we have reached the end of the queue 259 FREEKEYS; 260 if (idxPage) { DeletePage (book, idxPage); } 261 return (TRUE); 262 } 263 stripwhite (line); 264 265 // skip empty lines and commented-out lines 266 if (!*line) { free (line); continue; } 267 if (line[0] == '#') { free (line); continue; } 268 269 Page *page = NULL; 270 271 // the first non-whitespace line of the queue should contain the column names 272 // save those words as the words on the index page 273 274 if (idxPage) { 275 sprintf (pagename, "page.%03d", book->Npages); 276 } else { 277 sprintf (pagename, "page.index"); 278 } 279 page = CreatePage (book, pagename); 280 281 int Nw = 0; // index into the number of the word on the line 282 char *ptr = line; 283 while (ptr) { 284 if (idxPage && (Nw >= idxPage->Nwords)) { 285 gprint (GP_ERR, "ERROR: line has too many items: %s\n", line); 286 return (FALSE); 287 } 288 289 char *tmpword = thisword (ptr); 290 if (tmpword == NULL) abort(); // should not happen if ptr is not NULL 291 292 // need to use the index page to get the words 293 if (idxPage) { 294 BookSetWord (page, idxPage->words[Nw], tmpword); 295 } else { 296 BookSetWord (page, tmpword, "index"); 297 } 298 299 free (tmpword); 300 301 ptr = nextword (ptr); 302 Nw ++; 303 } 304 if (!queue2book_setpages (book, page)) return (FALSE); 305 queue2book_addwords (book, page); 306 queue2book_uniquify (book, page); 307 308 if (!idxPage) { idxPage = page; } 309 } 310 return FALSE; // it should not be possible to reach here 311 } 312 313 // keys, Nkeys are file-globals 314 int queue2book_setpages (Book *book, Page *page) { 315 316 char pagename[512]; 317 318 // set the page name based on the key values 319 if (!keys) return TRUE; 320 321 memset (pagename, 0, 512); 322 for (int i = 0; i < Nkeys; i++) { 323 char *tmpword = BookGetWord (page, keys[i]); 324 if (tmpword == NULL) { 325 gprint (GP_ERR, "ERROR: missing key %s for ID\n", keys[i]); 326 FREEKEYS; 327 return FALSE; 328 } 329 if (i > 0) strcat (pagename, ":"); 330 strcat (pagename, tmpword); 331 } 332 free (page[0].name); 333 page[0].name = strcreate (pagename); 334 return TRUE; 335 } 336 337 // setWordList, setWordValue, setWordN are file-globals 338 int queue2book_addwords (Book *book, Page *page) { 339 // add the fixed words to the page 340 for (int i = 0; i < setWordN; i++) { 341 BookSetWord (page, setWordList[i], setWordValue[i]); 342 } 343 return TRUE; 344 } 345 346 // setWordList, setWordValue, setWordN are file-globals 347 // it would be cleaner to not attach this page to the book until this step is passed 348 int queue2book_uniquify (Book *book, Page *page) { 349 350 if (!Unique) return TRUE; 351 352 // search for an existing page with this name 353 // delete this one if one is found 354 355 int found = FALSE; 356 for (int i = 0; !found && (i < book->Npages); i++) { 357 if (book->pages[i] == page) continue; 358 if (!strcmp (book->pages[i]->name, page->name)) { 359 found = TRUE; 360 } 361 } 362 if (found) { 363 DeletePage (book, page); 364 } 365 return TRUE; 366 } 367 368 234 369 235 370 /* scan through the queue lines. these should look like: 236 371 237 bookName METADATA238 key type value239 key type value240 ...241 END242 243 bookName METADATA244 key type value245 key type value246 ...247 END372 bookName METADATA 373 key type value 374 key type value 375 ... 376 END 377 378 bookName METADATA 379 key type value 380 key type value 381 ... 382 END 248 383 */
Note:
See TracChangeset
for help on using the changeset viewer.
