argv.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. /** @brief Sets alternative quotes list.
  80. *
  81. * Any character from specified string becomes alternative quote.
  82. *
  83. * @param [in] fargv Allocated fargv object.
  84. * @param [in] quotes String with symbols to consider as a quote.
  85. */
  86. void faux_argv_quotes(faux_argv_t *fargv, const char *quotes)
  87. {
  88. assert(fargv);
  89. if (!fargv)
  90. return;
  91. faux_str_free(fargv->quotes);
  92. if (!quotes) {
  93. fargv->quotes = NULL; // No additional quotes
  94. return;
  95. }
  96. fargv->quotes = faux_str_dup(quotes);
  97. }
  98. /** @brief Parse string to words and quoted substrings.
  99. *
  100. * Parse string to words and quoted substrings. Additionally function sets
  101. * continuable flag. It shows if last word is reliable ended i.e. it can't be
  102. * continued.
  103. *
  104. * @param [in] fargv Allocated fargv object.
  105. * @param [in] str String to parse.
  106. * @return Number of resulting words and substrings or < 0 on error.
  107. */
  108. ssize_t faux_argv_parse(faux_argv_t *fargv, const char *str)
  109. {
  110. const char *saveptr = str;
  111. char *word = NULL;
  112. bool_t closed_quotes = BOOL_FALSE;
  113. assert(fargv);
  114. if (!fargv)
  115. return -1;
  116. if (!str)
  117. return -1;
  118. while ((word = faux_str_nextword(saveptr, &saveptr, fargv->quotes, &closed_quotes)))
  119. faux_list_add(fargv->list, word);
  120. // Check if last argument can be continued
  121. // It's true if last argument has unclosed quotes.
  122. // It's true if last argument doesn't terminated by space.
  123. fargv->continuable = !closed_quotes || ((saveptr != str) && (!isspace(*(saveptr - 1))));
  124. return faux_list_len(fargv->list);
  125. }
  126. /** @brief Returns continuable flag.
  127. *
  128. * Can be used after faux_argv_parse() only.
  129. *
  130. * @sa faux_argv_parse()
  131. * @param [in] fargv Allocated fargv object.
  132. * @return Boolean continuable flag.
  133. */
  134. bool_t faux_argv_is_continuable(faux_argv_t *fargv)
  135. {
  136. assert(fargv);
  137. if (!fargv)
  138. return BOOL_FALSE;
  139. return fargv->continuable;
  140. }