/* * Parse the user's string argument that represents the list of key * fields or the counter fields to use in the AggBag. Parse the * string against the specified string map. The final parameter is * the argument type. On success, set the keys or counters on the * AggBag and return 0. Return non-zero on error. */ static int parseFields( const sk_stringmap_t *string_map, const char *name_list_arg, appOptionsEnum key_or_counter) { sk_stringmap_iter_t *sm_iter = NULL; sk_stringmap_entry_t *sm_entry = NULL; sk_aggbag_type_t *fields = NULL; unsigned int i; /* error message generated when parsing fields */ char *errmsg; ssize_t err; /* return value; assume failure */ int rv = -1; assert(string_map); assert(name_list_arg); assert(OPT_KEYS == key_or_counter || OPT_COUNTERS == key_or_counter); /* parse the argument */ if (skStringMapParse(string_map, name_list_arg, SKSTRINGMAP_DUPES_ERROR, &sm_iter, &errmsg)) { skAppPrintErr("Invalid %s: %s", appOptions[key_or_counter].name, errmsg); goto END; } /* create array to hold field IDs */ fields = (sk_aggbag_type_t *)calloc(skStringMapIterCountMatches(sm_iter), sizeof(sk_aggbag_type_t)); if (NULL == fields) { goto END; } /* add the field IDs to the array */ i = 0; while (skStringMapIterNext(sm_iter, &sm_entry, NULL) == SK_ITERATOR_OK) { assert(i < skStringMapIterCountMatches(sm_iter)); fields[i] = (sk_aggbag_type_t)sm_entry->id; ++i; } assert(skStringMapIterCountMatches(sm_iter) == i); if (OPT_KEYS == key_or_counter) { err = skAggBagSetKeyFields(ab, i, fields); } else { err = skAggBagSetCounterFields(ab, i, fields); } if (err) { skAppPrintErr("Unable to set %s %" SK_PRIdZ, appOptions[key_or_counter].name, err); goto END; } /* successful */ rv = 0; END: skStringMapIterDestroy(sm_iter); free(fields); return rv; }
/* * status = timestampFormatParse(format_string, out_flags); * * Parse the comma-separated list of timestamp format strings * contained in 'format_string' and set 'out_flags' to the result * of parsing the string. Return 0 on success, or -1 if parsing of * the values fails or conflicting values are given. */ static int timestampFormatParse( const char *format, uint32_t *out_flags) { char buf[256]; char *errmsg; sk_stringmap_t *str_map = NULL; sk_stringmap_iter_t *iter = NULL; sk_stringmap_entry_t *found_entry; const sk_stringmap_entry_t *entry; int name_seen = 0; int zone_seen = 0; int rv = -1; /* create a stringmap of the available timestamp formats */ if (SKSTRINGMAP_OK != skStringMapCreate(&str_map)) { skAppPrintOutOfMemory(NULL); goto END; } if (skStringMapAddEntries(str_map, -1, timestamp_names) != SKSTRINGMAP_OK){ skAppPrintOutOfMemory(NULL); goto END; } if (skStringMapAddEntries(str_map, -1, timestamp_zones) != SKSTRINGMAP_OK){ skAppPrintOutOfMemory(NULL); goto END; } /* attempt to match */ if (skStringMapParse(str_map, format, SKSTRINGMAP_DUPES_ERROR, &iter, &errmsg)) { skAppPrintErr("Invalid %s: %s", appOptions[OPT_TIMESTAMP_FORMAT].name, errmsg); goto END; } *out_flags = 0; while (skStringMapIterNext(iter, &found_entry, NULL) == SK_ITERATOR_OK) { *out_flags |= found_entry->id; switch (found_entry->id) { #if 0 case SKTIMESTAMP_NOMSEC: break; #endif case 0: case SKTIMESTAMP_EPOCH: case SKTIMESTAMP_ISO: case SKTIMESTAMP_MMDDYYYY: if (name_seen) { entry = timestamp_names; strncpy(buf, entry->name, sizeof(buf)); for (++entry; entry->name; ++entry) { strncat(buf, ",", sizeof(buf)-strlen(buf)-1); strncat(buf, entry->name, sizeof(buf)-strlen(buf)-1); } skAppPrintErr("Invalid %s: May only specify one of %s", appOptions[OPT_TIMESTAMP_FORMAT].name, buf); goto END; } name_seen = 1; break; case SKTIMESTAMP_UTC: case SKTIMESTAMP_LOCAL: if (zone_seen) { entry = timestamp_zones; strncpy(buf, entry->name, sizeof(buf)); for (++entry; entry->name; ++entry) { strncat(buf, ",", sizeof(buf)-strlen(buf)-1); strncat(buf, entry->name, sizeof(buf)-strlen(buf)-1); } skAppPrintErr("Invalid %s: May only specify one of %s", appOptions[OPT_TIMESTAMP_FORMAT].name, buf); goto END; } zone_seen = 1; break; default: skAbortBadCase(found_entry->id); } } rv = 0; END: if (str_map) { skStringMapDestroy(str_map); } if (iter) { skStringMapIterDestroy(iter); } return rv; }