diff --git a/uppsrc/Core/BiCont.h b/uppsrc/Core/BiCont.h index ced6ec63a..0f0be96fe 100644 --- a/uppsrc/Core/BiCont.h +++ b/uppsrc/Core/BiCont.h @@ -12,8 +12,8 @@ protected: void ReAlloc(int newalloc); void Add0(); void DeepCopy0(const BiVector& src); - T *AddHead0() { AssertMoveable(); Add0(); return &vector[start = Ix(alloc - 1)/*(start + alloc - 1) % alloc*/]; } - T *AddTail0() { AssertMoveable(); Add0(); return &vector[EI()]; } + T *AddHead0() { Add0(); return &vector[start = Ix(alloc - 1)/*(start + alloc - 1) % alloc*/]; } + T *AddTail0() { Add0(); return &vector[EI()]; } void Zero() { start = items = alloc = 0; vector = NULL; } void Free(); void Pick(BiVector&& x) { vector = pick(x.vector); start = x.start; items = x.items; @@ -21,6 +21,8 @@ protected: void Copy(T *dst, int start, int count) const; public: + static_assert(is_trivially_relocatable || is_upp_guest); + int GetCount() const { return items; } bool IsEmpty() const { return items == 0; } void Clear(); diff --git a/uppsrc/Core/Complex.h b/uppsrc/Core/Complex.h index 6d9c47f15..688a1b8ec 100644 --- a/uppsrc/Core/Complex.h +++ b/uppsrc/Core/Complex.h @@ -54,4 +54,6 @@ inline bool IsInf(const Complex& x) { return IsInf(x.real()) || IsInf(x.i inline bool IsFin(const Complex& x) { return IsFin(x.real()) && IsFin(x.imag()); } VALUE_COMPARE(Complex) -NTL_MOVEABLE(Complex) + +template <> inline constexpr bool is_trivially_relocatable = true; + diff --git a/uppsrc/Core/Core.h b/uppsrc/Core/Core.h index f23aa74b9..31f9830a3 100644 --- a/uppsrc/Core/Core.h +++ b/uppsrc/Core/Core.h @@ -1,7 +1,7 @@ #ifndef CORE_H #define CORE_H -#define UPP_VERSION 0x20220300 +#define UPP_VERSION 0x20240900 #ifndef flagMT #define flagMT // MT is now always on @@ -410,12 +410,6 @@ String AsString(const i16x8& x); String AsString(const i8x16& x); #endif -#ifdef PLATFORM_WIN32 -NTL_MOVEABLE(POINT) -NTL_MOVEABLE(SIZE) -NTL_MOVEABLE(RECT) -#endif - } #if (defined(TESTLEAKS) || defined(HEAPDBG)) && defined(COMPILER_GCC) && defined(UPP_HEAP) diff --git a/uppsrc/Core/JSON.cpp b/uppsrc/Core/JSON.cpp index 5ff1930df..69aac239e 100644 --- a/uppsrc/Core/JSON.cpp +++ b/uppsrc/Core/JSON.cpp @@ -65,7 +65,7 @@ Value ParseJSON(const char *s) String AsJSON(Time tm) { - return IsNull(tm) ? "null" : "\"\\/Date(" + AsString(1000 * (tm - Time(1970, 1, 1))) + ")\\/\""; + return IsNull(tm) ? String("null") : "\"\\/Date(" + AsString(1000 * (tm - Time(1970, 1, 1))) + ")\\/\""; } String AsJSON(Date dt) diff --git a/uppsrc/Core/LangInfo.cpp b/uppsrc/Core/LangInfo.cpp index 2cd362f57..1910a43fb 100644 --- a/uppsrc/Core/LangInfo.cpp +++ b/uppsrc/Core/LangInfo.cpp @@ -444,7 +444,7 @@ String LanguageInfo::FormatDouble(double value, int digits, int FD_flags, int fi return Null; return NlsFormatRaw(UPP::FormatDouble(value, digits, FD_flags), FD_flags & FD_NOTHSEPS ? String() : thousand_separator, - FD_flags & FD_COMMA ? "," : decimal_point); + FD_flags & FD_COMMA ? String(",") : decimal_point); } String LanguageInfo::FormatDate(Date date) const diff --git a/uppsrc/Core/MIME.cpp b/uppsrc/Core/MIME.cpp index 44590f305..c3c7d89e8 100644 --- a/uppsrc/Core/MIME.cpp +++ b/uppsrc/Core/MIME.cpp @@ -233,13 +233,13 @@ String FileExtToMIME(const String& ext) if(*h == '.') h = h.Mid(1); int q = sEXT().Find(h); - return q >= 0 ? sMIME()[q] : "application/octet-stream"; + return q >= 0 ? sMIME()[q] : String("application/octet-stream"); } String MIMEToFileExt(const String& mime) { int q = sMIME().Find(ToLower(mime)); - return q >= 0 ? sEXT()[q] : "bin"; + return q >= 0 ? sEXT()[q] : String("bin"); } } diff --git a/uppsrc/Core/Mem.h b/uppsrc/Core/Mem.h index bc16c9d0b..537e73843 100644 --- a/uppsrc/Core/Mem.h +++ b/uppsrc/Core/Mem.h @@ -330,14 +330,12 @@ void memcpy128(void *p, const void *q, size_t count) template void memcpy_t(void *t, const T *s, size_t count) { -#ifdef CPU_X86 if((sizeof(T) & 15) == 0) memcpy128(t, s, count * (sizeof(T) >> 4)); else if((sizeof(T) & 7) == 0) memcpy64(t, s, count * (sizeof(T) >> 3)); else -#endif if((sizeof(T) & 3) == 0) memcpy32(t, s, count * (sizeof(T) >> 2)); else diff --git a/uppsrc/Core/String.h b/uppsrc/Core/String.h index 073f7a20c..01cfd4586 100644 --- a/uppsrc/Core/String.h +++ b/uppsrc/Core/String.h @@ -343,7 +343,7 @@ public: ~String0() { Free(); } }; -class String : public Moveable > { +class String : Moveable, public AString { void Swap(String& b) { String0::Swap(b); } #ifdef _DEBUG @@ -799,7 +799,7 @@ public: // WString0& operator=(const WString0& s) { Free(); Set0(s); return *this; } }; -class WString : public Moveable > +class WString : Moveable, public AString { void Swap(WString& b) { WString0::Swap(b); } diff --git a/uppsrc/Core/Topt.h b/uppsrc/Core/Topt.h index fbb24e49a..8339b5e4f 100644 --- a/uppsrc/Core/Topt.h +++ b/uppsrc/Core/Topt.h @@ -130,74 +130,108 @@ inline void Fill(unsigned char *t, const unsigned char *lim, const unsigned char inline void Copy(unsigned char *dst, const unsigned char *src, const unsigned char *lim) { memcpy8(dst, src, size_t((byte *)lim - (byte *)src)); } -#ifdef NO_MOVEABLE_CHECK +template +inline void DeepCopyConstructFill(T *t, const T *end, const T& x) { + while(t != end) + new(t++) T(clone(x)); +} template -inline void AssertMoveable(T *) {} +inline void Construct(T *t, const T *lim) { + while(t < lim) + new(t++) T; +} -#define MoveableTemplate(T) - -template -class Moveable : public B +template +inline void Destruct(T *t) { -}; + t->~T(); +} template -struct Moveable_ { -}; - -#define NTL_MOVEABLE(T) - -#else +inline void Destroy(T *t, const T *end) +{ + while(t != end) + Destruct(t++); +} template -inline void AssertMoveablePtr(T, T) {} - -template -inline void AssertMoveable0(T *t) { AssertMoveablePtr(&**t, *t); } -// COMPILATION ERROR HERE MEANS TYPE T WAS NOT MARKED AS Moveable +struct TriviallyRelocatable {}; template -struct Moveable : public B { - friend void AssertMoveable0(T *) {} -}; +struct Moveable : TriviallyRelocatable {}; + +template // backward compatiblity +struct Moveable_ : Moveable {}; template -struct Moveable_ { - friend void AssertMoveable0(T *) {} -}; +inline constexpr bool is_trivially_relocatable = std::is_trivially_copyable_v || + std::is_base_of_v, T>; template -inline void AssertMoveable(T *t = 0) { if(t) AssertMoveable0(t); } +inline constexpr bool is_upp_guest = false; -#if defined(COMPILER_MSC) || defined(COMPILER_GCC) && (__GNUC__ < 4 || __GNUC_MINOR__ < 1) - #define NTL_MOVEABLE(T) inline void AssertMoveable0(T *) {} -#else - #define NTL_MOVEABLE(T) template<> inline void AssertMoveable(T *) {} -#endif +template +inline typename std::enable_if_t> Move(T *dst, T *src) +{ + memcpy(dst, src, sizeof(T)); +} -#endif +template +inline typename std::enable_if_t> Move(T *dst, T *src) +{ + new(dst) T(pick(*src)); + Destruct(src); +} -NTL_MOVEABLE(bool) -NTL_MOVEABLE(char) -NTL_MOVEABLE(signed char) -NTL_MOVEABLE(unsigned char) -NTL_MOVEABLE(short) -NTL_MOVEABLE(unsigned short) -NTL_MOVEABLE(int) -NTL_MOVEABLE(unsigned int) -NTL_MOVEABLE(long) -NTL_MOVEABLE(unsigned long) -NTL_MOVEABLE(int64) -NTL_MOVEABLE(uint64) -NTL_MOVEABLE(float) -NTL_MOVEABLE(double) -NTL_MOVEABLE(void *) -NTL_MOVEABLE(const void *) +template +inline void InMove(T *dst, T *src, int n) +{ + if(is_trivially_relocatable) + memmove(dst, src, n * sizeof(T)); + else { + if(n <= 0) + return; + dst += n - 1; + T *s = src + n - 1; + for(;;) { + Move(dst, s); + if(s == src) break; + dst--; + s--; + } + } +} -#if defined(_NATIVE_WCHAR_T_DEFINED) || defined(COMPILER_GCC) -NTL_MOVEABLE(wchar_t) -#endif +template +inline void ReMove(T *dst, T *src, int n) +{ + if(is_trivially_relocatable) + memmove(dst, src, n * sizeof(T)); + else { + T *lim = src + n; + while(src != lim) + Move(dst++, src++); + } +} + +template +inline void Relocate(T *dst, T *src, int n) +{ + if(is_trivially_relocatable) + memcpy_t(dst, src, n); + else { + T *lim = src + n; + while(src != lim) + Move(dst++, src++); + } +} + +template +inline void DeepCopyConstruct(T *t, const S *s, const S *end) { + while(s != end) + new (t++) T(clone(*s++)); +} template class WithClone : public B { @@ -216,8 +250,7 @@ public: }; template -class MoveableAndDeepCopyOption : public B { - friend void AssertMoveable0(T *) {} +class MoveableAndDeepCopyOption : public Moveable { #ifdef DEPRECATED friend T& operator<<=(T& dest, const T& src) { if(&dest != &src) { (&dest)->~T(); ::new(&dest) T(src, 1); } return dest; } @@ -421,9 +454,6 @@ public: STL_ITERATOR_COMPATIBILITY }; -unsigned Pow2Bound(unsigned i); -unsigned PrimeBound(unsigned i); - hash_t memhash(const void *ptr, size_t size); template @@ -480,12 +510,6 @@ public: template CombineHash& operator<<(const T& x) { Do(x); return *this; } }; -template -struct Data_S_ : Moveable< Data_S_ > -{ - byte filler[size]; -}; - template bool IsEqualMap(const C& a, const C& b) { diff --git a/uppsrc/Core/Tuple.h b/uppsrc/Core/Tuple.h index f85648342..e56db6032 100644 --- a/uppsrc/Core/Tuple.h +++ b/uppsrc/Core/Tuple.h @@ -155,6 +155,21 @@ public: Tuple(const Args... args) : Base(args...) {}; }; +template +inline constexpr bool is_trivially_relocatable> = is_trivially_relocatable && + is_trivially_relocatable; + +template +inline constexpr bool is_trivially_relocatable> = is_trivially_relocatable && + is_trivially_relocatable && + is_trivially_relocatable; + +template +inline constexpr bool is_trivially_relocatable> = is_trivially_relocatable && + is_trivially_relocatable && + is_trivially_relocatable && + is_trivially_relocatable; + template Tuple MakeTuple(const Args... args) { return Tuple(args...); diff --git a/uppsrc/Core/Value.h b/uppsrc/Core/Value.h index c83684be5..61ee3d82c 100644 --- a/uppsrc/Core/Value.h +++ b/uppsrc/Core/Value.h @@ -77,7 +77,7 @@ class AssignValueTypeNo : public ValueType {}; template dword GetValueTypeNo() { return ValueTypeNo((T*)NULL); } -class Value : Moveable_ { +class Value : Moveable { public: class Void { protected: @@ -292,7 +292,7 @@ public: friend void Swap(Value& a, Value& b) { Swap(a.data, b.data); } - typedef ConstIteratorOf> const_iterator; + typedef const Value *const_iterator; const_iterator begin() const { return GetVA().begin(); } const_iterator end() const { return GetVA().end(); } diff --git a/uppsrc/Core/Vcont.h b/uppsrc/Core/Vcont.h index f6fc2b757..140dbec00 100644 --- a/uppsrc/Core/Vcont.h +++ b/uppsrc/Core/Vcont.h @@ -9,33 +9,6 @@ void BREAK_WHEN_PICKED(T& x) } #endif -template -inline void DeepCopyConstructFill(T *t, const T *end, const T& x) { - while(t != end) - new(t++) T(clone(x)); -} - -template -inline void Construct(T *t, const T *lim) { - while(t < lim) - new(t++) T; -} - -template -inline void Destroy(T *t, const T *end) -{ - while(t != end) { - t->~T(); - t++; - } -} - -template -inline void DeepCopyConstruct(T *t, const S *s, const S *end) { - while(s != end) - new (t++) T(clone(*s++)); -} - template class Buffer : Moveable< Buffer > { T *ptr; @@ -165,6 +138,8 @@ template class Index; template class Vector : public MoveableAndDeepCopyOption< Vector > { + static_assert(is_trivially_relocatable || is_upp_guest); + T *vector; int items; int alloc; @@ -283,9 +258,8 @@ public: ~Vector() { Free(); return; // Constraints: - AssertMoveable((T *)0); // T must be moveable } - + // Pick assignment & copy. Picked source can only do Clear(), ~Vector(), operator=, operator <<= Vector(Vector&& v) { Pick(pick(v)); } void operator=(Vector&& v) { if(this != &v) { Free(); Pick(pick(v)); } } diff --git a/uppsrc/Core/Vcont.hpp b/uppsrc/Core/Vcont.hpp index ba8608314..6d0950a3b 100644 --- a/uppsrc/Core/Vcont.hpp +++ b/uppsrc/Core/Vcont.hpp @@ -122,7 +122,7 @@ bool Vector::ReAlloc(int newalloc) alloc = newalloc == INT_MAX ? INT_MAX // maximum alloc reached : (int)((sz - sz0) / sizeof(T) + newalloc); // adjust alloc to real memory size if(vector && newvector) - memcpy_t((T *)newvector, vector, items); + Relocate((T *)newvector, vector, items); vector = (T *)newvector; return alloced; } @@ -306,7 +306,7 @@ void Vector::Remove(int q, int count) { ASSERT(q >= 0 && q <= items - count && count >= 0); if(count == 0) return; Destroy(vector + q, vector + q + count); - memmove((void *)(vector + q), (void *)(vector + q + count), (items - q - count) * sizeof(T)); + ReMove(vector + q, vector + q + count, items - q - count); items -= count; } @@ -319,18 +319,17 @@ void Vector::Remove(const int *sorted_list, int n) for(;;) { ASSERT(pos < items); if(pos == *sorted_list) { - (vector + pos)->~T(); + Destruct(vector + pos); pos++; sorted_list++; if(--n == 0) break; ASSERT(*sorted_list >= pos); } else - *((Data_S_*)vector + npos++) - = *((Data_S_*)vector + pos++); + Move(vector + npos++, vector + pos++); } while(pos < items) - *((Data_S_*)vector + npos++) = *((Data_S_*)vector + pos++); + Move(vector + npos++, vector + pos++); items = npos; } @@ -347,15 +346,15 @@ void Vector::RemoveIf(Condition c) int i = 0; for(; i < items; i++) // run to the first element without moving if(c(i)) { - (vector + i)->~T(); + Destruct(vector + i); break; } int ti = i++; for(; i < items; i++) if(c(i)) - (vector + i)->~T(); + Destruct(vector + i); else - *((Data_S_*)vector + ti++) = *((Data_S_*)vector + i); + Move(vector + ti++, vector + i); items = ti; } @@ -368,14 +367,14 @@ void Vector::RawInsert(int q, int count) if(items + count > alloc) { T *newvector = RawAlloc(alloc = max(alloc + count, int(alloc + ((unsigned)alloc >> 1)))); if(vector) { - memcpy_t(newvector, vector, q); - memcpy_t(newvector + q + count, vector + q, items - q); + Relocate(newvector, vector, q); + Relocate(newvector + q + count, vector + q, items - q); RawFree(vector); } vector = newvector; } else - memmove((void *)(vector + q + count), (void *)(vector + q), (items - q) * sizeof(T)); + InMove(vector + q + count, vector + q, items - q); items += count; } @@ -442,7 +441,7 @@ void Vector::Insert(int i, Vector&& v) { ASSERT(!vector || v.vector != vector); if(v.items) { RawInsert(i, v.items); - memcpy_t(vector + i, v.vector, v.items); + Relocate(vector + i, v.vector, v.items); } RawFree(v.vector); v.Zero(); @@ -455,7 +454,7 @@ void Vector::InsertSplit(int i, Vector& v, int from) int n = v.GetCount() - from; if(n) { RawInsert(i, n); - memcpy_t(vector + i, v.vector + from, n); + Relocate(vector + i, v.vector + from, n); v.items = from; } } @@ -737,10 +736,10 @@ void BiVector::ReAlloc(int newalloc) { if(items) { int end = start + items; if(end <= alloc) - memcpy_t(newvector, vector + start, end - start); + Relocate(newvector, vector + start, end - start); else { - memcpy_t(newvector, vector + start, alloc - start); - memcpy_t(newvector + alloc - start, vector, end - alloc); + Relocate(newvector, vector + start, alloc - start); + Relocate(newvector + alloc - start, vector, end - alloc); } MemoryFree(vector); } diff --git a/uppsrc/Core/XML.h b/uppsrc/Core/XML.h index cbe77b9c3..37d3d68ba 100644 --- a/uppsrc/Core/XML.h +++ b/uppsrc/Core/XML.h @@ -174,7 +174,7 @@ public: XmlParser(Stream& in); }; -class XmlNode : Moveable< XmlNode, DeepCopyOption > { +class XmlNode : Moveable, DeepCopyOption { int type; String text; Array node; diff --git a/uppsrc/CtrlLib/AKeys.h b/uppsrc/CtrlLib/AKeys.h index 9221b0bf9..e8a21d49f 100644 --- a/uppsrc/CtrlLib/AKeys.h +++ b/uppsrc/CtrlLib/AKeys.h @@ -3,8 +3,6 @@ struct KeyInfo { dword key[4]; }; -NTL_MOVEABLE(KeyInfo) - void RegisterKeyBinding(const char *group, const char *id, KeyInfo& (*info)()); KeyInfo& AK_NULL(); diff --git a/uppsrc/Painter/BufferPainter.h b/uppsrc/Painter/BufferPainter.h index dfcb37b7f..f83274021 100644 --- a/uppsrc/Painter/BufferPainter.h +++ b/uppsrc/Painter/BufferPainter.h @@ -148,7 +148,7 @@ private: byte cap; bool invert; }; - struct Attr : Moveable { + struct Attr : Moveable, SimpleAttr { int mtx_serial; // used to detect changes to speedup preclip WithDeepCopy> color_stop; diff --git a/uppsrc/RichText/RichText.h b/uppsrc/RichText/RichText.h index 02fe05d46..5d39d13d3 100644 --- a/uppsrc/RichText/RichText.h +++ b/uppsrc/RichText/RichText.h @@ -73,7 +73,7 @@ inline Size operator/(Size sz, Zoom m) return Size(sz.cx / m, sz.cy / m); } -struct PageY : Moveable > { +struct PageY : Moveable, RelOps { int page; int y; diff --git a/uppsrc/ide/Debuggers/Pdb.h b/uppsrc/ide/Debuggers/Pdb.h index dac4114f3..f581ce25a 100644 --- a/uppsrc/ide/Debuggers/Pdb.h +++ b/uppsrc/ide/Debuggers/Pdb.h @@ -90,7 +90,7 @@ struct Pdb : Debugger, ParentCtrl { bool reference = false; // this is reference }; - struct Val : Moveable { + struct Val : Moveable, TypeInfo { bool array = false; bool rvalue = false; // data is loaded from debugee (if false, data pointed to by address) bool udt = false; // user defined type (e.g. struct..) diff --git a/uppsrc/ide/t.cpp b/uppsrc/ide/t.cpp index 954530646..e2c6475f4 100644 --- a/uppsrc/ide/t.cpp +++ b/uppsrc/ide/t.cpp @@ -5,7 +5,7 @@ struct FileLine : Moveable { int line; }; -struct LngEntry : Moveable > { +struct LngEntry : Moveable, DeepCopyOption { bool added; VectorMap text; Vector fileline; diff --git a/uppsrc/plugin/png/pngupp.cpp b/uppsrc/plugin/png/pngupp.cpp index 217570108..8358257e9 100644 --- a/uppsrc/plugin/png/pngupp.cpp +++ b/uppsrc/plugin/png/pngupp.cpp @@ -41,8 +41,6 @@ static void png_user_warning_fn(png_structp png_ptr, png_const_charp warning_msg LLOG("png warning: " << warning_msg); } -NTL_MOVEABLE(png_color) - static Size GetDotSize(Size pixel_size, png_uint_32 x_ppm, png_uint_32 y_ppm, int unit_type) { if(unit_type != 1 || !x_ppm || !y_ppm)