#include "Core.h" namespace Upp { template Vector SplitGeneric(int maxcount, const F& delim, const Char *s, bool ignoreempty = true) { Vector 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, int(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, int(t - s)); return r; } Vector Split(int maxcount, const char *s, const char * (*text_filter)(const char *), bool ignoreempty) { return SplitGeneric(maxcount, text_filter, s, ignoreempty); } struct SplitDelimFilter__ { int (*filter)(int); const char *operator()(const char *s) const { return (*filter)((byte)*s) ? s + 1 : NULL; } }; Vector Split(int maxcount, const char *s, int (*filter)(int), bool ignoreempty) { SplitDelimFilter__ delim; delim.filter = filter; return SplitGeneric(maxcount, delim, s, ignoreempty); } struct SplitDelimChar__ { int chr; const char *operator()(const char *s) const { return *s == chr ? s + 1 : NULL; } }; Vector Split(int maxcount, const char *s, int chr, bool ignoreempty) { SplitDelimChar__ delim; delim.chr = chr; return SplitGeneric(maxcount, delim, s, ignoreempty); } struct SplitDelimText__ { const char *ds; int l; const char *operator()(const char *s) const { return strncmp(s, ds, l) == 0 ? s + l : NULL; } }; Vector Split(int maxcount, const char *s, const char *text, bool ignoreempty) { SplitDelimText__ delim; delim.ds = text; delim.l = (int)strlen(text); return delim.l ? SplitGeneric(maxcount, delim, s, ignoreempty) : Vector(); } Vector Split(const char *s, const char * (*text_filter)(const char *), bool ignoreempty) { return Split(INT_MAX, s, text_filter, ignoreempty); } Vector Split(const char *s, int (*filter)(int), bool ignoreempty) { return Split(INT_MAX, s, filter, ignoreempty); } Vector Split(const char *s, int chr, bool ignoreempty) { return Split(INT_MAX, s, chr, ignoreempty); } Vector Split(const char *s, const char *text, bool ignoreempty) { return Split(INT_MAX, s, text, ignoreempty); } Vector Split(int maxcount, const wchar *s, const wchar * (*text_filter)(const wchar *), bool ignoreempty) { return SplitGeneric(maxcount, text_filter, s, ignoreempty); } struct SplitDelimWFilter__ { int (*filter)(int); const wchar *operator()(const wchar *s) const { return (*filter)((byte)*s) ? s + 1 : NULL; } }; Vector Split(int maxcount, const wchar *s, int (*filter)(int), bool ignoreempty) { SplitDelimWFilter__ delim; delim.filter = filter; return SplitGeneric(maxcount, delim, s, ignoreempty); } struct SplitDelimWChar__ { int chr; const wchar *operator()(const wchar *s) const { return *s == chr ? s + 1 : NULL; } }; Vector Split(int maxcount, const wchar *s, int chr, bool ignoreempty) { SplitDelimWChar__ delim; delim.chr = chr; return SplitGeneric(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; } struct SplitDelimWText { const wchar *ds; int l; const wchar *operator()(const wchar *s) const { return w_strncmp(s, ds, l) == 0 ? s + l : NULL; } }; Vector Split(int maxcount, const wchar *s, const wchar *text, bool ignoreempty) { SplitDelimWText delim; delim.ds = text; delim.l = strlen__(text); return delim.l ? SplitGeneric(maxcount, delim, s, ignoreempty) : Vector(); } Vector Split(const wchar *s, int (*filter)(int), bool ignoreempty) { return Split(INT_MAX, s, filter, ignoreempty); } Vector Split(const wchar *s, int chr, bool ignoreempty) { return Split(INT_MAX, s, chr, ignoreempty); } Vector Split(const wchar *s, const wchar *text, bool ignoreempty) { return Split(INT_MAX, s, text, ignoreempty); } Vector Split(const wchar *s, const wchar * (*text_filter)(const wchar *), bool ignoreempty) { return SplitGeneric(INT_MAX, text_filter, s, ignoreempty); } template T Join_(const Vector& im, const T& delim, bool ignoreempty) { B r; bool next = false; for(int i = 0; i < im.GetCount(); i++) if(!ignoreempty || im[i].GetCount()) { if(next) r.Cat(delim); r.Cat(im[i]); next = true; } return T(r); } String Join(const Vector& im, const String& delim, bool ignoreempty) { return Join_(im, delim, ignoreempty); } WString Join(const Vector& im, const WString& delim, bool ignoreempty) { return Join_(im, delim, ignoreempty); } }