ultimatepp/uppsrc/Core/SplitMerge.cpp
cxl 040913b8fd Core: Split/Join/Merge refactored
git-svn-id: svn://ultimatepp.org/upp/trunk@7285 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2014-04-21 15:22:49 +00:00

313 lines
8.5 KiB
C++

#include "Core.h"
NAMESPACE_UPP
template <class S, class Char, class F>
Vector<S> SplitGeneric(int maxcount, const F& delim, const Char *s, bool ignoreempty = true)
{
Vector<S> r;
r.Reserve(min(maxcount, 8));
const Char *t = s;
while(*t && r.GetCount() < maxcount) {
const Char *q = delim(t);
if(q) {
if(!ignoreempty || t > s)
r.Add().Set(s, t - s); // This is faster than r.Add(String(s, t))...
t = s = q;
}
else
t++;
}
if((!ignoreempty || t > s) && r.GetCount() < maxcount)
r.Add().Set(s, t - s);
return r;
}
Vector<String> Split(int maxcount, const char *s, const char * (*text_filter)(const char *), bool ignoreempty)
{
return SplitGeneric<String>(maxcount, text_filter, s, ignoreempty);
}
Vector<String> Split(int maxcount, const char *s, int (*filter)(int), bool ignoreempty)
{
struct {
int (*filter)(int);
const char *operator()(const char *s) const { return (*filter)((byte)*s) ? s + 1 : NULL; }
} delim;
delim.filter = filter;
return SplitGeneric<String>(maxcount, delim, s, ignoreempty);
}
Vector<String> Split(int maxcount, const char *s, int chr, bool ignoreempty)
{
struct {
int chr;
const char *operator()(const char *s) const { return *s == chr ? s + 1 : NULL; }
} delim;
delim.chr = chr;
return SplitGeneric<String>(maxcount, delim, s, ignoreempty);
}
Vector<String> Split(int maxcount, const char *s, const char *text, bool ignoreempty)
{
struct {
const char *ds;
int l;
const char *operator()(const char *s) const { return strncmp(s, ds, l) == 0 ? s + l : NULL; }
} delim;
delim.ds = text;
delim.l = strlen(text);
return delim.l ? SplitGeneric<String>(maxcount, delim, s, ignoreempty) : Vector<String>();
}
Vector<String> Split(const char *s, const char * (*text_filter)(const char *), bool ignoreempty)
{
return Split(INT_MAX, s, text_filter, ignoreempty);
}
Vector<String> Split(const char *s, int (*filter)(int), bool ignoreempty)
{
return Split(INT_MAX, s, filter, ignoreempty);
}
Vector<String> Split(const char *s, int chr, bool ignoreempty)
{
return Split(INT_MAX, s, chr, ignoreempty);
}
Vector<String> Split(const char *s, const char *text, bool ignoreempty)
{
return Split(INT_MAX, s, text, ignoreempty);
}
Vector<WString> Split(int maxcount, const wchar *s, const wchar * (*text_filter)(const wchar *), bool ignoreempty)
{
return SplitGeneric<WString>(maxcount, text_filter, s, ignoreempty);
}
Vector<WString> Split(int maxcount, const wchar *s, int (*filter)(int), bool ignoreempty)
{
struct {
int (*filter)(int);
const wchar *operator()(const wchar *s) const { return (*filter)((byte)*s) ? s + 1 : NULL; }
} delim;
delim.filter = filter;
return SplitGeneric<WString>(maxcount, delim, s, ignoreempty);
}
Vector<WString> Split(int maxcount, const wchar *s, int chr, bool ignoreempty)
{
struct {
int chr;
const wchar *operator()(const wchar *s) const { return *s == chr ? s + 1 : NULL; }
} delim;
delim.chr = chr;
return SplitGeneric<WString>(maxcount, delim, s, ignoreempty);
}
int w_strncmp(const wchar *s, const wchar *t, int n)
{
while(*s && *t && n > 0) {
int q = (int)(uint16)*s - (int)(uint16)*t;
if(q)
return q;
s++;
t++;
n--;
}
return 0;
}
Vector<WString> Split(int maxcount, const wchar *s, const wchar *text, bool ignoreempty)
{
struct {
const wchar *ds;
int l;
const wchar *operator()(const wchar *s) const { return w_strncmp(s, ds, l) == 0 ? s + l : NULL; }
} delim;
delim.ds = text;
delim.l = wstrlen(text);
return delim.l ? SplitGeneric<WString>(maxcount, delim, s, ignoreempty) : Vector<WString>();
}
Vector<WString> Split(const wchar *s, int (*filter)(int), bool ignoreempty)
{
return Split(INT_MAX, s, filter, ignoreempty);
}
Vector<WString> Split(const wchar *s, int chr, bool ignoreempty)
{
return Split(INT_MAX, s, chr, ignoreempty);
}
Vector<WString> Split(const wchar *s, const wchar *text, bool ignoreempty)
{
return Split(INT_MAX, s, text, ignoreempty);
}
Vector<WString> Split(const wchar *s, const wchar * (*text_filter)(const wchar *), bool ignoreempty)
{
return SplitGeneric<WString>(INT_MAX, text_filter, s, ignoreempty);
}
String Join(const Vector<String>& im, const String& delim, bool ignoreempty) {
StringBuffer r;
for(int i = 0; i < im.GetCount(); i++)
if(!ignoreempty || im[i].GetCount()) {
if(r.GetCount())
r.Cat(delim);
r.Cat(im[i]);
}
return r;
}
WString Join(const Vector<WString>& im, const WString& delim, bool ignoreempty) {
WStringBuffer r;
for(int i = 0; i < im.GetCount(); i++)
if(!ignoreempty || im[i].GetCount()) {
if(r.GetCount())
r.Cat(delim);
r.Cat(im[i]);
}
return r;
}
static void sMergeWith(String& dest, const char *delim, const String& s)
{
if(s.GetLength()) {
if(dest.GetCount())
dest.Cat(delim);
dest.Cat(s);
}
}
#define E__TL(I) typename COMBINE(T, I)
#define E__NFIf(I) COMBINE(p, I) = r[I - 1]
#define E__NFValue(I) String& COMBINE(p, I)
#define E__PI(I) COMBINE(p, I)
#define E__NFSValue(I) const String& COMBINE(p, I)
#define E__Merge(I) sMergeWith(dest, delim, COMBINE(p, I))
#define E__NFBody(I) \
bool SplitTo(const char *s, int chr, bool ignoreempty, __List##I(E__NFValue)) \
{ \
Vector<String> r = Split(I, s, chr, ignoreempty); \
if(r.GetCount() < I) return false; \
__List##I(E__NFIf); \
return true; \
} \
bool SplitTo(const char *s, int chr, __List##I(E__NFValue)) \
{ \
return SplitTo(s, chr, true, __List##I(E__PI)); \
} \
bool SplitTo(const char *s, int (*filter)(int), bool ignoreempty, __List##I(E__NFValue)) \
{ \
Vector<String> r = Split(I, s, filter, ignoreempty); \
if(r.GetCount() < I) return false; \
__List##I(E__NFIf); \
return true; \
} \
bool SplitTo(const char *s, int (*filter)(int), __List##I(E__NFValue)) \
{ \
return SplitTo(s, filter, true, __List##I(E__PI)); \
} \
bool SplitTo(const char *s, const char *text, bool ignoreempty, __List##I(E__NFValue)) \
{ \
Vector<String> r = Split(I, s, text, ignoreempty); \
if(r.GetCount() < I) return false; \
__List##I(E__NFIf); \
return true; \
} \
bool SplitTo(const char *s, const char *text, __List##I(E__NFValue)) \
{ \
return SplitTo(s, text, true, __List##I(E__PI)); \
} \
String Merge(const char *delim, __List##I(E__NFSValue)) \
{ \
String dest; \
__List##I(E__Merge); \
return dest; \
} \
void MergeWith(String& dest, const char *delim, __List##I(E__NFSValue)) \
{ \
__List##I(E__Merge); \
} \
__Expand8(E__NFBody)
#undef E__TL
#undef E__NFIf
#undef E__NFValue
#undef E__PI
#undef E__NFBody
static void sMergeWith(WString& dest, const wchar *delim, const WString& s)
{
if(s.GetLength()) {
if(dest.GetCount())
dest.Cat(delim);
dest.Cat(s);
}
}
#define E__TL(I) typename COMBINE(T, I)
#define E__NFIf(I) COMBINE(p, I) = r[I - 1]
#define E__NFValue(I) WString& COMBINE(p, I)
#define E__PI(I) COMBINE(p, I)
#define E__NFSValue(I) const WString& COMBINE(p, I)
#define E__Merge(I) sMergeWith(dest, delim, COMBINE(p, I))
#define E__NFBody(I) \
bool SplitTo(const wchar *s, int chr, bool ignoreempty, __List##I(E__NFValue)) \
{ \
Vector<WString> r = Split(I, s, chr, ignoreempty); \
if(r.GetCount() < I) return false; \
__List##I(E__NFIf); \
return true; \
} \
bool SplitTo(const wchar *s, int chr, __List##I(E__NFValue)) \
{ \
return SplitTo(s, chr, true, __List##I(E__PI)); \
} \
bool SplitTo(const wchar *s, int (*filter)(int), bool ignoreempty, __List##I(E__NFValue)) \
{ \
Vector<WString> r = Split(I, s, filter, ignoreempty); \
if(r.GetCount() < I) return false; \
__List##I(E__NFIf); \
return true; \
} \
bool SplitTo(const wchar *s, int (*filter)(int), __List##I(E__NFValue)) \
{ \
return SplitTo(s, filter, true, __List##I(E__PI)); \
} \
bool SplitTo(const wchar *s, const wchar *text, bool ignoreempty, __List##I(E__NFValue)) \
{ \
Vector<WString> r = Split(I, s, text, ignoreempty); \
if(r.GetCount() < I) return false; \
__List##I(E__NFIf); \
return true; \
} \
bool SplitTo(const wchar *s, const wchar *text, __List##I(E__NFValue)) \
{ \
return SplitTo(s, text, true, __List##I(E__PI)); \
} \
WString Merge(const wchar *delim, __List##I(E__NFSValue)) \
{ \
WString dest; \
__List##I(E__Merge); \
return dest; \
} \
void MergeWith(WString& dest, const wchar *delim, __List##I(E__NFSValue)) \
{ \
__List##I(E__Merge); \
} \
__Expand8(E__NFBody)
#undef E__TL
#undef E__NFIf
#undef E__NFValue
#undef E__PI
#undef E__NFBody
END_UPP_NAMESPACE