* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/ .
+ * along with this program. If not, see https://www.gnu.org/licenses/ .
*
* Author: Jani Nikula <jani@nikula.org>
*/
#include <ctype.h>
#include <errno.h>
+#include <stdbool.h>
char *
strtok_len (char *s, const char *delim, size_t *len)
return *len ? s : NULL;
}
+const char *
+strsplit_len (const char *s, char delim, size_t *len)
+{
+ bool escaping = false;
+ size_t count = 0, last_nonspace = 0;
+
+ /* Skip initial unescaped delimiters and whitespace */
+ while (*s && (*s == delim || isspace (*s)))
+ s++;
+
+ while (s[count] && (escaping || s[count] != delim)) {
+ if (! isspace (s[count]))
+ last_nonspace = count;
+ escaping = (s[count] == '\\');
+ count++;
+ }
+
+ if (count == 0)
+ return NULL;
+
+ *len = last_nonspace + 1;
+ return s;
+}
+
const char *
strtok_len_c (const char *s, const char *delim, size_t *len)
{
/* strtok_len is already const-safe, but we can't express both
* versions in the C type system. */
- return strtok_len ((char*)s, delim, len);
+ return strtok_len ((char *) s, delim, len);
}
char *
for (loop = out; *loop; loop++) {
if (*loop == '\t' || *loop == '\n')
*loop = ' ';
- else if ((unsigned char)(*loop) < 32)
+ else if ((unsigned char) (*loop) < 32)
*loop = '?';
}
* beginning, and anything containing non-ASCII text. */
if (! term[0])
need_quoting = 1;
- for (in = term; *in && !need_quoting; in++)
+ for (in = term; *in && ! need_quoting; in++)
if (is_unquoted_terminator (*in) || *in == '"' || *in == '('
- || (unsigned char)*in > 127)
+ || (unsigned char) *in > 127)
need_quoting = 1;
if (need_quoting)
return 0;
}
-static const char*
+const char *
skip_space (const char *str)
{
while (*str && isspace ((unsigned char) *str))
char **prefix_out, char **term_out)
{
int err = EINVAL;
+
*prefix_out = *term_out = NULL;
/* Parse prefix */
str = skip_space (str);
const char *pos = strchr (str, ':');
+
if (! pos || pos == str)
goto FAIL;
*prefix_out = talloc_strndup (ctx, str, pos - str);
}
/* Did the term terminate without a closing quote or is there
* trailing text after the closing quote? */
- if (!closed || *pos)
+ if (! closed || *pos)
goto FAIL;
*out = '\0';
} else {
}
return 0;
- FAIL:
+ FAIL:
talloc_free (*prefix_out);
talloc_free (*term_out);
errno = err;
return -1;
}
+
+int
+strcmp_null (const char *s1, const char *s2)
+{
+ if (s1 && s2)
+ return strcmp (s1, s2);
+ else if (! s1 && ! s2)
+ return 0;
+ else if (s1)
+ return 1; /* s1 (non-NULL) is greater than s2 (NULL) */
+ else
+ return -1; /* s1 (NULL) is less than s2 (non-NULL) */
+}
+
+int
+strcase_equal (const void *a, const void *b)
+{
+ return strcasecmp (a, b) == 0;
+}
+
+unsigned int
+strcase_hash (const void *ptr)
+{
+ const char *s = ptr;
+
+ /* This is the djb2 hash. */
+ unsigned int hash = 5381;
+
+ while (s && *s) {
+ hash = ((hash << 5) + hash) + tolower (*s);
+ s++;
+ }
+
+ return hash;
+}
+
+void
+strip_trailing (char *str, char ch)
+{
+ int i;
+
+ for (i = strlen (str) - 1; i >= 0; i--) {
+ if (str[i] == ch)
+ str[i] = '\0';
+ else
+ break;
+ }
+}