From ae979b97854a1d349842949eab4c4c79099cadd2 Mon Sep 17 00:00:00 2001 From: Alex Alabuzhev Date: Wed, 28 Jun 2017 18:08:39 +0000 Subject: [PATCH] error in file locked dialog, fmt v4.0.0, tinyxml2 v5.0.1 --- far/changelog | 8 ++ far/farlang.templ.m4 | 6 +- far/stddlg.cpp | 4 +- far/thirdparty/fmt/format.cc | 31 ++---- far/thirdparty/fmt/format.h | 149 +++++++++++++++++-------- far/thirdparty/tinyxml2/tinyxml2.cpp | 157 ++++++++++++++++++--------- far/thirdparty/tinyxml2/tinyxml2.h | 117 +++++++++++++++----- far/tinyxml.hpp | 9 ++ 8 files changed, 339 insertions(+), 142 deletions(-) diff --git a/far/changelog b/far/changelog index a3f12d9d52..1b1be94c0a 100644 --- a/far/changelog +++ b/far/changelog @@ -1,3 +1,11 @@ +drkns 28.06.2017 19:02:42 +0000 - build 4980 + +1. Ошибка отображения информации о заблокированном файле. + +2. fmt v4.0.0. + +3. TinyXML-2 v5.0.1 + drkns 25.06.2017 02:03:37 +0000 - build 4979 1. Рефакторинг. diff --git a/far/farlang.templ.m4 b/far/farlang.templ.m4 index de13d21eab..831fe0e1ae 100644 --- a/far/farlang.templ.m4 +++ b/far/farlang.templ.m4 @@ -28272,14 +28272,14 @@ upd:"opened" MObjectLockedSwitchTo "Переключиться" -"Switch to:" +"Switch to" "Přepnout na" "Gehe zu" upd:"Switch to" upd:"Switch to" -"Cambiar a:" +"Cambiar a" "Prepnúť na" -"Vai A:" +"Vai A" "Перемкнутися" MObjectLockedClose diff --git a/far/stddlg.cpp b/far/stddlg.cpp index 74acecf50e..30988ad442 100644 --- a/far/stddlg.cpp +++ b/far/stddlg.cpp @@ -568,8 +568,8 @@ operation OperationFailed(const string& Object, lng Title, const string& Descrip { Result = Message(MSG_WARNING | MSG_ERRORTYPE, msg(Title), - std::move(Msgs), - std::move(Buttons)); + Msgs, + Buttons); if(SwitchBtn) { diff --git a/far/thirdparty/fmt/format.cc b/far/thirdparty/fmt/format.cc index b2bb7687d4..09d2ea9fda 100644 --- a/far/thirdparty/fmt/format.cc +++ b/far/thirdparty/fmt/format.cc @@ -41,6 +41,9 @@ #endif #if FMT_USE_WINDOWS_H +# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# endif # if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) # include # else @@ -50,8 +53,6 @@ # endif #endif -using fmt::internal::Arg; - #if FMT_EXCEPTIONS # define FMT_TRY try # define FMT_CATCH(x) catch (x) @@ -212,16 +213,6 @@ void report_error(FormatFunc func, int error_code, } } // namespace -namespace internal { - -// This method is used to preserve binary compatibility with fmt 3.0. -// It can be removed in 4.0. -FMT_FUNC void format_system_error( - Writer &out, int error_code, StringRef message) FMT_NOEXCEPT { - fmt::format_system_error(out, error_code, message); -} -} // namespace internal - FMT_FUNC void SystemError::init( int err_code, CStringRef format_str, ArgList args) { error_code_ = err_code; @@ -455,14 +446,14 @@ void internal::FixedBuffer::grow(std::size_t) { FMT_THROW(std::runtime_error("buffer overflow")); } -FMT_FUNC Arg internal::FormatterBase::do_get_arg( +FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg( unsigned arg_index, const char *&error) { - Arg arg = args_[arg_index]; + internal::Arg arg = args_[arg_index]; switch (arg.type) { - case Arg::NONE: + case internal::Arg::NONE: error = "argument index out of range"; break; - case Arg::NAMED_ARG: + case internal::Arg::NAMED_ARG: arg = *static_cast(arg.pointer); break; default: @@ -513,11 +504,11 @@ template void internal::FixedBuffer::grow(std::size_t); template void internal::ArgMap::init(const ArgList &args); -template int internal::CharTraits::format_float( +template FMT_API int internal::CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, double value); -template int internal::CharTraits::format_float( +template FMT_API int internal::CharTraits::format_float( char *buffer, std::size_t size, const char *format, unsigned width, int precision, long double value); @@ -527,11 +518,11 @@ template void internal::FixedBuffer::grow(std::size_t); template void internal::ArgMap::init(const ArgList &args); -template int internal::CharTraits::format_float( +template FMT_API int internal::CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, double value); -template int internal::CharTraits::format_float( +template FMT_API int internal::CharTraits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, unsigned width, int precision, long double value); diff --git a/far/thirdparty/fmt/format.h b/far/thirdparty/fmt/format.h index db8e79ceea..6ee9d2a21a 100644 --- a/far/thirdparty/fmt/format.h +++ b/far/thirdparty/fmt/format.h @@ -38,10 +38,10 @@ #include #include #include -#include +#include // for std::pair // The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 30002 +#define FMT_VERSION 40000 #ifdef _SECURE_SCL # define FMT_SECURE_SCL _SECURE_SCL @@ -107,6 +107,7 @@ typedef __int64 intmax_t; #endif #if defined(__clang__) && !defined(FMT_ICC_VERSION) +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdocumentation-unknown-command" # pragma clang diagnostic ignored "-Wpadded" @@ -155,10 +156,6 @@ typedef __int64 intmax_t; # endif #endif -#if FMT_USE_RVALUE_REFERENCES -# include // for std::move -#endif - // Check if exceptions are disabled. #if defined(__GNUC__) && !defined(__EXCEPTIONS) # define FMT_EXCEPTIONS 0 @@ -246,6 +243,20 @@ typedef __int64 intmax_t; TypeName& operator=(const TypeName&) #endif +#ifndef FMT_USE_DEFAULTED_FUNCTIONS +# define FMT_USE_DEFAULTED_FUNCTIONS 0 +#endif + +#ifndef FMT_DEFAULTED_COPY_CTOR +# if FMT_USE_DEFAULTED_FUNCTIONS || FMT_HAS_FEATURE(cxx_defaulted_functions) || \ + (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1800 +# define FMT_DEFAULTED_COPY_CTOR(TypeName) \ + TypeName(const TypeName&) = default; +# else +# define FMT_DEFAULTED_COPY_CTOR(TypeName) +# endif +#endif + #ifndef FMT_USE_USER_DEFINED_LITERALS // All compilers which support UDLs also support variadic templates. This // makes the fmt::literals implementation easier. However, an explicit check @@ -259,22 +270,10 @@ typedef __int64 intmax_t; #endif #ifndef FMT_USE_EXTERN_TEMPLATES -// Clang doesn't have a feature check for extern templates so we check -// for variadic templates which were introduced in the same version. -// For GCC according to cppreference.com they were introduced in 3.3. # define FMT_USE_EXTERN_TEMPLATES \ - ((__clang__ && FMT_USE_VARIADIC_TEMPLATES) || \ - (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11)) + (FMT_CLANG_VERSION >= 209 || (FMT_GCC_VERSION >= 303 && FMT_HAS_GXX_CXX11)) #endif -// Checks if decltype v1.1 is supported -// http://en.cppreference.com/w/cpp/compiler_support -#define FMT_HAS_DECLTYPE_INCOMPLETE_RETURN_TYPES \ - (FMT_HAS_FEATURE(cxx_decltype_incomplete_return_types) || \ - (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \ - FMT_MSC_VER >= 1900 || \ - FMT_ICC_VERSION >= 1200) - #ifdef FMT_HEADER_ONLY // If header only do not use extern templates. # undef FMT_USE_EXTERN_TEMPLATES @@ -285,12 +284,16 @@ typedef __int64 intmax_t; # define FMT_ASSERT(condition, message) assert((condition) && message) #endif -#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) -# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) -#endif +// __builtin_clz is broken in clang with Microsoft CodeGen: +// https://github.com/fmtlib/fmt/issues/519 +#ifndef _MSC_VER +# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz) +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +# endif -#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) -# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +# if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll) +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +# endif #endif // Some compilers masquerade as both MSVC and GCC-likes or @@ -606,7 +609,7 @@ class FormatError : public std::runtime_error { explicit FormatError(CStringRef message) : std::runtime_error(message.c_str()) {} FormatError(const FormatError &ferr) : std::runtime_error(ferr) {} - ~FormatError() FMT_DTOR_NOEXCEPT; + FMT_API ~FormatError() FMT_DTOR_NOEXCEPT; }; namespace internal { @@ -722,7 +725,8 @@ class Buffer { template template void Buffer::append(const U *begin, const U *end) { - std::size_t new_size = size_ + internal::to_unsigned(end - begin); + FMT_ASSERT(end >= begin, "negative value"); + std::size_t new_size = size_ + (end - begin); if (new_size > capacity_) grow(new_size); std::uninitialized_copy(begin, end, @@ -1206,7 +1210,7 @@ template <> struct Not { enum { value = 1 }; }; template -struct False { enum { value = 0 }; }; +struct FalseType { enum { value = 0 }; }; template struct LConvCheck { LConvCheck(int) {} @@ -1246,7 +1250,7 @@ inline fmt::StringRef thousands_sep(...) { return ""; } template void format_arg(Formatter &, const Char *, const T &) { - FMT_STATIC_ASSERT(False::value, + FMT_STATIC_ASSERT(FalseType::value, "Cannot format argument. To enable the use of ostream " "operator<< include fmt/ostream.h. Otherwise provide " "an overload of format_arg."); @@ -1392,14 +1396,9 @@ class MakeValue : public Arg { } template - MakeValue(const T &value, - typename EnableIf::value, int>::type = 0) { - int_value = value; - } - - template - static uint64_t type(const T &) { - return ConvertToInt::value ? Arg::INT : Arg::CUSTOM; + static typename EnableIf::value>::value, uint64_t>::type + type(const T &) { + return Arg::CUSTOM; } // Additional template param `Char_` is needed here because make_type always @@ -1448,7 +1447,7 @@ class RuntimeError : public std::runtime_error { protected: RuntimeError() : std::runtime_error("") {} RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {} - ~RuntimeError() FMT_DTOR_NOEXCEPT; + FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT; }; template @@ -1949,6 +1948,9 @@ class ArgFormatterBase : public ArgVisitor { writer_.write_int(reinterpret_cast(p), spec_); } + // workaround MSVC two-phase lookup issue + typedef internal::Arg Arg; + protected: BasicWriter &writer() { return writer_; } Spec &spec() { return spec_; } @@ -2213,10 +2215,10 @@ inline uint64_t make_type(const T &arg) { return MakeValue< BasicFormatter >::type(arg); } -template +template struct ArgArray; -template +template struct ArgArray { typedef Value Type[N > 0 ? N : 1]; @@ -2234,7 +2236,7 @@ struct ArgArray { } }; -template +template struct ArgArray { typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE @@ -2374,7 +2376,7 @@ inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) { */ class SystemError : public internal::RuntimeError { private: - void init(int err_code, CStringRef format_str, ArgList args); + FMT_API void init(int err_code, CStringRef format_str, ArgList args); protected: int error_code_; @@ -2405,9 +2407,10 @@ class SystemError : public internal::RuntimeError { SystemError(int error_code, CStringRef message) { init(error_code, message, ArgList()); } + FMT_DEFAULTED_COPY_CTOR(SystemError) FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef) - ~SystemError() FMT_DTOR_NOEXCEPT; + FMT_API ~SystemError() FMT_DTOR_NOEXCEPT; int error_code() const { return error_code_; } }; @@ -2924,7 +2927,7 @@ void BasicWriter::write_int(T value, Spec spec) { case 'n': { unsigned num_digits = internal::count_digits(abs_value); fmt::StringRef sep = ""; -#ifndef ANDROID +#if !(defined(ANDROID) || defined(__ANDROID__)) sep = internal::thousands_sep(std::localeconv()); #endif unsigned size = static_cast( @@ -3865,6 +3868,66 @@ void BasicFormatter::format(BasicCStringRef format_str) { } write(writer_, start, s); } + +template +struct ArgJoin { + It first; + It last; + BasicCStringRef sep; + + ArgJoin(It first, It last, const BasicCStringRef& sep) : + first(first), + last(last), + sep(sep) {} +}; + +template +ArgJoin join(It first, It last, const BasicCStringRef& sep) { + return ArgJoin(first, last, sep); +} + +template +ArgJoin join(It first, It last, const BasicCStringRef& sep) { + return ArgJoin(first, last, sep); +} + +#if FMT_HAS_GXX_CXX11 +template +auto join(const Range& range, const BasicCStringRef& sep) + -> ArgJoin { + return join(std::begin(range), std::end(range), sep); +} + +template +auto join(const Range& range, const BasicCStringRef& sep) + -> ArgJoin { + return join(std::begin(range), std::end(range), sep); +} +#endif + +template +void format_arg(fmt::BasicFormatter &f, + const Char *&format_str, const ArgJoin& e) { + const Char* end = format_str; + if (*end == ':') + ++end; + while (*end && *end != '}') + ++end; + if (*end != '}') + FMT_THROW(FormatError("missing '}' in format string")); + + It it = e.first; + if (it != e.last) { + const Char* save = format_str; + f.format(format_str, internal::MakeArg >(*it++)); + while (it != e.last) { + f.writer().write(e.sep); + format_str = save; + f.format(format_str, internal::MakeArg >(*it++)); + } + } + format_str = end + 1; +} } // namespace fmt #if FMT_USE_USER_DEFINED_LITERALS diff --git a/far/thirdparty/tinyxml2/tinyxml2.cpp b/far/thirdparty/tinyxml2/tinyxml2.cpp index 06be39e67f..1ce0fb28fc 100644 --- a/far/thirdparty/tinyxml2/tinyxml2.cpp +++ b/far/thirdparty/tinyxml2/tinyxml2.cpp @@ -368,6 +368,19 @@ const char* StrPair::GetStr() // --------- XMLUtil ----------- // +const char* XMLUtil::writeBoolTrue = "true"; +const char* XMLUtil::writeBoolFalse = "false"; + +void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) +{ + static const char* defTrue = "true"; + static const char* defFalse = "false"; + + writeBoolTrue = (writeTrue) ? writeTrue : defTrue; + writeBoolFalse = (writeFalse) ? writeFalse : defFalse; +} + + const char* XMLUtil::ReadBOM( const char* p, bool* bom ) { TIXMLASSERT( p ); @@ -545,7 +558,7 @@ void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) { - TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? "true" : "false" ); + TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); } /* @@ -665,46 +678,34 @@ char* XMLDocument::Identify( char* p, XMLNode** node ) TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool XMLNode* returnNode = 0; if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLDeclaration( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += xmlHeaderLen; } else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += commentHeaderLen; } else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - XMLText* text = new (_textPool.Alloc()) XMLText( this ); + XMLText* text = CreateUnlinkedNode( _textPool ); returnNode = text; returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_textPool; p += cdataHeaderLen; text->SetCData( true ); } else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); - returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode = CreateUnlinkedNode( _commentPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_commentPool; p += dtdHeaderLen; } else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { - TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); - returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode = CreateUnlinkedNode( _elementPool ); returnNode->_parseLineNum = _parseCurLineNum; - returnNode->_memPool = &_elementPool; p += elementHeaderLen; } else { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - returnNode = new (_textPool.Alloc()) XMLText( this ); - returnNode->_memPool = &_textPool; + returnNode = CreateUnlinkedNode( _textPool ); returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character p = start; // Back it up, all the text counts. _parseCurLineNum = startLine; @@ -771,6 +772,18 @@ void XMLNode::SetValue( const char* str, bool staticMem ) } } +XMLNode* XMLNode::DeepClone(XMLDocument* target) const +{ + XMLNode* clone = this->ShallowClone(target); + if (!clone) return 0; + + for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { + XMLNode* childClone = child->DeepClone(target); + TIXMLASSERT(childClone); + clone->InsertEndChild(childClone); + } + return clone; +} void XMLNode::DeleteChildren() { @@ -800,6 +813,8 @@ void XMLNode::Unlink( XMLNode* child ) if ( child->_next ) { child->_next->_prev = child->_prev; } + child->_next = 0; + child->_prev = 0; child->_parent = 0; } @@ -810,6 +825,9 @@ void XMLNode::DeleteChild( XMLNode* node ) TIXMLASSERT( node->_document == _document ); TIXMLASSERT( node->_parent == this ); Unlink( node ); + TIXMLASSERT(node->_prev == 0); + TIXMLASSERT(node->_next == 0); + TIXMLASSERT(node->_parent == 0); DeleteNode( node ); } @@ -954,7 +972,7 @@ const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const } -char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) +char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) { // This is a recursive method, but thinking about it "at the current level" // it is a pretty simple flat list: @@ -1019,8 +1037,8 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) if ( ele ) { // We read the end tag. Return it to the parent. if ( ele->ClosingType() == XMLElement::CLOSING ) { - if ( parentEnd ) { - ele->_value.TransferTo( parentEnd ); + if ( parentEndTag ) { + ele->_value.TransferTo( parentEndTag ); } node->_memPool->SetTracked(); // created and then immediately deleted. DeleteNode( node ); @@ -1054,11 +1072,16 @@ char* XMLNode::ParseDeep( char* p, StrPair* parentEnd, int* curLineNumPtr ) return 0; } -void XMLNode::DeleteNode( XMLNode* node ) +/*static*/ void XMLNode::DeleteNode( XMLNode* node ) { if ( node == 0 ) { return; } + TIXMLASSERT(node->_document); + if (!node->ToDocument()) { + node->_document->MarkInUse(node); + } + MemPool* pool = node->_memPool; node->~XMLNode(); pool->Free( node ); @@ -1069,10 +1092,13 @@ void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const TIXMLASSERT( insertThis ); TIXMLASSERT( insertThis->_document == _document ); - if ( insertThis->_parent ) + if (insertThis->_parent) { insertThis->_parent->Unlink( insertThis ); - else + } + else { + insertThis->_document->MarkInUse(insertThis); insertThis->_memPool->SetTracked(); + } } const XMLElement* XMLNode::ToElementWithName( const char* name ) const @@ -1132,6 +1158,7 @@ XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const bool XMLText::ShallowEqual( const XMLNode* compare ) const { + TIXMLASSERT( compare ); const XMLText* text = compare->ToText(); return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); } @@ -1447,7 +1474,7 @@ void XMLAttribute::SetAttribute( float v ) // --------- XMLElement ---------- // XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), - _closingType( 0 ), + _closingType( OPEN ), _rootAttribute( 0 ) { } @@ -1837,6 +1864,7 @@ XMLAttribute* XMLElement::CreateAttribute() { TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + TIXMLASSERT( attrib ); attrib->_memPool = &_document->_attributePool; attrib->_memPool->SetTracked(); return attrib; @@ -1846,7 +1874,7 @@ XMLAttribute* XMLElement::CreateAttribute() // // foobar // -char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr ) +char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) { // Read the element name. p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); @@ -1865,11 +1893,11 @@ char* XMLElement::ParseDeep( char* p, StrPair* strPair, int* curLineNumPtr ) } p = ParseAttributes( p, curLineNumPtr ); - if ( !p || !*p || _closingType ) { + if ( !p || !*p || _closingType != OPEN ) { return p; } - p = XMLNode::ParseDeep( p, strPair, curLineNumPtr ); + p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); return p; } @@ -1938,10 +1966,10 @@ const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { "XML_ERROR_FILE_NOT_FOUND", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", "XML_ERROR_FILE_READ_ERROR", - "XML_ERROR_ELEMENT_MISMATCH", + "UNUSED_XML_ERROR_ELEMENT_MISMATCH", "XML_ERROR_PARSING_ELEMENT", "XML_ERROR_PARSING_ATTRIBUTE", - "XML_ERROR_IDENTIFYING_TAG", + "UNUSED_XML_ERROR_IDENTIFYING_TAG", "XML_ERROR_PARSING_TEXT", "XML_ERROR_PARSING_CDATA", "XML_ERROR_PARSING_COMMENT", @@ -1955,13 +1983,15 @@ const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { }; -XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : XMLNode( 0 ), _writeBOM( false ), _processEntities( processEntities ), _errorID(XML_SUCCESS), - _whitespace( whitespace ), - _charBuffer( 0 ) + _whitespaceMode( whitespaceMode ), + _errorLineNum( 0 ), + _charBuffer( 0 ), + _parseCurLineNum( 0 ) { // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) _document = this; @@ -1974,9 +2004,25 @@ XMLDocument::~XMLDocument() } +void XMLDocument::MarkInUse(XMLNode* node) +{ + TIXMLASSERT(node); + TIXMLASSERT(node->_parent == 0); + + for (int i = 0; i < _unlinked.Size(); ++i) { + if (node == _unlinked[i]) { + _unlinked.SwapRemove(i); + break; + } + } +} + void XMLDocument::Clear() { DeleteChildren(); + while( _unlinked.Size()) { + DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. + } #ifdef DEBUG const bool hadError = Error(); @@ -2004,11 +2050,22 @@ void XMLDocument::Clear() } +void XMLDocument::DeepCopy(XMLDocument* target) +{ + TIXMLASSERT(target); + if (target == this) { + return; // technically success - a no-op. + } + + target->Clear(); + for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { + target->InsertEndChild(node->DeepClone(target)); + } +} + XMLElement* XMLDocument::NewElement( const char* name ) { - TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); - XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); - ele->_memPool = &_elementPool; + XMLElement* ele = CreateUnlinkedNode( _elementPool ); ele->SetName( name ); return ele; } @@ -2016,9 +2073,7 @@ XMLElement* XMLDocument::NewElement( const char* name ) XMLComment* XMLDocument::NewComment( const char* str ) { - TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); - XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); - comment->_memPool = &_commentPool; + XMLComment* comment = CreateUnlinkedNode( _commentPool ); comment->SetValue( str ); return comment; } @@ -2026,9 +2081,7 @@ XMLComment* XMLDocument::NewComment( const char* str ) XMLText* XMLDocument::NewText( const char* str ) { - TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); - XMLText* text = new (_textPool.Alloc()) XMLText( this ); - text->_memPool = &_textPool; + XMLText* text = CreateUnlinkedNode( _textPool ); text->SetValue( str ); return text; } @@ -2036,9 +2089,7 @@ XMLText* XMLDocument::NewText( const char* str ) XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) { - TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); - XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); - dec->_memPool = &_commentPool; + XMLDeclaration* dec = CreateUnlinkedNode( _commentPool ); dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); return dec; } @@ -2046,9 +2097,7 @@ XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) XMLUnknown* XMLDocument::NewUnknown( const char* str ) { - TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); - XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); - unk->_memPool = &_commentPool; + XMLUnknown* unk = CreateUnlinkedNode( _commentPool ); unk->SetValue( str ); return unk; } @@ -2259,6 +2308,16 @@ void XMLDocument::SetError( XMLError error, const char* str1, const char* str2, return errorName; } +const char* XMLDocument::GetErrorStr1() const +{ + return _errorStr1.GetStr(); +} + +const char* XMLDocument::GetErrorStr2() const +{ + return _errorStr2.GetStr(); +} + const char* XMLDocument::ErrorName() const { return ErrorIDToName(_errorID); diff --git a/far/thirdparty/tinyxml2/tinyxml2.h b/far/thirdparty/tinyxml2/tinyxml2.h index c6f43e8551..e02a2a54ef 100644 --- a/far/thirdparty/tinyxml2/tinyxml2.h +++ b/far/thirdparty/tinyxml2/tinyxml2.h @@ -53,7 +53,7 @@ distribution. AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h */ -#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +#if defined( _DEBUG ) || defined (__DEBUG__) # ifndef DEBUG # define DEBUG # endif @@ -98,7 +98,7 @@ distribution. /* Versioning, past 1.0.14: http://semver.org/ */ -static const int TIXML2_MAJOR_VERSION = 4; +static const int TIXML2_MAJOR_VERSION = 5; static const int TIXML2_MINOR_VERSION = 0; static const int TIXML2_PATCH_VERSION = 1; @@ -264,6 +264,13 @@ class DynArray return _allocated; } + void SwapRemove(int i) { + TIXMLASSERT(i >= 0 && i < _size); + TIXMLASSERT(_size > 0); + _mem[i] = _mem[_size - 1]; + --_size; + } + const T* Mem() const { TIXMLASSERT( _mem ); return _mem; @@ -284,6 +291,7 @@ class DynArray TIXMLASSERT( cap <= INT_MAX / 2 ); int newAllocated = cap * 2; T* newMem = new T[newAllocated]; + TIXMLASSERT( newAllocated >= _size ); memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs if ( _mem != _pool ) { delete [] _mem; @@ -505,10 +513,10 @@ enum XMLError { XML_ERROR_FILE_NOT_FOUND, XML_ERROR_FILE_COULD_NOT_BE_OPENED, XML_ERROR_FILE_READ_ERROR, - XML_ERROR_ELEMENT_MISMATCH, + UNUSED_XML_ERROR_ELEMENT_MISMATCH, // remove at next major version XML_ERROR_PARSING_ELEMENT, XML_ERROR_PARSING_ATTRIBUTE, - XML_ERROR_IDENTIFYING_TAG, + UNUSED_XML_ERROR_IDENTIFYING_TAG, // remove at next major version XML_ERROR_PARSING_TEXT, XML_ERROR_PARSING_CDATA, XML_ERROR_PARSING_COMMENT, @@ -527,7 +535,7 @@ enum XMLError { /* Utility functionality. */ -class XMLUtil +class TINYXML2_LIB XMLUtil { public: static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { @@ -605,6 +613,17 @@ class XMLUtil static bool ToFloat( const char* str, float* value ); static bool ToDouble( const char* str, double* value ); static bool ToInt64(const char* str, int64_t* value); + + // Changes what is serialized for a boolean value. + // Default to "true" and "false". Shouldn't be changed + // unless you have a special testing or compatibility need. + // Be careful: static, global, & not thread safe. + // Be sure to set static const memory as parameters. + static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); + +private: + static const char* writeBoolTrue; + static const char* writeBoolFalse; }; @@ -846,6 +865,21 @@ class TINYXML2_LIB XMLNode */ virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + /** + Make a copy of this node and all its children. + + If the 'target' is null, then the nodes will + be allocated in the current document. If 'target' + is specified, the memory will be allocated is the + specified XMLDocument. + + NOTE: This is probably not the correct tool to + copy a document, since XMLDocuments can have multiple + top level XMLNodes. You probably want to use + XMLDocument::DeepCopy() + */ + XMLNode* DeepClone( XMLDocument* target ) const; + /** Test if 2 nodes are the same, but don't test children. The 2 nodes do not need to be in the same Document. @@ -896,7 +930,7 @@ class TINYXML2_LIB XMLNode XMLNode( XMLDocument* ); virtual ~XMLNode(); - virtual char* ParseDeep( char*, StrPair*, int* ); + virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); XMLDocument* _document; XMLNode* _parent; @@ -964,7 +998,7 @@ class TINYXML2_LIB XMLText : public XMLNode XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} virtual ~XMLText() {} - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: bool _isCData; @@ -995,7 +1029,7 @@ class TINYXML2_LIB XMLComment : public XMLNode XMLComment( XMLDocument* doc ); virtual ~XMLComment(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); private: XMLComment( const XMLComment& ); // not supported @@ -1034,7 +1068,7 @@ class TINYXML2_LIB XMLDeclaration : public XMLNode XMLDeclaration( XMLDocument* doc ); virtual ~XMLDeclaration(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLDeclaration( const XMLDeclaration& ); // not supported @@ -1069,7 +1103,7 @@ class TINYXML2_LIB XMLUnknown : public XMLNode XMLUnknown( XMLDocument* doc ); virtual ~XMLUnknown(); - char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLUnknown( const XMLUnknown& ); // not supported @@ -1177,7 +1211,7 @@ class TINYXML2_LIB XMLAttribute private: enum { BUF_SIZE = 200 }; - XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} virtual ~XMLAttribute() {} XMLAttribute( const XMLAttribute& ); // not supported @@ -1548,19 +1582,19 @@ class TINYXML2_LIB XMLElement : public XMLNode float FloatText(float defaultValue = 0) const; // internal: - enum { + enum ElementClosingType { OPEN, // CLOSED, // CLOSING // }; - int ClosingType() const { + ElementClosingType ClosingType() const { return _closingType; } virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: - char* ParseDeep( char* p, StrPair* endTag, int* curLineNumPtr ); + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); private: XMLElement( XMLDocument* doc ); @@ -1578,7 +1612,7 @@ class TINYXML2_LIB XMLElement : public XMLNode XMLAttribute* CreateAttribute(); enum { BUF_SIZE = 200 }; - int _closingType; + ElementClosingType _closingType; // The attribute list is ordered; there is no 'lastAttribute' // because the list needs to be scanned for dupes before adding // a new attribute. @@ -1602,7 +1636,7 @@ class TINYXML2_LIB XMLDocument : public XMLNode friend class XMLElement; public: /// constructor - XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); ~XMLDocument(); virtual XMLDocument* ToDocument() { @@ -1666,7 +1700,7 @@ class TINYXML2_LIB XMLDocument : public XMLNode return _processEntities; } Whitespace WhitespaceMode() const { - return _whitespace; + return _whitespaceMode; } /** @@ -1769,13 +1803,11 @@ class TINYXML2_LIB XMLDocument : public XMLNode static const char* ErrorIDToName(XMLError errorID); /// Return a possibly helpful diagnostic location or string. - const char* GetErrorStr1() const { - return _errorStr1.GetStr(); - } + const char* GetErrorStr1() const; + /// Return a possibly helpful secondary diagnostic location or string. - const char* GetErrorStr2() const { - return _errorStr2.GetStr(); - } + const char* GetErrorStr2() const; + /// Return the line where the error occured, or zero if unknown. int GetErrorLineNum() const { @@ -1787,9 +1819,21 @@ class TINYXML2_LIB XMLDocument : public XMLNode /// Clear the document, resetting it to the initial state. void Clear(); - // internal + /** + Copies this document to a target document. + The target will be completely cleared before the copy. + If you want to copy a sub-tree, see XMLNode::DeepClone(). + + NOTE: that the 'target' must be non-null. + */ + void DeepCopy(XMLDocument* target); + + // internal char* Identify( char* p, XMLNode** node ); + // internal + void MarkInUse(XMLNode*); + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; } @@ -1804,12 +1848,19 @@ class TINYXML2_LIB XMLDocument : public XMLNode bool _writeBOM; bool _processEntities; XMLError _errorID; - Whitespace _whitespace; + Whitespace _whitespaceMode; mutable StrPair _errorStr1; mutable StrPair _errorStr2; int _errorLineNum; char* _charBuffer; int _parseCurLineNum; + // Memory tracking does add some overhead. + // However, the code assumes that you don't + // have a bunch of unlinked nodes around. + // Therefore it takes less memory to track + // in the document vs. a linked list in the XMLNode, + // and the performance is the same. + DynArray _unlinked; MemPoolT< sizeof(XMLElement) > _elementPool; MemPoolT< sizeof(XMLAttribute) > _attributePool; @@ -1819,8 +1870,23 @@ class TINYXML2_LIB XMLDocument : public XMLNode static const char* _errorNames[XML_ERROR_COUNT]; void Parse(); + + template + NodeType* CreateUnlinkedNode( MemPoolT& pool ); }; +template +inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT& pool ) +{ + TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); + TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); + NodeType* returnNode = new (pool.Alloc()) NodeType( this ); + TIXMLASSERT( returnNode ); + returnNode->_memPool = &pool; + + _unlinked.Push(returnNode); + return returnNode; +} /** A XMLHandle is a class that wraps a node pointer with null checks; this is @@ -2152,6 +2218,7 @@ class TINYXML2_LIB XMLPrinter : public XMLVisitor void ClearBuffer() { _buffer.Clear(); _buffer.Push(0); + _firstElement = true; } protected: diff --git a/far/tinyxml.hpp b/far/tinyxml.hpp index e145ba851e..c44256fb3c 100644 --- a/far/tinyxml.hpp +++ b/far/tinyxml.hpp @@ -42,8 +42,17 @@ WARNING_PUSH() WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant") WARNING_DISABLE_GCC("-Wsuggest-override") +#ifdef MEMCHECK +#pragma push_macro("new") +#undef new +#endif + #include "thirdparty/tinyxml2/tinyxml2.h" +#ifdef MEMCHECK +#pragma pop_macro("new") +#endif + WARNING_POP() }