aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/path.mxx3
-rw-r--r--libbutl/utility.cxx38
-rw-r--r--libbutl/utility.ixx56
-rw-r--r--libbutl/utility.mxx64
4 files changed, 133 insertions, 28 deletions
diff --git a/libbutl/path.mxx b/libbutl/path.mxx
index ab85a0f..5b9bec1 100644
--- a/libbutl/path.mxx
+++ b/libbutl/path.mxx
@@ -343,6 +343,9 @@ LIBBUTL_MODEXPORT namespace butl
static int
compare (const C* l, size_type ln, const C* r, size_type rn)
{
+ //@@ TODO: would be nice to ignore difference in trailing slashes
+ // (except for POSIX root).
+
for (size_type i (0), n (ln < rn ? ln : rn); i != n; ++i)
{
#ifdef _WIN32
diff --git a/libbutl/utility.cxx b/libbutl/utility.cxx
index c8e4e85..4645b68 100644
--- a/libbutl/utility.cxx
+++ b/libbutl/utility.cxx
@@ -35,7 +35,6 @@ import std.io;
#endif
-
namespace butl
{
using namespace std;
@@ -88,6 +87,43 @@ namespace butl
win32::error_msg (system_code));
#endif
}
+
+ string&
+ trim (string& l)
+ {
+ /*
+ assert (trim (r = "") == "");
+ assert (trim (r = " ") == "");
+ assert (trim (r = " \t\r") == "");
+ assert (trim (r = "a") == "a");
+ assert (trim (r = " a") == "a");
+ assert (trim (r = "a ") == "a");
+ assert (trim (r = " \ta") == "a");
+ assert (trim (r = "a \r") == "a");
+ assert (trim (r = " a ") == "a");
+ assert (trim (r = " \ta \r") == "a");
+ */
+
+ size_t i (0), n (l.size ());
+
+ for (char c;
+ i != n && ((c = l[i]) == ' ' || c == '\t' || c == '\r');
+ ++i) ;
+
+ for (char c;
+ n != i && ((c = l[n - 1]) == ' ' || c == '\t' || c == '\r');
+ --n) ;
+
+ if (i != 0)
+ {
+ string s (l, i, n - i);
+ l.swap (s);
+ }
+ else if (n != l.size ())
+ l.resize (n);
+
+ return l;
+ }
}
namespace std
diff --git a/libbutl/utility.ixx b/libbutl/utility.ixx
index fcb8789..24271e4 100644
--- a/libbutl/utility.ixx
+++ b/libbutl/utility.ixx
@@ -4,18 +4,6 @@
namespace butl
{
- inline bool
- eof (std::istream& is)
- {
- if (!is.fail ())
- return false;
-
- if (is.eof ())
- return true;
-
- throw std::istream::failure ("");
- }
-
inline char
ucase (char c)
{
@@ -167,4 +155,48 @@ namespace butl
{
return std::iswxdigit (c);
}
+
+ inline std::size_t
+ next_word (const std::string& s, std::size_t& b, std::size_t& e,
+ char d1, char d2)
+ {
+ return next_word (s, s.size (), b, e, d1, d2);
+ }
+
+ inline size_t
+ next_word (const std::string& s,
+ std::size_t n, std::size_t& b, std::size_t& e,
+ char d1, char d2)
+ {
+ if (b != e)
+ b = e;
+
+ // Skip leading delimiters.
+ //
+ for (; b != n && (s[b] == d1 || s[b] == d2); ++b) ;
+
+ if (b == n)
+ {
+ e = n;
+ return 0;
+ }
+
+ // Find first trailing delimiter.
+ //
+ for (e = b + 1; e != n && s[e] != d1 && s[e] != d2; ++e) ;
+
+ return e - b;
+ }
+
+ inline bool
+ eof (std::istream& is)
+ {
+ if (!is.fail ())
+ return false;
+
+ if (is.eof ())
+ return true;
+
+ throw std::istream::failure ("");
+ }
}
diff --git a/libbutl/utility.mxx b/libbutl/utility.mxx
index 4c83827..b957282 100644
--- a/libbutl/utility.mxx
+++ b/libbutl/utility.mxx
@@ -57,21 +57,6 @@ LIBBUTL_MODEXPORT namespace butl
[[noreturn]] LIBBUTL_SYMEXPORT void
throw_system_error (int system_code, int fallback_errno_code = 0);
- // If an input stream is in a failed state, then return true if this is
- // because of the eof and throw istream::failure otherwise. If the stream
- // is not in a failed state, return false. This helper function is normally
- // used like this:
- //
- // is.exceptions (istream::badbit);
- //
- // for (string l; !eof (getline (is, l)); )
- // {
- // ...
- // }
- //
- bool
- eof (std::istream&);
-
// Convert ASCII character/string case. If there is no upper/lower case
// counterpart, leave the character unchanged. The POSIX locale (also known
// as C locale) must be the current application locale. Otherwise the
@@ -149,6 +134,55 @@ LIBBUTL_MODEXPORT namespace butl
bool alnum (wchar_t);
bool xdigit (wchar_t);
+ // Basic string utilities.
+ //
+
+ // Trim leading/trailing whitespacec, including '\r'.
+ //
+ std::string&
+ trim (std::string&);
+
+ // Find the beginning and end poistions of the next word. Return the size
+ // of the word or 0 and set b = e = n if there are no more words. For
+ // example:
+ //
+ // for (size_t b (0), e (0); next_word (s, b, e); )
+ // {
+ // string w (s, b, e - b);
+ // }
+ //
+ // Or:
+ //
+ // for (size_t b (0), e (0), n; n = next_word (s, b, e, ' ', ','); )
+ // {
+ // string w (s, b, n);
+ // }
+ //
+ // The second version examines up to the n'th character in the string.
+ //
+ std::size_t
+ next_word (const std::string&, std::size_t& b, std::size_t& e,
+ char d1 = ' ', char d2 = '\0');
+
+ std::size_t
+ next_word (const std::string&, std::size_t n, std::size_t& b, std::size_t& e,
+ char d1 = ' ', char d2 = '\0');
+
+ // If an input stream is in a failed state, then return true if this is
+ // because of the eof and throw istream::failure otherwise. If the stream
+ // is not in a failed state, return false. This helper function is normally
+ // used like this:
+ //
+ // is.exceptions (istream::badbit);
+ //
+ // for (string l; !eof (getline (is, l)); )
+ // {
+ // ...
+ // }
+ //
+ bool
+ eof (std::istream&);
+
// Key comparators (i.e., to be used in sets, maps, etc).
//
struct compare_c_string