argv.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. if (!fargv)
  41. return;
  42. faux_list_free(fargv->list);
  43. faux_str_free(fargv->quotes);
  44. faux_free(fargv);
  45. }
  46. /** @brief Initializes iterator to iterate through the entire argv object.
  47. *
  48. * Before iterating with the faux_argv_each() function the iterator must be
  49. * initialized. This function do it.
  50. *
  51. * @param [in] fargv Allocated and initialized argv object.
  52. * @return Initialized iterator.
  53. * @sa faux_argv_each()
  54. */
  55. faux_argv_node_t *faux_argv_iter(const faux_argv_t *fargv)
  56. {
  57. assert(fargv);
  58. if (!fargv)
  59. return NULL;
  60. return (faux_argv_node_t *)faux_list_head(fargv->list);
  61. }
  62. /** @brief Iterate entire argv object for arguments.
  63. *
  64. * Before iteration the iterator must be initialized by faux_argv_iter()
  65. * function. Doesn't use faux_argv_each() with uninitialized iterator.
  66. *
  67. * On each call function returns string (argument) and modifies iterator.
  68. * Stop iteration when function returns NULL.
  69. *
  70. * @param [in,out] iter Iterator.
  71. * @return String.
  72. * @sa faux_argv_iter()
  73. */
  74. const char *faux_argv_each(faux_argv_node_t **iter)
  75. {
  76. return (const char *)faux_list_each((faux_list_node_t **)iter);
  77. }
  78. /** @brief Get current argument by iterator.
  79. *
  80. * Before iteration the iterator must be initialized by faux_argv_iter()
  81. * function. Doesn't use faux_argv_current() with uninitialized iterator.
  82. *
  83. * Function doesn't modify iterator.
  84. *
  85. * @param [in] iter Iterator.
  86. * @return String.
  87. * @sa faux_argv_iter()
  88. */
  89. const char *faux_argv_current(faux_argv_node_t *iter)
  90. {
  91. return (const char *)faux_list_data((faux_list_node_t *)iter);
  92. }
  93. /** @brief Sets alternative quotes list.
  94. *
  95. * Any character from specified string becomes alternative quote.
  96. *
  97. * @param [in] fargv Allocated fargv object.
  98. * @param [in] quotes String with symbols to consider as a quote.
  99. */
  100. void faux_argv_set_quotes(faux_argv_t *fargv, const char *quotes)
  101. {
  102. assert(fargv);
  103. if (!fargv)
  104. return;
  105. faux_str_free(fargv->quotes);
  106. if (!quotes) {
  107. fargv->quotes = NULL; // No additional quotes
  108. return;
  109. }
  110. fargv->quotes = faux_str_dup(quotes);
  111. }
  112. /** @brief Parse string to words and quoted substrings.
  113. *
  114. * Parse string to words and quoted substrings. Additionally function sets
  115. * continuable flag. It shows if last word is reliable ended i.e. it can't be
  116. * continued.
  117. *
  118. * @param [in] fargv Allocated fargv object.
  119. * @param [in] str String to parse.
  120. * @return Number of resulting words and substrings or < 0 on error.
  121. */
  122. ssize_t faux_argv_parse(faux_argv_t *fargv, const char *str)
  123. {
  124. const char *saveptr = str;
  125. char *word = NULL;
  126. bool_t closed_quotes = BOOL_FALSE;
  127. assert(fargv);
  128. if (!fargv)
  129. return -1;
  130. if (!str)
  131. return -1;
  132. while ((word = faux_str_nextword(saveptr, &saveptr, fargv->quotes, &closed_quotes)))
  133. faux_list_add(fargv->list, word);
  134. // Check if last argument can be continued
  135. // It's true if last argument has unclosed quotes.
  136. // It's true if last argument doesn't terminated by space.
  137. fargv->continuable = !closed_quotes || ((saveptr != str) && (!isspace(*(saveptr - 1))));
  138. return faux_list_len(fargv->list);
  139. }
  140. /** @brief Get number of arguments.
  141. *
  142. * @param [in] fargv Allocated fargv object.
  143. * @return Number of words and substrings or < 0 on error.
  144. */
  145. ssize_t faux_argv_len(faux_argv_t *fargv)
  146. {
  147. assert(fargv);
  148. if (!fargv)
  149. return -1;
  150. return faux_list_len(fargv->list);
  151. }
  152. /** @brief Returns continuable flag.
  153. *
  154. * Can be used after faux_argv_parse() only.
  155. *
  156. * @sa faux_argv_parse()
  157. * @param [in] fargv Allocated fargv object.
  158. * @return Boolean continuable flag.
  159. */
  160. bool_t faux_argv_is_continuable(const faux_argv_t *fargv)
  161. {
  162. assert(fargv);
  163. if (!fargv)
  164. return BOOL_FALSE;
  165. return fargv->continuable;
  166. }
  167. /** @brief Sets continuable flag.
  168. *
  169. * @param [in] fargv Allocated fargv object.
  170. * @param [in] continuable Continuable flag to set.
  171. */
  172. void faux_argv_set_continuable(faux_argv_t *fargv, bool_t continuable)
  173. {
  174. assert(fargv);
  175. if (!fargv)
  176. return;
  177. fargv->continuable = continuable;
  178. }
  179. /** @brief If given node is last one.
  180. *
  181. * @param [in] iter Iterator/Node.
  182. * @return BOOL_TRUE if last, BOOL_FALSE - not last or error.
  183. */
  184. bool_t faux_argv_is_last(faux_argv_node_t *iter)
  185. {
  186. faux_list_node_t *node = (faux_list_node_t *)iter;
  187. if (!node)
  188. return BOOL_FALSE;
  189. if (faux_list_next_node(node) == NULL)
  190. return BOOL_TRUE;
  191. return BOOL_FALSE;
  192. }
  193. /** @brief Adds argument to fargv object.
  194. *
  195. * @param [in] fargv Allocated argv object.
  196. * @param [in] arg Argument to add.
  197. * @return BOOL_TRUE - success, BOOL_FALSE - error.
  198. */
  199. bool_t faux_argv_add(faux_argv_t *fargv, const char *arg)
  200. {
  201. assert(fargv);
  202. if (!fargv)
  203. return BOOL_FALSE;
  204. assert(arg);
  205. if (!arg)
  206. return BOOL_FALSE;
  207. faux_list_add(fargv->list, faux_str_dup(arg));
  208. return BOOL_TRUE;
  209. }