IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42408 for trunk/Ohana


Ignore:
Timestamp:
Mar 10, 2023, 4:03:44 PM (3 years ago)
Author:
eugene
Message:

add option to interpret queue as a list of white-space-separated columns

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/opihi/cmd.data/queue2book.c

    r41341 r42408  
    11# include "pantasks.h"
    22
    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]); } \
    66  free (setWordValue); free (setWordList);
    77
    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
     46int Unique;
     47int RawColumns;
     48
     49char **setWordList;
     50char **setWordValue;
     51int    setWordN;
     52
     53int   Nkeys;
     54char **keys;
     55
     56int queue2book_rawcolumns (Queue *queue, Book *book);
     57int queue2book_setpages (Book *book, Page *page);
     58int queue2book_addwords (Book *book, Page *page);
     59int queue2book_uniquify (Book *book, Page *page);
     60
    961int queue2book (int argc, char **argv) {
    1062
    11   int i, N, onPage, found, Unique, Nkeys, NKEYS;
     63  int N, onPage;
    1264  char *line, *tmpword, *tmpvalue;
    1365  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;
    2266
    2367  /* supply additional constant words */
    2468  setWordN = 0;
    25   setWordNalloc = 10;
     69  int setWordNalloc = 10;
    2670  ALLOCATE (setWordList, char *, setWordNalloc);
    2771  ALLOCATE (setWordValue, char *, setWordNalloc);
     
    4690  }
    4791
     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)
    4899  Nkeys = 0;
    49   keys = NULL;
     100  keys  = NULL;
    50101  if ((N = get_argument (argc, argv, "-key"))) {
    51102    remove_argument (N, &argc, argv);
    52103
    53104    /* parse the key (word:word:word) into constituents */
    54     NKEYS = 10;
     105    int NKEYS = 10;
    55106    ALLOCATE (keys, char *, NKEYS);
    56107   
    57     p = q = argv[N];
     108    char *p = argv[N];
     109    char *q = p;
    58110    while (q != NULL) {
    59111      q = strchr (p, ':');
     
    67119
    68120  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");
    70122    gprint (GP_ERR, "       converts the named queue  with ipptool metadata output into book format\n");
    71123    FREEKEYS;
     
    73125  }
    74126
    75   queue = FindQueue (argv[1]);
     127  Queue *queue = FindQueue (argv[1]);
    76128  if (queue == NULL) {
    77129    gprint (GP_ERR, "queue %s not found\n", argv[1]);
     
    80132  }
    81133   
    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  }
    83140
    84141  /* the first non-whitespace line of the queue should contain:
     
    101158    free (line);
    102159  }
    103   bookName = thisword (line);
     160  char *bookName = thisword (line);
    104161  tmpword = nextword (line);
    105162
     163  // check for BookName MULTI
    106164  if (!tmpword || strcmp(tmpword, "MULTI")) {
    107165    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;
    112167  }
    113168  free (line);
    114169 
     170  // loop over lines, checking for new pages and words in the page
    115171  onPage = FALSE;
     172  Page *page = NULL;
    116173  while (TRUE) {
    117174    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"); }
    119177      free (bookName);
    120       if (onPage) {
    121         gprint (GP_ERR, "ERROR: unterminated metadata\n");
    122         FREEKEYS;
    123         return (TRUE);
    124       }
    125178      FREEKEYS;
    126179      return (TRUE);
    127180    }
    128181    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; }
    137186   
     187    // parse the words on this line
    138188    tmpword = thisword (line);
    139189    if (tmpword == NULL) abort(); // should not happen if line exists
     
    142192      if (strcmp(tmpword, bookName)) {
    143193        gprint (GP_ERR, "ERROR: unexpected metadata name %s\n", tmpword);
    144         free (line);
    145194        free (tmpword);
    146         free (bookName);
    147         FREEKEYS;
    148         return (TRUE);
     195        goto escape;
    149196      }
    150197      free (tmpword);
     
    152199      if (strcmp(tmpword, "METADATA")) {
    153200        gprint (GP_ERR, "ERROR: missing METADATA tag\n");
    154         free (line);
    155201        free (tmpword);
    156         free (bookName);
    157         FREEKEYS;
    158         return TRUE;
     202        goto escape;
    159203      }
    160204      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
    162207      sprintf (pagename, "page.%03d", book[0].Npages);
    163208      page = CreatePage (book, pagename);
     
    167212    }
    168213
    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
    170217    if (!strcmp(tmpword, "END")) {
    171218      // XXX set the page name based on the contents
     
    173220      free (line);
    174221
    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);
    212225
    213226      onPage = FALSE;
     
    219232      gprint (GP_ERR, "ERROR: missing value for %s\n", tmpword);
    220233      free (tmpword);
    221       free (line);
    222       free (bookName);
    223       FREEKEYS;
    224       return (TRUE);
     234      goto escape;
    225235    }
    226236    BookSetWord (page, tmpword, tmpvalue);
     
    231241  FREEKEYS;
    232242  return (TRUE);
    233 }
     243
     244escape:
     245  free (line);
     246  free (bookName);
     247  FREEKEYS;
     248  return (TRUE);
     249}
     250
     251int 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
     314int 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
     338int 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
     348int 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
    234369
    235370/* scan through the queue lines.  these should look like: 
    236371
    237 bookName METADATA
    238 key type value
    239 key type value
    240 ...
    241 END
    242 
    243 bookName METADATA
    244 key type value
    245 key type value
    246 ...
    247 END
     372   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
    248383*/
Note: See TracChangeset for help on using the changeset viewer.