//************************************************************************************************* //************************************************************************************************* // // STRINGS // //************************************************************************************************* //************************************************************************************************* #if !defined(__XSTRINGARRAY_H__) #define __XSTRINGARRAY_H__ #include #include "XToolsCommon.h" #include "XObjArray.h" #include "XString.h" template struct _xstringarray__char_type; template struct _xstringarray__char_type { // typedef const char* type; static const typename T::char_t* getCharPtr(const T& t) { return t.s(); } }; template struct _xstringarray__char_type { static const T* getCharPtr(T* t) { return t; } }; //template //struct _xstringarray__char_type //{ // static const T* getCharPtr(const T* t) { return t; } //}; template struct _xstringarray__char_type { static const T* getCharPtr(T* t) { return t; } }; template struct _xstringarray__char_type { static const T* getCharPtr(const T* t) { return t; } }; //#define XStringArraySuper XObjArray template class XStringArray_/* : public XStringArraySuper*/ { protected: XObjArray array; public: typedef XStringClass_ XStringClass; XStringArray_() : array() {}; size_t size() const { return array.size(); } void setEmpty() { array.setEmpty(); } bool isEmpty() const { return this->size() == 0 ; } bool notEmpty() const { return this->size() > 0 ; } // #define enable_if _xtools_enable_if_t /* [] */ template const XStringClass& operator [](IntegralType i) const { return array[i]; } template XStringClass& operator [](IntegralType i) { return array[i]; } /* ElementAt */ template const XStringClass& elementAt(IntegralType i) const { return array[i]; } template XStringClass& elementAt(IntegralType i) { return array[i]; } template XStringClass ConcatAll(const Type1& Separator, const Type2& Prefix, const Type3& Suffix) const { size_t i; XStringClass s; if ( array.size() > 0 ) { s.takeValueFrom(Prefix); s += array.ElementAt(0); for ( i=1 ; i XStringClass ConcatAll(const Type1& Separator) const { return ConcatAll(Separator, "", ""); } template bool Equal(const OtherXStringArrayClass &aStrings) const { size_t ui; if ( array.size() != aStrings.size() ) return false; for ( ui=0 ; ui bool operator ==(const OtherXStringArrayClass &aXStrings) const { return Equal(aXStrings); } template bool operator !=(const OtherXStringArrayClass& aXStrings) const { return !Equal(aXStrings); } /* contains */ template bool contains(const CharType* s) const { for ( size_t i=0 ; i bool contains(const OtherXStringClass &S) const { return contains(S.s()); } /* containsIC */ template bool containsIC(const CharType* s) const { for ( size_t i=0 ; i bool containsIC(const OtherXStringClass &S) const { return containsIC(S.s()); } /* ContainsStartWithIC */ template bool containsStartWithIC(const CharType* s) const { for ( size_t i=0 ; i bool containsStartWithIC(const OtherXStringClass &S) const { return ContainsStartWithIC(S.s()); } template bool Same(const OtherXStringArrayClass &aStrings) const { size_t i; for ( i=0 ; isize() ; i+=1 ) { if ( !aStrings.contains(array.ElementAt(i)) ) return false; } for ( i=0 ; i void AddStrings(const CharType* Val1, ...) { va_list va; const wchar_t *p; { XStringClass* newS = new XStringClass; newS->takeValueFrom(Val1); AddReference(newS, true); } va_start(va, Val1); p = VA_ARG(va, const CharType*); while ( p != nullptr ) { XStringClass* newS = new XStringClass; newS->takeValueFrom(Val1); AddReference(newS, true); p = VA_ARG(va, const CharType*); } va_end(va); } void AddNoNull(const XStringClass &aString) { if ( !aString.isEmpty() ) array.AddCopy(aString); } void AddEvenNull(const XStringClass &aString) { array.AddCopy(aString); } template void Add(const CharType* s) { XStringClass* xstr = new XStringClass; xstr->strcpy(s); array.AddReference(xstr, true); } template void Add(const XStringClass1 &aString) { Add(aString.s()); } template void insertAtPos(const XStringClass1 &aString, size_t pos) { array.InsertRef(new XStringClass1(aString), pos, true); } void AddReference(XStringClass *newElement, bool FreeIt) { array.AddReference(newElement, FreeIt); } void insertReferenceAtPos(XStringClass *newElement, size_t pos, bool FreeIt) { array.InsertRef(newElement, pos, FreeIt); } template void import(const XStringArray_ &aStrings) { size_t i; for ( i=0 ; i 0 ) { size_t i = array.size(); do { i--; if ( array[i] == aString ) { array.RemoveAtIndex(i); break; } } while ( i > 0 ); } } void removeAtPos(size_t pos) { array.RemoveAtIndex(pos); } void removeIC(const XStringClass &aString) { if ( array.size() > 0 ) { size_t i = array.size(); do { i--; if ( array[i].equalIC(aString) ) { array.RemoveAtIndex(i); break; } } while ( i > 0 ); } } XStringArrayClass trimEachString() { for ( size_t i=0 ; i { }; extern const XString8Array NullXString8Array; class XString16Array : public XStringArray_ { }; extern const XString16Array NullXString16Array; class XString32Array : public XStringArray_ { }; extern const XString32Array NullXString32Array; class XStringWArray : public XStringArray_ { }; extern const XStringWArray NullXStringWArray; // //template //XStringArrayClass Split(const XStringClass1& S) //{ // return Split(S, ", "_XS8); //}; //template template XStringArrayClass Split(Type1 S, const Type2 Separator) { XStringArrayClass xsArray; auto s = _xstringarray__char_type::getCharPtr(S); auto separator = _xstringarray__char_type::getCharPtr(Separator); // typename _xstringarray__char_type::type separator = Separator; size_t separatorLength = length_of_utf_string(separator); if ( separatorLength == 0 ) { typename XStringArrayClass::XStringClass* xstr; xstr = new typename XStringArrayClass::XStringClass; xstr->takeValueFrom(S); xsArray.AddReference(xstr, true); return xsArray; } // typename _xstringarray__char_type::type s = S; // const CharType1* s = S; char32_t char32 = 1; do { while ( XStringAbstract__ncompare(s, separator, separatorLength, false) == 0 ) { // I have to implement a move_forward_one_char in unicode_conversions, as we don't care about char32 for ( size_t i = 0 ; i < separatorLength ; i++ ) s = get_char32_from_string(s, &char32); } if ( !*s ) return xsArray; auto t = s; // typename _xstringarray__char_type::type t = s; // const CharType1* t = s; size_t nb = 0; while ( char32 && XStringAbstract__ncompare(t, separator, separatorLength, false) != 0 ) { nb++; t = get_char32_from_string(t, &char32); } typename XStringArrayClass::XStringClass* xstr; xstr = new typename XStringArrayClass::XStringClass; xstr->strncpy(s, nb); xsArray.AddReference(xstr, true); // s = get_char32_from_string(t, &char32); s = t; // Consume the separator we found for ( size_t i = 0 ; i < separatorLength ; i++ ) s = get_char32_from_string(s, &char32); } while ( char32 ); return xsArray; // // // // TODO : Allocating temporary strings could be avoided by using low level function from unicode_conversions // typename XStringArrayClass::XStringClass SS; // SS.takeValueFrom(S); // typename XStringArrayClass::XStringClass XSeparator; // SS.takeValueFrom(Separator); // return Split(SS, XSeparator); }; template XStringArrayClass Split(Type1 S) { return Split(S, ", "); }; // //template //XStringArrayClass Split(const XStringClass1& S, const XStringClass2& Separator) //{ // return Split(S.s(), Separator.s()); //// //// XStringArrayClass Ss; //// size_t idxB, idxE; //// //// if ( Separator.length() == 0 ) { //// Ss.Add(S); //// return Ss; //// } //// idxB = 0; //// idxE = S.indexOf(Separator, idxB); //// while ( idxE != MAX_XSIZE ) { //// Ss.Add(S.subString(idxB, idxE-idxB)); //// idxB = idxE + Separator.length(); //// idxE = S.indexOf(Separator, idxB); //// } //// if ( idxB < S.length() ) Ss.Add(S.subString(idxB, S.length()-idxB)); //// return Ss; //}; // // //template //XStringArrayClass Split(const XStringClass1& S) //{ // return Split(S, ", "_XS8); //}; #endif