root/opal/util/argv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_argv_append
  2. opal_argv_append_nosize
  3. opal_argv_prepend_nosize
  4. opal_argv_append_unique_nosize
  5. opal_argv_free
  6. opal_argv_split_inter
  7. opal_argv_split
  8. opal_argv_split_with_empty
  9. opal_argv_count
  10. opal_argv_join
  11. opal_argv_join_range
  12. opal_argv_len
  13. opal_argv_copy
  14. opal_argv_delete
  15. opal_argv_insert
  16. opal_argv_insert_element

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2007      Voltaire. All rights reserved.
  13  * Copyright (c) 2012      Los Alamos National Security, LLC. All rights reserved.
  14  * Copyright (c) 2015      Research Organization for Information Science
  15  *                         and Technology (RIST). All rights reserved.
  16  *
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 #include "opal_config.h"
  25 #include <stdlib.h>
  26 #include <string.h>
  27 
  28 #include "opal/util/argv.h"
  29 #include "opal/util/string_copy.h"
  30 #include "opal/constants.h"
  31 
  32 #define ARGSIZE 128
  33 
  34 
  35 /*
  36  * Append a string to the end of a new or existing argv array.
  37  */
  38 int opal_argv_append(int *argc, char ***argv, const char *arg)
  39 {
  40     int rc;
  41 
  42     /* add the new element */
  43     if (OPAL_SUCCESS != (rc = opal_argv_append_nosize(argv, arg))) {
  44         return rc;
  45     }
  46 
  47     *argc = opal_argv_count(*argv);
  48 
  49     return OPAL_SUCCESS;
  50 }
  51 
  52 int opal_argv_append_nosize(char ***argv, const char *arg)
  53 {
  54     int argc;
  55 
  56   /* Create new argv. */
  57 
  58   if (NULL == *argv) {
  59     *argv = (char**) malloc(2 * sizeof(char *));
  60     if (NULL == *argv) {
  61         return OPAL_ERR_OUT_OF_RESOURCE;
  62     }
  63     argc = 0;
  64     (*argv)[0] = NULL;
  65     (*argv)[1] = NULL;
  66   }
  67 
  68   /* Extend existing argv. */
  69   else {
  70         /* count how many entries currently exist */
  71         argc = opal_argv_count(*argv);
  72 
  73         *argv = (char**) realloc(*argv, (argc + 2) * sizeof(char *));
  74         if (NULL == *argv) {
  75             return OPAL_ERR_OUT_OF_RESOURCE;
  76         }
  77     }
  78 
  79     /* Set the newest element to point to a copy of the arg string */
  80 
  81     (*argv)[argc] = strdup(arg);
  82     if (NULL == (*argv)[argc]) {
  83         return OPAL_ERR_OUT_OF_RESOURCE;
  84     }
  85 
  86     argc = argc + 1;
  87     (*argv)[argc] = NULL;
  88 
  89     return OPAL_SUCCESS;
  90 }
  91 
  92 int opal_argv_prepend_nosize(char ***argv, const char *arg)
  93 {
  94     int argc;
  95     int i;
  96 
  97     /* Create new argv. */
  98 
  99     if (NULL == *argv) {
 100         *argv = (char**) malloc(2 * sizeof(char *));
 101         if (NULL == *argv) {
 102             return OPAL_ERR_OUT_OF_RESOURCE;
 103         }
 104         (*argv)[0] = strdup(arg);
 105         (*argv)[1] = NULL;
 106     } else {
 107         /* count how many entries currently exist */
 108         argc = opal_argv_count(*argv);
 109 
 110         *argv = (char**) realloc(*argv, (argc + 2) * sizeof(char *));
 111         if (NULL == *argv) {
 112             return OPAL_ERR_OUT_OF_RESOURCE;
 113         }
 114         (*argv)[argc+1] = NULL;
 115 
 116         /* shift all existing elements down 1 */
 117         for (i=argc; 0 < i; i--) {
 118             (*argv)[i] = (*argv)[i-1];
 119         }
 120         (*argv)[0] = strdup(arg);
 121     }
 122 
 123     return OPAL_SUCCESS;
 124 }
 125 
 126 int opal_argv_append_unique_nosize(char ***argv, const char *arg, bool overwrite)
 127 {
 128     int i;
 129 
 130     /* if the provided array is NULL, then the arg cannot be present,
 131      * so just go ahead and append
 132      */
 133     if (NULL == *argv) {
 134         return opal_argv_append_nosize(argv, arg);
 135     }
 136 
 137     /* see if this arg is already present in the array */
 138     for (i=0; NULL != (*argv)[i]; i++) {
 139         if (0 == strcmp(arg, (*argv)[i])) {
 140             /* already exists - are we authorized to overwrite? */
 141             if (overwrite) {
 142                 free((*argv)[i]);
 143                 (*argv)[i] = strdup(arg);
 144             }
 145             return OPAL_SUCCESS;
 146         }
 147     }
 148 
 149     /* we get here if the arg is not in the array - so add it */
 150     return opal_argv_append_nosize(argv, arg);
 151 }
 152 
 153 /*
 154  * Free a NULL-terminated argv array.
 155  */
 156 void opal_argv_free(char **argv)
 157 {
 158   char **p;
 159 
 160   if (NULL == argv)
 161     return;
 162 
 163   for (p = argv; NULL != *p; ++p) {
 164     free(*p);
 165   }
 166 
 167   free(argv);
 168 }
 169 
 170 
 171 /*
 172  * Split a string into a NULL-terminated argv array.
 173  */
 174 static char **opal_argv_split_inter(const char *src_string, int delimiter,
 175         int include_empty)
 176 {
 177   char arg[ARGSIZE];
 178   char **argv = NULL;
 179   const char *p;
 180   char *argtemp;
 181   int argc = 0;
 182   size_t arglen;
 183 
 184   while (src_string && *src_string) {
 185     p = src_string;
 186     arglen = 0;
 187 
 188     while (('\0' != *p) && (*p != delimiter)) {
 189       ++p;
 190       ++arglen;
 191     }
 192 
 193     /* zero length argument, skip */
 194 
 195     if (src_string == p) {
 196       if (include_empty) {
 197         arg[0] = '\0';
 198         if (OPAL_SUCCESS != opal_argv_append(&argc, &argv, arg))
 199           return NULL;
 200       }
 201     }
 202 
 203     /* tail argument, add straight from the original string */
 204 
 205     else if ('\0' == *p) {
 206       if (OPAL_SUCCESS != opal_argv_append(&argc, &argv, src_string))
 207         return NULL;
 208       src_string = p;
 209       continue;
 210     }
 211 
 212     /* long argument, malloc buffer, copy and add */
 213 
 214     else if (arglen > (ARGSIZE - 1)) {
 215         argtemp = (char*) malloc(arglen + 1);
 216       if (NULL == argtemp)
 217         return NULL;
 218 
 219       opal_string_copy(argtemp, src_string, arglen + 1);
 220       argtemp[arglen] = '\0';
 221 
 222       if (OPAL_SUCCESS != opal_argv_append(&argc, &argv, argtemp)) {
 223         free(argtemp);
 224         return NULL;
 225       }
 226 
 227       free(argtemp);
 228     }
 229 
 230     /* short argument, copy to buffer and add */
 231 
 232     else {
 233       opal_string_copy(arg, src_string, arglen + 1);
 234       arg[arglen] = '\0';
 235 
 236       if (OPAL_SUCCESS != opal_argv_append(&argc, &argv, arg))
 237         return NULL;
 238     }
 239 
 240     src_string = p + 1;
 241   }
 242 
 243   /* All done */
 244 
 245   return argv;
 246 }
 247 
 248 char **opal_argv_split(const char *src_string, int delimiter)
 249 {
 250     return opal_argv_split_inter(src_string, delimiter, 0);
 251 }
 252 
 253 char **opal_argv_split_with_empty(const char *src_string, int delimiter)
 254 {
 255     return opal_argv_split_inter(src_string, delimiter, 1);
 256 }
 257 
 258 /*
 259  * Return the length of a NULL-terminated argv array.
 260  */
 261 int opal_argv_count(char **argv)
 262 {
 263   char **p;
 264   int i;
 265 
 266   if (NULL == argv)
 267     return 0;
 268 
 269   for (i = 0, p = argv; *p; i++, p++)
 270     continue;
 271 
 272   return i;
 273 }
 274 
 275 
 276 /*
 277  * Join all the elements of an argv array into a single
 278  * newly-allocated string.
 279  */
 280 char *opal_argv_join(char **argv, int delimiter)
 281 {
 282   char **p;
 283   char *pp;
 284   char *str;
 285   size_t str_len = 0;
 286   size_t i;
 287 
 288   /* Bozo case */
 289 
 290   if (NULL == argv || NULL == argv[0]) {
 291       return strdup("");
 292   }
 293 
 294   /* Find the total string length in argv including delimiters.  The
 295      last delimiter is replaced by the NULL character. */
 296 
 297   for (p = argv; *p; ++p) {
 298     str_len += strlen(*p) + 1;
 299   }
 300 
 301   /* Allocate the string. */
 302 
 303   if (NULL == (str = (char*) malloc(str_len)))
 304     return NULL;
 305 
 306   /* Loop filling in the string. */
 307 
 308   str[--str_len] = '\0';
 309   p = argv;
 310   pp = *p;
 311 
 312   for (i = 0; i < str_len; ++i) {
 313     if ('\0' == *pp) {
 314 
 315       /* End of a string, fill in a delimiter and go to the next
 316          string. */
 317 
 318       str[i] = (char) delimiter;
 319       ++p;
 320       pp = *p;
 321     } else {
 322       str[i] = *pp++;
 323     }
 324   }
 325 
 326   /* All done */
 327 
 328   return str;
 329 }
 330 
 331 
 332 /*
 333  * Join all the elements of an argv array from within a
 334  * specified range into a single newly-allocated string.
 335  */
 336 char *opal_argv_join_range(char **argv, size_t start, size_t end, int delimiter)
 337 {
 338     char **p;
 339     char *pp;
 340     char *str;
 341     size_t str_len = 0;
 342     size_t i;
 343 
 344     /* Bozo case */
 345 
 346     if (NULL == argv || NULL == argv[0] || (int)start > opal_argv_count(argv)) {
 347         return strdup("");
 348     }
 349 
 350     /* Find the total string length in argv including delimiters.  The
 351      last delimiter is replaced by the NULL character. */
 352 
 353     for (p = &argv[start], i=start; *p && i < end; ++p, ++i) {
 354         str_len += strlen(*p) + 1;
 355     }
 356 
 357     /* Allocate the string. */
 358 
 359     if (NULL == (str = (char*) malloc(str_len)))
 360         return NULL;
 361 
 362     /* Loop filling in the string. */
 363 
 364     str[--str_len] = '\0';
 365     p = &argv[start];
 366     pp = *p;
 367 
 368     for (i = 0; i < str_len; ++i) {
 369         if ('\0' == *pp) {
 370 
 371             /* End of a string, fill in a delimiter and go to the next
 372              string. */
 373 
 374             str[i] = (char) delimiter;
 375             ++p;
 376             pp = *p;
 377         } else {
 378             str[i] = *pp++;
 379         }
 380     }
 381 
 382     /* All done */
 383 
 384     return str;
 385 }
 386 
 387 
 388 /*
 389  * Return the number of bytes consumed by an argv array.
 390  */
 391 size_t opal_argv_len(char **argv)
 392 {
 393   char **p;
 394   size_t length;
 395 
 396   if (NULL == argv)
 397     return (size_t) 0;
 398 
 399   length = sizeof(char *);
 400 
 401   for (p = argv; *p; ++p) {
 402     length += strlen(*p) + 1 + sizeof(char *);
 403   }
 404 
 405   return length;
 406 }
 407 
 408 
 409 /*
 410  * Copy a NULL-terminated argv array.
 411  */
 412 char **opal_argv_copy(char **argv)
 413 {
 414   char **dupv = NULL;
 415   int dupc = 0;
 416 
 417   if (NULL == argv)
 418     return NULL;
 419 
 420   /* create an "empty" list, so that we return something valid if we
 421      were passed a valid list with no contained elements */
 422   dupv = (char**) malloc(sizeof(char*));
 423   dupv[0] = NULL;
 424 
 425   while (NULL != *argv) {
 426     if (OPAL_SUCCESS != opal_argv_append(&dupc, &dupv, *argv)) {
 427       opal_argv_free(dupv);
 428       return NULL;
 429     }
 430 
 431     ++argv;
 432   }
 433 
 434   /* All done */
 435 
 436   return dupv;
 437 }
 438 
 439 
 440 int opal_argv_delete(int *argc, char ***argv, int start, int num_to_delete)
 441 {
 442     int i;
 443     int count;
 444     int suffix_count;
 445     char **tmp;
 446 
 447     /* Check for the bozo cases */
 448     if (NULL == argv || NULL == *argv || 0 == num_to_delete) {
 449         return OPAL_SUCCESS;
 450     }
 451     count = opal_argv_count(*argv);
 452     if (start > count) {
 453         return OPAL_SUCCESS;
 454     } else if (start < 0 || num_to_delete < 0) {
 455         return OPAL_ERR_BAD_PARAM;
 456     }
 457 
 458     /* Ok, we have some tokens to delete.  Calculate the new length of
 459        the argv array. */
 460 
 461     suffix_count = count - (start + num_to_delete);
 462     if (suffix_count < 0) {
 463         suffix_count = 0;
 464     }
 465 
 466     /* Free all items that are being deleted */
 467 
 468     for (i = start; i < count && i < start + num_to_delete; ++i) {
 469         free((*argv)[i]);
 470     }
 471 
 472     /* Copy the suffix over the deleted items */
 473 
 474     for (i = start; i < start + suffix_count; ++i) {
 475         (*argv)[i] = (*argv)[i + num_to_delete];
 476     }
 477 
 478     /* Add the trailing NULL */
 479 
 480     (*argv)[i] = NULL;
 481 
 482     /* adjust the argv array */
 483     tmp = (char**)realloc(*argv, sizeof(char*) * (i + 1));
 484     if (NULL != tmp) *argv = tmp;
 485 
 486     /* adjust the argc */
 487     (*argc) -= num_to_delete;
 488 
 489     return OPAL_SUCCESS;
 490 }
 491 
 492 
 493 int opal_argv_insert(char ***target, int start, char **source)
 494 {
 495     int i, source_count, target_count;
 496     int suffix_count;
 497 
 498     /* Check for the bozo cases */
 499 
 500     if (NULL == target || NULL == *target || start < 0) {
 501         return OPAL_ERR_BAD_PARAM;
 502     } else if (NULL == source) {
 503         return OPAL_SUCCESS;
 504     }
 505 
 506     /* Easy case: appending to the end */
 507 
 508     target_count = opal_argv_count(*target);
 509     source_count = opal_argv_count(source);
 510     if (start > target_count) {
 511         for (i = 0; i < source_count; ++i) {
 512             opal_argv_append(&target_count, target, source[i]);
 513         }
 514     }
 515 
 516     /* Harder: insertting into the middle */
 517 
 518     else {
 519 
 520         /* Alloc out new space */
 521 
 522         *target = (char**) realloc(*target,
 523                                    sizeof(char *) * (target_count + source_count + 1));
 524 
 525         /* Move suffix items down to the end */
 526 
 527         suffix_count = target_count - start;
 528         for (i = suffix_count - 1; i >= 0; --i) {
 529             (*target)[start + source_count + i] =
 530                 (*target)[start + i];
 531         }
 532         (*target)[start + suffix_count + source_count] = NULL;
 533 
 534         /* Strdup in the source argv */
 535 
 536         for (i = start; i < start + source_count; ++i) {
 537             (*target)[i] = strdup(source[i - start]);
 538         }
 539     }
 540 
 541     /* All done */
 542 
 543     return OPAL_SUCCESS;
 544 }
 545 
 546 int opal_argv_insert_element(char ***target, int location, char *source)
 547 {
 548     int i, target_count;
 549     int suffix_count;
 550 
 551     /* Check for the bozo cases */
 552 
 553     if (NULL == target || NULL == *target || location < 0) {
 554         return OPAL_ERR_BAD_PARAM;
 555     } else if (NULL == source) {
 556         return OPAL_SUCCESS;
 557     }
 558 
 559     /* Easy case: appending to the end */
 560     target_count = opal_argv_count(*target);
 561     if (location > target_count) {
 562         opal_argv_append(&target_count, target, source);
 563         return OPAL_SUCCESS;
 564     }
 565 
 566     /* Alloc out new space */
 567     *target = (char**) realloc(*target,
 568                                sizeof(char*) * (target_count + 2));
 569 
 570     /* Move suffix items down to the end */
 571     suffix_count = target_count - location;
 572     for (i = suffix_count - 1; i >= 0; --i) {
 573         (*target)[location + 1 + i] =
 574         (*target)[location + i];
 575     }
 576     (*target)[location + suffix_count + 1] = NULL;
 577 
 578     /* Strdup in the source */
 579     (*target)[location] = strdup(source);
 580 
 581     /* All done */
 582     return OPAL_SUCCESS;
 583 }

/* [<][>][^][v][top][bottom][index][help] */