argv.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /** @file argv.c
  2. * @brief Functions to parse string to arguments.
  3. */
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <ctype.h>
  9. #include "private.h"
  10. #include "faux/faux.h"
  11. #include "faux/str.h"
  12. #include "faux/list.h"
  13. #include "faux/argv.h"
  14. /** @brief Allocates new argv object.
  15. *
  16. * Before working with argument list it must be allocated and initialized.
  17. *
  18. * @return Allocated and initialized argument list or NULL on error.
  19. */
  20. faux_argv_t *faux_argv_new(void)
  21. {
  22. faux_argv_t *fargv = NULL;
  23. fargv = faux_zmalloc(sizeof(*fargv));
  24. assert(fargv);
  25. if (!fargv)
  26. return NULL;
  27. // Init
  28. fargv->list = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  29. NULL, NULL, (void (*)(void *))faux_str_free);
  30. fargv->quotes = NULL;
  31. fargv->continuable = BOOL_FALSE;
  32. return fargv;
  33. }
  34. /** @brief Frees the argv object object.
  35. *
  36. * After using the argv object must be freed. Function frees argv object.
  37. */
  38. void faux_argv_free(faux_argv_t *fargv)
  39. {
  40. assert(fargv);
  41. if (!fargv)
  42. return;
  43. faux_list_free(fargv->list);
  44. faux_str_free(fargv->quotes);
  45. faux_free(fargv);
  46. }
  47. /** @brief Initializes iterator to iterate through the entire argv object.
  48. *
  49. * Before iterating with the faux_argv_each() function the iterator must be
  50. * initialized. This function do it.
  51. *
  52. * @param [in] fargv Allocated and initialized argv object.
  53. * @return Initialized iterator.
  54. * @sa faux_argv_each()
  55. */
  56. faux_argv_node_t *faux_argv_iter(const faux_argv_t *fargv)
  57. {
  58. assert(fargv);
  59. if (!fargv)
  60. return NULL;
  61. return (faux_argv_node_t *)faux_list_head(fargv->list);
  62. }
  63. /** @brief Iterate entire argv object for arguments.
  64. *
  65. * Before iteration the iterator must be initialized by faux_argv_iter()
  66. * function. Doesn't use faux_argv_each() with uninitialized iterator.
  67. *
  68. * On each call function returns string (argument) and modifies iterator.
  69. * Stop iteration when function returns NULL.
  70. *
  71. * @param [in,out] iter Iterator.
  72. * @return String.
  73. * @sa faux_argv_iter()
  74. */
  75. const char *faux_argv_each(faux_argv_node_t **iter)
  76. {
  77. return (const char *)faux_list_each((faux_list_node_t **)iter);
  78. }
  79. void faux_argv_quotes(faux_argv_t *fargv, const char *quotes)
  80. {
  81. assert(fargv);
  82. if (!fargv)
  83. return;
  84. faux_str_free(fargv->quotes);
  85. if (!quotes) {
  86. fargv->quotes = NULL; // No additional quotes
  87. return;
  88. }
  89. fargv->quotes = faux_str_dup(quotes);
  90. }
  91. ssize_t faux_argv_parse(faux_argv_t *fargv, const char *str)
  92. {
  93. const char *saveptr = str;
  94. char *word = NULL;
  95. bool_t closed_quotes = BOOL_FALSE;
  96. assert(fargv);
  97. if (!fargv)
  98. return -1;
  99. if (!str)
  100. return -1;
  101. while ((word = faux_str_nextword(saveptr, &saveptr, fargv->quotes, &closed_quotes))) {
  102. faux_list_add(fargv->list, word);
  103. }
  104. // Check if last argument can be continued
  105. // It's true if last argument has unclosed quotes.
  106. // It's true if last argument doesn't terminated by space.
  107. fargv->continuable = !closed_quotes || ((saveptr != str) && (!isspace(*(saveptr - 1))));
  108. return 0;
  109. }
  110. bool_t faux_argv_is_continuable(faux_argv_t *fargv)
  111. {
  112. assert(fargv);
  113. if (!fargv)
  114. return BOOL_FALSE;
  115. return fargv->continuable;
  116. }