/src/common/split.c

https://code.google.com/ · C · 165 lines · 87 code · 29 blank · 49 comment · 41 complexity · 61936cbed53afac9c19ac61790b6ee9e MD5 · raw file

  1. /*****************************************************************************\
  2. * $Id$
  3. *****************************************************************************
  4. * Copyright (C) 2006 The Regents of the University of California.
  5. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  6. * Written by Jim Garlick <garlick@llnl.gov>.
  7. * UCRL-CODE-2003-005.
  8. *
  9. * This file is part of Pdsh, a parallel remote shell program.
  10. * For details, see <http://www.llnl.gov/linux/pdsh/>.
  11. *
  12. * Pdsh is free software; you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free
  14. * Software Foundation; either version 2 of the License, or (at your option)
  15. * any later version.
  16. *
  17. * Pdsh is distributed in the hope that it will be useful, but WITHOUT ANY
  18. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  20. * details.
  21. *
  22. * You should have received a copy of the GNU General Public License along
  23. * with Pdsh; if not, write to the Free Software Foundation, Inc.,
  24. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  25. \*****************************************************************************/
  26. #if HAVE_CONFIG_H
  27. # include <config.h>
  28. #endif
  29. #include <string.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include "xmalloc.h"
  33. #include "split.h"
  34. /*
  35. * Helper function for list_split(). Extract tokens from str.
  36. * Return a pointer to the next token; at the same time, advance
  37. * *str to point to the next separator.
  38. * sep (IN) string containing list of separator characters
  39. * str (IN) double-pointer to string containing tokens and separators
  40. * RETURN next token
  41. */
  42. static char *_next_tok(char *sep, char **str)
  43. {
  44. char *tok;
  45. int level = 0;
  46. /* push str past any leading separators */
  47. while (**str != '\0' && strchr(sep, **str) != NULL)
  48. (*str)++;
  49. if (**str == '\0')
  50. return NULL;
  51. /* assign token pointer */
  52. tok = *str;
  53. /* push str past token and leave pointing to first separator,
  54. ignoring separators between any '[]' */
  55. while (**str != '\0' && (level != 0 || strchr(sep, **str) == NULL)) {
  56. if (**str == '[')
  57. level++;
  58. else if (**str == ']')
  59. level--;
  60. (*str)++;
  61. }
  62. /* nullify consecutive separators and push str beyond them */
  63. while (**str != '\0' && strchr(sep, **str) != NULL)
  64. *(*str)++ = '\0';
  65. return tok;
  66. }
  67. static void free_f (char *str)
  68. {
  69. Free ((void **) &str);
  70. }
  71. /*
  72. * Given a list of separators and a string, generate a list
  73. * sep (IN) string containing separater characters
  74. * str (IN) string containing tokens and separators
  75. * RETURN new list containing all tokens
  76. */
  77. List list_split(char *sep, char *str)
  78. {
  79. List new = list_create((ListDelF) free_f);
  80. char *tok;
  81. if (sep == NULL)
  82. sep = " \t";
  83. while ((tok = _next_tok(sep, &str)) != NULL) {
  84. if (strlen(tok) > 0)
  85. list_append(new, Strdup(tok));
  86. }
  87. return new;
  88. }
  89. List list_split_append (List l, char *sep, char *str)
  90. {
  91. char *tok;
  92. if (l == NULL)
  93. return (list_split (sep, str));
  94. if (sep == NULL)
  95. sep = " \t";
  96. while ((tok = _next_tok(sep, &str)) != NULL) {
  97. if (strlen(tok) > 0)
  98. list_append(l, Strdup(tok));
  99. }
  100. return l;
  101. }
  102. int list_join (char *result, size_t len, const char *sep, List l)
  103. {
  104. char *str = NULL;
  105. int n = 0;
  106. int truncated = 0;
  107. ListIterator i;
  108. memset (result, 0, len);
  109. if (list_count(l) == 0)
  110. return (0);
  111. i = list_iterator_create(l);
  112. while ((str = list_next(i))) {
  113. int count;
  114. if (!truncated) {
  115. count = snprintf(result + n, len - n, "%s%s", str, sep);
  116. if ((count >= (len - n)) || (count < 0))
  117. truncated = 1;
  118. else
  119. n += count;
  120. }
  121. else
  122. n += strlen (str) + strlen (sep);
  123. }
  124. list_iterator_destroy(i);
  125. if (truncated)
  126. result [len - 1] = '\0';
  127. else {
  128. /*
  129. * Delete final separator
  130. */
  131. result[strlen(result) - strlen(sep)] = '\0';
  132. }
  133. return (n);
  134. }
  135. /* vi: ts=4 sw=4 expandtab
  136. */