123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- // Generic algorithms for manipulating null-terminated character sequences
- //
- // Platform: ISO C++ 98/11
- // $Id$
- //
- // (c) __vic 2008
- #ifndef __VIC_TCHAR_H
- #define __VIC_TCHAR_H
- #include<__vic/defs.h>
- #include<string> // for char_traits
- #include<cstring>
- #include<cwchar>
- #if !__cpp_lambdas
- #include<functional>
- #endif
- namespace __vic { namespace tchar {
- //----------------------------------------------------------------------------
- // String length (generic strlen)
- //----------------------------------------------------------------------------
- template<class charT>
- inline size_t length(const charT *st)
- {
- return std::char_traits<charT>::length(st);
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Check if string has no characters
- //----------------------------------------------------------------------------
- template<class charT>
- inline bool empty(const charT *s)
- {
- return !s || !*s;
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find end of sequence (pointer to null-terminator)
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *end(const charT *st)
- {
- while(*st != charT()) st++;
- return st;
- }
- //----------------------------------------------------------------------------
- template<>
- inline const char *end(const char *st)
- {
- return std::strchr(st, '\x0');
- }
- //----------------------------------------------------------------------------
- template<>
- inline const wchar_t *end(const wchar_t *st)
- {
- return std::wcschr(st, L'\x0');
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *end(charT *st)
- {
- return const_cast<charT*>(end(const_cast<const charT *>(st)));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Compare strings (generic strcmp, wcscmp)
- //----------------------------------------------------------------------------
- template<class charT>
- inline int compare(const charT *s1, const charT *s2)
- {
- for(; *s1 && *s2; ++s1, ++s2)
- if(*s1 != *s2) return *s1 < *s2 ? -1 : 1;
- if(!*s1 && *s2) return -1; // s1 < s2
- if( *s1 && !*s2) return 1; // s1 > s2
- return 0; // s1 == s2
- }
- //----------------------------------------------------------------------------
- template<>
- inline int compare(const char *s1, const char *s2)
- {
- return std::strcmp(s1, s2);
- }
- //----------------------------------------------------------------------------
- template<>
- inline int compare(const wchar_t *s1, const wchar_t *s2)
- {
- return std::wcscmp(s1, s2);
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Check if strings are equal
- //----------------------------------------------------------------------------
- template<class charT>
- inline bool equal(const charT *s1, const charT *s2)
- {
- return compare(s1, s2) == 0;
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Copy string (generic strcpy, wcscpy)
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *copy(charT *dest, const charT *src, size_t n)
- {
- std::memcpy(dest, src, n*sizeof(charT));
- return dest;
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *copy(charT *dest, const charT *src)
- {
- return copy(dest, src, length(src) + 1);
- }
- //----------------------------------------------------------------------------
- template<>
- inline char *copy(char *dest, const char *src)
- {
- return std::strcpy(dest, src);
- }
- //----------------------------------------------------------------------------
- template<>
- inline wchar_t *copy(wchar_t *dest, const wchar_t *src)
- {
- return std::wcscpy(dest, src);
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Move the string in memory (generic memmove)
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *move(charT *dest, const charT *src)
- {
- std::memmove(dest, src, (length(src) + 1) * sizeof(charT));
- return dest;
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Add a one string to another (generic strcat)
- //----------------------------------------------------------------------------
- template<class charT>
- charT *concat(charT *dest, const charT *src)
- {
- return copy(end(dest), src);
- }
- //----------------------------------------------------------------------------
- template<>
- inline char *concat(char *dest, const char *src)
- {
- return std::strcat(dest, src);
- }
- //----------------------------------------------------------------------------
- template<>
- inline wchar_t *concat(wchar_t *dest, const wchar_t *src)
- {
- return std::wcscat(dest, src);
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find first character in a string that satisfies a specified condition
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- const charT *find_if(const charT *st, Pred pred)
- {
- for(; *st; st++)
- if(pred(*st)) return st;
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- inline charT *find_if(charT *st, Pred pred)
- {
- return const_cast<charT*>(find_if(const_cast<const charT *>(st), pred));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find first character in a string that not satisfies a specified condition
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- const charT *find_if_not(const charT *st, Pred pred)
- {
- for(; *st; st++)
- if(!pred(*st)) return st;
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- inline charT *find_if_not(charT *st, Pred pred)
- {
- return const_cast<charT*>(find_if_not(const_cast<const charT *>(st), pred));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find last character in a string that satisfies a specified condition
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- const charT *rfind_if(const charT *st, Pred pred)
- {
- for(const charT *p = end(st) - 1; p >= st; p--)
- if(pred(*p)) return p;
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- inline charT *rfind_if(charT *st, Pred pred)
- {
- return const_cast<charT*>(rfind_if(const_cast<const charT *>(st), pred));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find last character in a string that not satisfies a specified condition
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- const charT *rfind_if_not(const charT *st, Pred pred)
- {
- for(const charT *p = end(st) - 1; p >= st; p--)
- if(!pred(*p)) return p;
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<class charT, class Pred>
- inline charT *rfind_if_not(charT *st, Pred pred)
- {
- return const_cast<charT*>(rfind_if_not(const_cast<const charT *>(st), pred));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a first occurrence of char in string (generic strchr)
- //----------------------------------------------------------------------------
- template<class charT>
- inline const charT *find(const charT *st, charT ch)
- {
- return find_if(st,
- #if __cpp_lambdas
- [ch](charT c) { return c == ch; }
- #else
- std::bind2nd(std::equal_to<charT>(), ch)
- #endif
- );
- }
- //----------------------------------------------------------------------------
- template<>
- inline const char *find(const char *st, char ch)
- {
- return std::strchr(st,ch);
- }
- //----------------------------------------------------------------------------
- template<>
- inline const wchar_t *find(const wchar_t *st, wchar_t ch)
- {
- return std::wcschr(st,ch);
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *find(charT *st, charT ch)
- {
- return const_cast<charT*>(find(const_cast<const charT *>(st), ch));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a first occurrence of substring in string (generic strstr)
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *find(const charT *st, const charT *sub)
- {
- for(; *st; st++)
- {
- if(*st == *sub)
- {
- const charT *p = st, *q = sub;
- while(*p && *q && *p != *q) p++, q++;
- if(*q == charT()) return st;
- }
- }
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<>
- inline const char *find(const char *st, const char *sub)
- {
- return std::strstr(st,sub);
- }
- //----------------------------------------------------------------------------
- template<>
- inline const wchar_t *find(const wchar_t *st, const wchar_t *sub)
- {
- return std::wcsstr(st,sub);
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *find(charT *st, const charT *sub)
- {
- return const_cast<charT*>(find(const_cast<const charT *>(st), sub));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a last occurrence of ch in string or NULL (generic strrchr)
- //----------------------------------------------------------------------------
- template<class charT>
- inline const charT *rfind(const charT *st, charT ch)
- {
- return rfind_if(st,
- #if __cpp_lambdas
- [ch](charT c) { return c == ch; }
- #else
- std::bind2nd(std::equal_to<charT>(), ch)
- #endif
- );
- }
- //----------------------------------------------------------------------------
- template<>
- inline const char *rfind(const char *st, char ch)
- {
- return std::strrchr(st,ch);
- }
- //----------------------------------------------------------------------------
- template<>
- inline const wchar_t *rfind(const wchar_t *st, wchar_t ch)
- {
- return std::wcsrchr(st,ch);
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *rfind(charT *st, charT ch)
- {
- return const_cast<charT*>(rfind(const_cast<const charT *>(st), ch));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a first occurrence of any character from
- // specified set in string (generic strpbrk)
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *find_first_of(const charT *st, const charT *set)
- {
- for(; *st; st++)
- for(const charT *p = set; *p; p++) if(*st == *p) return st;
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<>
- inline const char *find_first_of(const char *st, const char *set)
- {
- return std::strpbrk(st, set);
- }
- //----------------------------------------------------------------------------
- template<>
- inline const wchar_t *find_first_of(const wchar_t *st, const wchar_t *set)
- {
- return std::wcspbrk(st, set);
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *find_first_of(charT *st, const charT *set)
- {
- return const_cast<charT*>(find_first_of(const_cast<const charT *>(st), set));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a first character in a string that does NOT belong
- // to a set (generic strspn, that returns pointer instead of index)
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *find_first_not_of(const charT *st, const charT *set)
- {
- for(; *st; st++)
- for(const charT *p = set; *p; p++) if(*st != *p) return st;
- return nullptr;
- }
- //----------------------------------------------------------------------------
- template<>
- inline const char *find_first_not_of(const char *st, const char *set)
- {
- return st + std::strspn(st, set);
- }
- //----------------------------------------------------------------------------
- template<>
- inline const wchar_t *find_first_not_of(const wchar_t *st, const wchar_t *set)
- {
- return st + std::wcsspn(st, set);
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *find_first_not_of(charT *st, const charT *set)
- {
- return const_cast<charT*>(find_first_not_of(const_cast<const charT *>(st), set));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a last occurrence of any character from specified set in string
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *find_last_of(const charT *st, const charT *set)
- {
- const charT *p = end(st) - 1;
- while(p >= st && !find(set, *p)) p--;
- return p >= st ? p : nullptr;
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *find_last_of(charT *st, const charT *set)
- {
- return const_cast<charT*>(find_last_of(const_cast<const charT *>(st), set));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Find a last character in a string that does NOT belong to a set
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *find_last_not_of(const charT *st, const charT *set)
- {
- const charT *p = end(st) - 1;
- while(p >= st && find(set, *p)) p--;
- return p >= st ? p : nullptr;
- }
- //----------------------------------------------------------------------------
- template<class charT>
- inline charT *find_last_not_of(charT *st, const charT *set)
- {
- return const_cast<charT*>(find_last_not_of(const_cast<const charT *>(st), set));
- }
- //----------------------------------------------------------------------------
- //----------------------------------------------------------------------------
- // Skip all occurrences of the specified character at the begin of the string
- //----------------------------------------------------------------------------
- template<class charT>
- const charT *skip(const charT *p, charT ch)
- {
- while(*p && *p == ch) p++;
- return p;
- }
- //----------------------------------------------------------------------------
- template<class charT>
- charT *skip(charT *p, charT ch)
- {
- return const_cast<charT*>(skip(const_cast<const charT *>(p), ch));
- }
- //----------------------------------------------------------------------------
- }} // namespace
- #endif // header guard
|