snapraid/cmdline/str.h
2026-08-26 12:43:17 +02:00

142 lines
4.6 KiB
C

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2025 Andrea Mazzoleni
#ifndef __STR_H
#define __STR_H
#include "app.h"
#include "str.h"
/****************************************************************************/
/* string */
/**
* Polish a string.
*
* Not printable chars are replaced by spaces.
*
* Note that the passed string is modified.
*/
char* strpolish(char* s);
/**
* Split a string into tokens in-place.
*
* Scans @str for tokens separated by any character in @delimiters,
* null-terminates each token by overwriting its trailing delimiter,
* and stores a pointer to each token's start in @split_map.
*
* Leading and consecutive delimiters are silently skipped, so the
* output never contains empty tokens.
*
* The input string is modified in-place; @split_map entries point
* directly into @str and are only valid for its lifetime.
*
* \param split_map Output array receiving pointers to each token.
* \param split_max Capacity of @split_map; at most this many tokens are stored.
* \param str Input string to tokenise (modified in-place).
* \param delimiters Null-terminated set of delimiter characters.
* \return Number of tokens stored in @split_map.
*
* Example:
* char buf[] = " one,two,,three ";
* char* map[8];
* unsigned n = strsplit(map, 8, buf, " ,");
* // n == 3, map[] == { "one", "two", "three" }
*/
unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters);
/**
* Split a command-line string into an argument vector,
* applying the quoting rules of the platform's native shell.
*
* The input string is modified in-place: quotes and escape characters
* are stripped and each token is null-terminated. Whitespace is the
* implicit token delimiter on both platforms.
*
* bash quoting (Linux / macOS):
* 'single quotes' - Everything literal; no escapes processed inside.
* "double quotes" - '\' only escapes $, `, ", '\', and newline;
* all other backslashes are kept as-is.
* \x (unquoted) - Next character taken literally (even whitespace).
*
* cmd.exe quoting (Windows):
* "double quotes" - Toggle quoted mode; inside, '^' is NOT special.
* ^x (unquoted) - Next character taken literally.
* Single quotes and '\' carry no special meaning in either mode.
*
* \param split_map Output array receiving pointers to each argument.
* \param split_max Capacity of @split_map; at most this many tokens are stored.
* \param str Input command-line string (modified in-place).
* \return Number of arguments stored in @split_map.
*
* Example (bash):
* char buf[] = "one 'two three' \"say \\\"hi\\\"\" back\\slash";
* char* map[8];
* unsigned n = argsplit(map, 8, buf);
* // n==4, map[] == { "one", "two three", "say \"hi\"", "backslash" }
*
* Example (cmd.exe):
* char buf[] = "one \"two three\" ^&safe ^\"quoted^\"";
* char* map[8];
* unsigned n = argsplit(map, 8, buf);
* // n==4, map[] == { "one", "two three", "&safe", "\"quoted\"" }
*/
unsigned argsplit(const char** split_map, unsigned split_max, char* str);
/**
* Trim spaces from the start and the end
*/
char* strtrim(char* s);
/**
* Lower case
*/
char* strlwr(char* s);
/*
* Find the first occurrence of 'needle' in 'haystack' only if it
* appears as a separate word (space, number or string boundaries).
*
* Returns a pointer to the beginning of the match, or NULL if not found.
*/
char* worddigitstr(const char* haystack, const char* needle);
/**
* Convert a string to an integer, with the same semantics as strtol.
*/
int strtoi(const char* nptr, char** endptr, int base);
/**
* Convert a string to an unsigned integer, with the same semantics as strtoul.
*/
unsigned strtou(const char* nptr, char** endptr, int base);
/****************************************************************************/
/* match */
/*
* Wild match function.
*
* If match_sub is !=0, it matches sub directory. Specifically it matches if the
* string "t" is not fully consumed and the next character to consume is a /.
*
* - ? matches any single character except /
* - * matches any sequence of characters except /
* - ** (nearby a /) matches everything including /
* - ** (not near a /) like *
* - ##/ reduces to nothing in addition to the normal matching of ** (using # instead of * to not mess the C comment)
* - [...] matches character classes with support for ranges and negation lile [!...] or [^...], except /
* - \ escapes *, ?, [, ], and \
*
* \return 0 if it matches
*/
int wnmatch_sub(const char* p, const char* t, int match_sub);
static inline int wnmatch(const char* p, const char* t)
{
return wnmatch_sub(p, t, 0);
}
#endif