From 47af51fdfb6aedbb894ec380ee633cf4f2ae6dd6 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Tue, 15 Jan 2013 22:57:27 -0600 Subject: [PATCH 01/25] First stab (Windows) at IPAddress SOO --- Net/Net_vs100.vcxproj | 2 + Net/Net_vs100.vcxproj.filters | 6 + Net/include/Poco/Net/IPAddress.h | 28 +- Net/include/Poco/Net/IPAddressImpl.h | 201 ++++++ Net/src/IPAddress.cpp | 912 ++++----------------------- Net/src/IPAddressImpl.cpp | 770 ++++++++++++++++++++++ 6 files changed, 1114 insertions(+), 805 deletions(-) create mode 100644 Net/include/Poco/Net/IPAddressImpl.h create mode 100644 Net/src/IPAddressImpl.cpp diff --git a/Net/Net_vs100.vcxproj b/Net/Net_vs100.vcxproj index 190f81346..781dc997c 100644 --- a/Net/Net_vs100.vcxproj +++ b/Net/Net_vs100.vcxproj @@ -270,6 +270,7 @@ + @@ -369,6 +370,7 @@ + diff --git a/Net/Net_vs100.vcxproj.filters b/Net/Net_vs100.vcxproj.filters index 3cbe0c129..5b0a5cf62 100644 --- a/Net/Net_vs100.vcxproj.filters +++ b/Net/Net_vs100.vcxproj.filters @@ -420,6 +420,9 @@ Reactor\Header Files + + NetCore\Header Files + @@ -695,6 +698,9 @@ NetCore\Source Files + + NetCore\Source Files + diff --git a/Net/include/Poco/Net/IPAddress.h b/Net/include/Poco/Net/IPAddress.h index 2a3c2ecc0..1843354a9 100644 --- a/Net/include/Poco/Net/IPAddress.h +++ b/Net/include/Poco/Net/IPAddress.h @@ -42,6 +42,7 @@ #include "Poco/Net/Net.h" #include "Poco/Net/SocketDefs.h" +#include "Poco/Net/IPAddressImpl.h" #include @@ -53,9 +54,6 @@ class BinaryWriter; namespace Net { -class IPAddressImpl; - - class Net_API IPAddress /// This class represents an internet (IP) host /// address. The address can belong either to the @@ -80,9 +78,9 @@ public: enum Family /// Possible address families for IP addresses. { - IPv4 + IPv4 = Poco::Net::Impl::IPAddressImpl::IPv4 #ifdef POCO_HAVE_IPv6 - ,IPv6 + ,IPv6 = Poco::Net::Impl::IPAddressImpl::IPv6 #endif }; @@ -143,7 +141,7 @@ public: IPAddress& operator = (const IPAddress& addr); /// Assigns an IPAddress. - void swap(IPAddress& address); + //void swap(IPAddress& address); /// Swaps the IPAddress with another one. Family family() const; @@ -387,26 +385,26 @@ public: /// Maximum length in bytes of a socket address. }; -protected: - void init(IPAddressImpl* pImpl); - private: - IPAddressImpl* _pImpl; + typedef Poco::Net::Impl::IPAddressImpl Impl; + typedef Impl* Ptr; + + Ptr pImpl() const; + + char _memory[sizeof(Poco::Net::Impl::IPv6AddressImpl)]; }; -// -// inlines -// -inline void swap(IPAddress& addr1, IPAddress& addr2) +inline IPAddress::Ptr IPAddress::pImpl() const { - addr1.swap(addr2); + return reinterpret_cast(const_cast(_memory)); } BinaryWriter& operator << (BinaryWriter& writer, const IPAddress& value); BinaryReader& operator >> (BinaryReader& reader, IPAddress& value); + } } // namespace Poco::Net diff --git a/Net/include/Poco/Net/IPAddressImpl.h b/Net/include/Poco/Net/IPAddressImpl.h new file mode 100644 index 000000000..b1808e50d --- /dev/null +++ b/Net/include/Poco/Net/IPAddressImpl.h @@ -0,0 +1,201 @@ +// +// IPAddressImpl.h +// +// $Id: //poco/1.4/Net/include/Poco/Net/IPAddressImpl.h#2 $ +// +// Library: Net +// Package: NetCore +// Module: IPAddressImpl +// +// Definition of the IPAddressImpl class. +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Net_IPAddressImpl_INCLUDED +#define Net_IPAddressImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include + + +namespace Poco { +namespace Net { +namespace Impl { + + +class IPAddressImpl +{ +public: + enum Family + /// Possible address families for IP addresses. + { + IPv4 +#ifdef POCO_HAVE_IPv6 + ,IPv6 +#endif + }; + + virtual std::string toString() const = 0; + virtual poco_socklen_t length() const = 0; + virtual const void* addr() const = 0; + virtual Family family() const = 0; + virtual int af() const = 0; + virtual Poco::UInt32 scope() const = 0; + virtual bool isWildcard() const = 0; + virtual bool isBroadcast() const = 0; + virtual bool isLoopback() const = 0; + virtual bool isMulticast() const = 0; + virtual bool isLinkLocal() const = 0; + virtual bool isSiteLocal() const = 0; + virtual bool isIPv4Mapped() const = 0; + virtual bool isIPv4Compatible() const = 0; + virtual bool isWellKnownMC() const = 0; + virtual bool isNodeLocalMC() const = 0; + virtual bool isLinkLocalMC() const = 0; + virtual bool isSiteLocalMC() const = 0; + virtual bool isOrgLocalMC() const = 0; + virtual bool isGlobalMC() const = 0; + virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0; + virtual unsigned prefixLength() const = 0; + + virtual IPAddressImpl* clone() const = 0; + +protected: + IPAddressImpl(); + virtual ~IPAddressImpl(); + +private: + IPAddressImpl(const IPAddressImpl&); + IPAddressImpl& operator = (const IPAddressImpl&); +}; + + +// +// IPv4AddressImpl +// + +class IPv4AddressImpl: public IPAddressImpl +{ +public: + IPv4AddressImpl(); + IPv4AddressImpl(const void* addr); + IPv4AddressImpl(unsigned prefix); + IPv4AddressImpl(const IPv4AddressImpl& addr); + IPv4AddressImpl& operator = (const IPv4AddressImpl&); + std::string toString() const; + poco_socklen_t length() const; + const void* addr() const; + Family family() const; + int af() const; + unsigned prefixLength() const; + Poco::UInt32 scope() const; + bool isWildcard() const; + bool isBroadcast() const; + bool isLoopback() const; + bool isMulticast() const; + bool isLinkLocal() const; + bool isSiteLocal() const; + bool isIPv4Compatible() const; + bool isIPv4Mapped() const; + bool isWellKnownMC() const; + bool isNodeLocalMC() const; + bool isLinkLocalMC() const; + bool isSiteLocalMC() const; + bool isOrgLocalMC() const; + bool isGlobalMC() const; + static IPv4AddressImpl parse(const std::string& addr); + void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet); + IPAddressImpl* clone() const; + IPv4AddressImpl operator & (const IPv4AddressImpl& addr) const; + IPv4AddressImpl operator | (const IPv4AddressImpl& addr) const; + IPv4AddressImpl operator ^ (const IPv4AddressImpl& addr) const; + IPv4AddressImpl operator ~ () const; + bool operator == (const IPv4AddressImpl& addr) const; + bool operator != (const IPv4AddressImpl& addr) const; + +private: + struct in_addr _addr; +}; + + +// +// IPv6AddressImpl +// + +class IPv6AddressImpl: public IPAddressImpl +{ +public: + IPv6AddressImpl(); + IPv6AddressImpl(const void* addr); + IPv6AddressImpl(const void* addr, Poco::UInt32 scope); + IPv6AddressImpl(unsigned prefix); + std::string toString() const; + poco_socklen_t length() const; + const void* addr() const; + Family family() const; + int af() const; + unsigned prefixLength() const; + Poco::UInt32 scope() const; + bool isWildcard() const; + bool isBroadcast() const; + bool isLoopback() const; + bool isMulticast() const; + bool isLinkLocal() const; + bool isSiteLocal() const; + bool isIPv4Compatible() const; + bool isIPv4Mapped() const; + bool isWellKnownMC() const; + bool isNodeLocalMC() const; + bool isLinkLocalMC() const; + bool isSiteLocalMC() const; + bool isOrgLocalMC() const; + bool isGlobalMC() const; + static IPv6AddressImpl parse(const std::string& addr); + void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet); + IPAddressImpl* clone() const; + IPv6AddressImpl operator & (const IPv6AddressImpl& addr) const; + IPv6AddressImpl operator | (const IPv6AddressImpl& addr) const; + IPv6AddressImpl operator ^ (const IPv6AddressImpl& addr) const; + IPv6AddressImpl operator ~ () const; + bool operator == (const IPv6AddressImpl& addr) const; + bool operator != (const IPv6AddressImpl& addr) const; + IPv6AddressImpl(const IPv6AddressImpl& addr); + IPv6AddressImpl& operator = (const IPv6AddressImpl&); + +private: + struct in6_addr _addr; + unsigned int _scope; +}; + + +} } } // namespace Poco::Net::Impl + + +#endif // Net_IPAddressImpl_INCLUDED diff --git a/Net/src/IPAddress.cpp b/Net/src/IPAddress.cpp index f598a1afc..13bce33c1 100644 --- a/Net/src/IPAddress.cpp +++ b/Net/src/IPAddress.cpp @@ -49,726 +49,41 @@ using Poco::NumberFormatter; using Poco::BinaryReader; using Poco::BinaryWriter; using Poco::toLower; +using Poco::trim; using Poco::UInt8; using Poco::UInt16; using Poco::UInt32; - - -namespace { - -template -unsigned maskBits(T val, unsigned size) - /// Returns the length of the mask (number of bits set in val). - /// The val should be either all zeros or two contiguos areas of 1s and 0s. - /// The algorithm ignores invalid non-contiguous series of 1s and treats val - /// as if all bits between MSb and last non-zero bit are set to 1. -{ - unsigned count = 0; - if (val) - { - val = (val ^ (val - 1)) >> 1; - for (count = 0; val; ++count) val >>= 1; - } - else count = size; - return size - count; -} - -} // namespace +using Poco::Net::Impl::IPAddressImpl; +using Poco::Net::Impl::IPv4AddressImpl; +using Poco::Net::Impl::IPv6AddressImpl; namespace Poco { namespace Net { -// -// IPAddressImpl -// - - -class IPAddressImpl: public RefCountedObject -{ -public: - virtual std::string toString() const = 0; - virtual poco_socklen_t length() const = 0; - virtual const void* addr() const = 0; - virtual IPAddress::Family family() const = 0; - virtual int af() const = 0; - virtual Poco::UInt32 scope() const = 0; - virtual bool isWildcard() const = 0; - virtual bool isBroadcast() const = 0; - virtual bool isLoopback() const = 0; - virtual bool isMulticast() const = 0; - virtual bool isLinkLocal() const = 0; - virtual bool isSiteLocal() const = 0; - virtual bool isIPv4Mapped() const = 0; - virtual bool isIPv4Compatible() const = 0; - virtual bool isWellKnownMC() const = 0; - virtual bool isNodeLocalMC() const = 0; - virtual bool isLinkLocalMC() const = 0; - virtual bool isSiteLocalMC() const = 0; - virtual bool isOrgLocalMC() const = 0; - virtual bool isGlobalMC() const = 0; - virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0; - virtual unsigned prefixLength() const = 0; - - virtual IPAddressImpl* clone() const = 0; - -protected: - IPAddressImpl() - { - } - - virtual ~IPAddressImpl() - { - } - -private: - IPAddressImpl(const IPAddressImpl&); - IPAddressImpl& operator = (const IPAddressImpl&); -}; - - -class IPv4AddressImpl: public IPAddressImpl -{ -public: - IPv4AddressImpl() - { - std::memset(&_addr, 0, sizeof(_addr)); - } - - IPv4AddressImpl(const void* addr) - { - std::memcpy(&_addr, addr, sizeof(_addr)); - } - - IPv4AddressImpl(unsigned prefix) - { - UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix); - _addr.s_addr = htonl(addr); - } - - std::string toString() const - { - const UInt8* bytes = reinterpret_cast(&_addr); - std::string result; - result.reserve(16); - NumberFormatter::append(result, bytes[0]); - result.append("."); - NumberFormatter::append(result, bytes[1]); - result.append("."); - NumberFormatter::append(result, bytes[2]); - result.append("."); - NumberFormatter::append(result, bytes[3]); - return result; - } - - poco_socklen_t length() const - { - return sizeof(_addr); - } - - const void* addr() const - { - return &_addr; - } - - IPAddress::Family family() const - { - return IPAddress::IPv4; - } - - int af() const - { - return AF_INET; - } - - unsigned prefixLength() const - { - return maskBits(ntohl(_addr.s_addr), 32); - } - - Poco::UInt32 scope() const - { - return 0; - } - - bool isWildcard() const - { - return _addr.s_addr == INADDR_ANY; - } - - bool isBroadcast() const - { - return _addr.s_addr == INADDR_NONE; - } - - bool isLoopback() const - { - return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255 - } - - bool isMulticast() const - { - return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24 - } - - bool isLinkLocal() const - { - return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16 - } - - bool isSiteLocal() const - { - UInt32 addr = ntohl(_addr.s_addr); - return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24 - (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16 - (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255 - } - - bool isIPv4Compatible() const - { - return true; - } - - bool isIPv4Mapped() const - { - return true; - } - - bool isWellKnownMC() const - { - return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8 - } - - bool isNodeLocalMC() const - { - return false; - } - - bool isLinkLocalMC() const - { - return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24 - } - - bool isSiteLocalMC() const - { - return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16 - } - - bool isOrgLocalMC() const - { - return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16 - } - - bool isGlobalMC() const - { - UInt32 addr = ntohl(_addr.s_addr); - return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255 - } - - static IPv4AddressImpl* parse(const std::string& addr) - { - if (addr.empty()) return 0; -#if defined(_WIN32) - struct in_addr ia; - ia.s_addr = inet_addr(addr.c_str()); - if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") - return 0; - else - return new IPv4AddressImpl(&ia); -#else -#if __GNUC__ < 3 || defined(POCO_VXWORKS) - struct in_addr ia; - ia.s_addr = inet_addr(const_cast(addr.c_str())); - if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") - return 0; - else - return new IPv4AddressImpl(&ia); -#else - struct in_addr ia; - if (inet_aton(addr.c_str(), &ia)) - return new IPv4AddressImpl(&ia); - else - return 0; -#endif -#endif - } - - void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) - { - poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET); - - _addr.s_addr &= static_cast(pMask)->_addr.s_addr; - _addr.s_addr |= static_cast(pSet)->_addr.s_addr & ~static_cast(pMask)->_addr.s_addr; - } - - IPAddressImpl* clone() const - { - return new IPv4AddressImpl(&_addr); - } - - IPv4AddressImpl operator & (const IPv4AddressImpl& addr) const - { - IPv4AddressImpl result(&_addr); - result._addr.s_addr &= addr._addr.s_addr; - return result; - } - - IPv4AddressImpl operator | (const IPv4AddressImpl& addr) const - { - IPv4AddressImpl result(&_addr); - result._addr.s_addr |= addr._addr.s_addr; - return result; - } - - IPv4AddressImpl operator ^ (const IPv4AddressImpl& addr) const - { - IPv4AddressImpl result(&_addr); - result._addr.s_addr ^= addr._addr.s_addr; - return result; - } - - IPv4AddressImpl operator ~ () const - { - IPv4AddressImpl result(&_addr); - result._addr.s_addr ^= 0xffffffff; - return result; - } - -private: - IPv4AddressImpl(const IPv4AddressImpl& addr) - { - std::memcpy(&_addr, &addr._addr, sizeof(_addr)); - } - - IPv4AddressImpl& operator = (const IPv4AddressImpl&); - - struct in_addr _addr; -}; - - -#if defined(POCO_HAVE_IPv6) - - -class IPv6AddressImpl: public IPAddressImpl -{ -public: - IPv6AddressImpl(): - _scope(0) - { - std::memset(&_addr, 0, sizeof(_addr)); - } - - IPv6AddressImpl(const void* addr): - _scope(0) - { - std::memcpy(&_addr, addr, sizeof(_addr)); - } - - IPv6AddressImpl(const void* addr, Poco::UInt32 scope): - _scope(scope) - { - std::memcpy(&_addr, addr, sizeof(_addr)); - } - - - IPv6AddressImpl(unsigned prefix): - _scope(0) - { - unsigned i = 0; -#ifdef POCO_OS_FAMILY_WINDOWS - for (; prefix >= 16; ++i, prefix -= 16) { - _addr.s6_addr16[i] = 0xffff; - } - if (prefix > 0) - _addr.s6_addr16[i++] = htons(~(0xffff >> prefix)); - while (i < 8) - _addr.s6_addr16[i++] = 0; -#else - for (; prefix >= 32; ++i, prefix -= 32) { - _addr.s6_addr32[i] = 0xffffffff; - } - if (prefix > 0) - _addr.s6_addr32[i++] = htonl(~(0xffffffffU >> prefix)); - while (i < 4) - _addr.s6_addr32[i++] = 0; -#endif - } - - std::string toString() const - { - const UInt16* words = reinterpret_cast(&_addr); - if (isIPv4Compatible() || isIPv4Mapped()) - { - std::string result; - result.reserve(24); - if (words[5] == 0) - result.append("::"); - else - result.append("::ffff:"); - const UInt8* bytes = reinterpret_cast(&_addr); - NumberFormatter::append(result, bytes[12]); - result.append("."); - NumberFormatter::append(result, bytes[13]); - result.append("."); - NumberFormatter::append(result, bytes[14]); - result.append("."); - NumberFormatter::append(result, bytes[15]); - return result; - } - else - { - std::string result; - result.reserve(64); - bool zeroSequence = false; - int i = 0; - while (i < 8) - { - if (!zeroSequence && words[i] == 0) - { - int zi = i; - while (zi < 8 && words[zi] == 0) ++zi; - if (zi > i + 1) - { - i = zi; - result.append(":"); - zeroSequence = true; - } - } - if (i > 0) result.append(":"); - if (i < 8) NumberFormatter::appendHex(result, ntohs(words[i++])); - } - if (_scope > 0) - { - result.append("%"); -#if defined(_WIN32) - NumberFormatter::append(result, _scope); -#else - char buffer[IFNAMSIZ]; - if (if_indextoname(_scope, buffer)) - { - result.append(buffer); - } - else - { - NumberFormatter::append(result, _scope); - } -#endif - } - return toLower(result); - } - } - - poco_socklen_t length() const - { - return sizeof(_addr); - } - - const void* addr() const - { - return &_addr; - } - - IPAddress::Family family() const - { - return IPAddress::IPv6; - } - - int af() const - { - return AF_INET6; - } - - unsigned prefixLength() const - { - unsigned bits = 0; - unsigned bitPos = 128; -#if defined(POCO_OS_FAMILY_UNIX) - for (int i = 3; i >= 0; --i) - { - unsigned addr = ntohl(_addr.s6_addr32[i]); - if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits)); - bitPos -= 32; - } - return 0; -#elif defined(POCO_OS_FAMILY_WINDOWS) - for (int i = 7; i >= 0; --i) - { - unsigned short addr = ntohs(_addr.s6_addr16[i]); - if ((bits = maskBits(addr, 16))) return (bitPos - (16 - bits)); - bitPos -= 16; - } - return 0; -#else -#warning prefixLength() not implemented - throw NotImplementedException("prefixLength() not implemented"); -#endif - } - Poco::UInt32 scope() const - { - return _scope; - } - - bool isWildcard() const - { - const UInt16* words = reinterpret_cast(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && - words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0; - } - - bool isBroadcast() const - { - return false; - } - - bool isLoopback() const - { - const UInt16* words = reinterpret_cast(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && - words[4] == 0 && words[5] == 0 && words[6] == 0 && ntohs(words[7]) == 0x0001; - } - - bool isMulticast() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFE0) == 0xFF00; - } - - bool isLinkLocal() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFE0) == 0xFE80; - } - - bool isSiteLocal() const - { - const UInt16* words = reinterpret_cast(&_addr); - return ((ntohs(words[0]) & 0xFFE0) == 0xFEC0) || ((ntohs(words[0]) & 0xFF00) == 0xFC00); - } - - bool isIPv4Compatible() const - { - const UInt16* words = reinterpret_cast(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0; - } - - bool isIPv4Mapped() const - { - const UInt16* words = reinterpret_cast(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ntohs(words[5]) == 0xFFFF; - } - - bool isWellKnownMC() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFF0) == 0xFF00; - } - - bool isNodeLocalMC() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFEF) == 0xFF01; - } - - bool isLinkLocalMC() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFEF) == 0xFF02; - } - - bool isSiteLocalMC() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFEF) == 0xFF05; - } - - bool isOrgLocalMC() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFEF) == 0xFF08; - } - - bool isGlobalMC() const - { - const UInt16* words = reinterpret_cast(&_addr); - return (ntohs(words[0]) & 0xFFEF) == 0xFF0F; - } - - static IPv6AddressImpl* parse(const std::string& addr) - { - if (addr.empty()) return 0; -#if defined(_WIN32) - struct addrinfo* pAI; - struct addrinfo hints; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_NUMERICHOST; - int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI); - if (rc == 0) - { - IPv6AddressImpl* pResult = new IPv6AddressImpl(&reinterpret_cast(pAI->ai_addr)->sin6_addr, static_cast(reinterpret_cast(pAI->ai_addr)->sin6_scope_id)); - freeaddrinfo(pAI); - return pResult; - } - else return 0; -#else - struct in6_addr ia; - std::string::size_type pos = addr.find('%'); - if (std::string::npos != pos) - { - std::string::size_type start = ('[' == addr[0]) ? 1 : 0; - std::string unscopedAddr(addr, start, pos - start); - std::string scope(addr, pos + 1, addr.size() - start - pos); - Poco::UInt32 scopeId(0); - if (!(scopeId = if_nametoindex(scope.c_str()))) - return 0; - if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1) - return new IPv6AddressImpl(&ia, scopeId); - else - return 0; - } - else - { - if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) - return new IPv6AddressImpl(&ia); - else - return 0; - } -#endif - } - - void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) - { - throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses"); - } - - IPAddressImpl* clone() const - { - return new IPv6AddressImpl(&_addr, _scope); - } - - IPv6AddressImpl operator & (const IPv6AddressImpl& addr) const - { - IPv6AddressImpl result(&_addr); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; - result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; - result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2]; - result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3]; - result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4]; - result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5]; - result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6]; - result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7]; -#else - result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0]; - result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1]; - result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2]; - result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3]; -#endif - return result; - } - - IPv6AddressImpl operator | (const IPv6AddressImpl& addr) const - { - IPv6AddressImpl result(&_addr); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; - result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; - result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2]; - result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3]; - result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4]; - result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5]; - result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6]; - result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7]; -#else - result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0]; - result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1]; - result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2]; - result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3]; -#endif - return result; - } - - IPv6AddressImpl operator ^ (const IPv6AddressImpl& addr) const - { - IPv6AddressImpl result(&_addr); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; - result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; - result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2]; - result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3]; - result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4]; - result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5]; - result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6]; - result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7]; -#else - result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0]; - result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1]; - result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2]; - result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3]; -#endif - return result; - } - - IPv6AddressImpl operator ~ () const - { - IPv6AddressImpl result(&_addr); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] ^= 0xffff; - result._addr.s6_addr16[1] ^= 0xffff; - result._addr.s6_addr16[2] ^= 0xffff; - result._addr.s6_addr16[3] ^= 0xffff; - result._addr.s6_addr16[4] ^= 0xffff; - result._addr.s6_addr16[5] ^= 0xffff; - result._addr.s6_addr16[6] ^= 0xffff; - result._addr.s6_addr16[7] ^= 0xffff; -#else - result._addr.s6_addr32[0] ^= 0xffffffff; - result._addr.s6_addr32[1] ^= 0xffffffff; - result._addr.s6_addr32[2] ^= 0xffffffff; - result._addr.s6_addr32[3] ^= 0xffffffff; -#endif - return result; - } - -private: - IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(0) - { - std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr)); - } - - IPv6AddressImpl& operator = (const IPv6AddressImpl&); - - struct in6_addr _addr; - Poco::UInt32 _scope; -}; - - -#endif // POCO_HAVE_IPv6 - - -// -// IPAddress -// - - -IPAddress::IPAddress(): _pImpl(new IPv4AddressImpl) +IPAddress::IPAddress() { + new ((void*) _memory) IPv4AddressImpl(); } -IPAddress::IPAddress(const IPAddress& addr): _pImpl(addr._pImpl) +IPAddress::IPAddress(const IPAddress& addr) { - _pImpl->duplicate(); + if (addr.family() == IPv4) + std::memcpy(pImpl(), addr.pImpl(), sizeof (IPv4AddressImpl)); + else + std::memcpy(pImpl(), addr.pImpl(), sizeof (IPv6AddressImpl)); } -IPAddress::IPAddress(Family family): _pImpl(0) +IPAddress::IPAddress(Family family) { if (family == IPv4) - _pImpl = new IPv4AddressImpl(); + new ((void*) _memory) IPv4AddressImpl(); #if defined(POCO_HAVE_IPv6) else if (family == IPv6) - _pImpl = new IPv6AddressImpl(); + new ((void*) _memory) IPv6AddressImpl(); #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); @@ -777,35 +92,67 @@ IPAddress::IPAddress(Family family): _pImpl(0) IPAddress::IPAddress(const std::string& addr) { - _pImpl = IPv4AddressImpl::parse(addr); + IPv4AddressImpl empty4 = IPv4AddressImpl(); + if (addr.empty() || trim(addr) == "0.0.0.0") + { + std::memcpy(pImpl(), &empty4, sizeof(empty4)); + return; + } + + IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); + if (addr4 != empty4) + { + std::memcpy(pImpl(), &addr4, sizeof(addr4)); + return; + } + #if defined(POCO_HAVE_IPv6) - if (!_pImpl) - _pImpl = IPv6AddressImpl::parse(addr); + IPv6AddressImpl empty6 = IPv6AddressImpl(); + if (addr.empty() || trim(addr) == "::") + { + std::memcpy(pImpl(), &empty6, sizeof(empty6)); + return; + } + + IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); + if (addr6 != IPv6AddressImpl()) + { + std::memcpy(pImpl(), &addr6, sizeof(addr6)); + return; + } #endif - if (!_pImpl) throw InvalidAddressException(addr); + + throw InvalidAddressException(addr); } -IPAddress::IPAddress(const std::string& addr, Family family): _pImpl(0) +IPAddress::IPAddress(const std::string& addr, Family family) { if (family == IPv4) - _pImpl = IPv4AddressImpl::parse(addr); + { + IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); + std::memcpy(pImpl(), &addr4, sizeof(addr4)); + return; + } #if defined(POCO_HAVE_IPv6) else if (family == IPv6) - _pImpl = IPv6AddressImpl::parse(addr); + { + IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); + std::memcpy(pImpl(), &addr6, sizeof(addr6)); + return; + } #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); - if (!_pImpl) throw InvalidAddressException(addr); } IPAddress::IPAddress(const void* addr, poco_socklen_t length) { if (length == sizeof(struct in_addr)) - _pImpl = new IPv4AddressImpl(addr); + new ((void*) _memory) IPv4AddressImpl(addr); #if defined(POCO_HAVE_IPv6) else if (length == sizeof(struct in6_addr)) - _pImpl = new IPv6AddressImpl(addr); + new ((void*) _memory) IPv6AddressImpl(addr); #endif else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); } @@ -814,34 +161,31 @@ IPAddress::IPAddress(const void* addr, poco_socklen_t length) IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope) { if (length == sizeof(struct in_addr)) - _pImpl = new IPv4AddressImpl(addr); + new ((void*) _memory) IPv4AddressImpl(addr); #if defined(POCO_HAVE_IPv6) else if (length == sizeof(struct in6_addr)) - _pImpl = new IPv6AddressImpl(addr, scope); + new ((void*) _memory) IPv6AddressImpl(addr, scope); #endif else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); } -IPAddress::IPAddress(unsigned prefix, Family family): _pImpl(0) +IPAddress::IPAddress(unsigned prefix, Family family) { if (family == IPv4) { - if (prefix <= 32) { - _pImpl = new IPv4AddressImpl(prefix); - } + if (prefix <= 32) + new ((void*) _memory) IPv4AddressImpl(prefix); } #if defined(POCO_HAVE_IPv6) else if (family == IPv6) { if (prefix <= 128) - { - _pImpl = new IPv6AddressImpl(prefix); - } + new ((void*) _memory) IPv6AddressImpl(prefix); } #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); - if (!_pImpl) throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); + if (!pImpl()) throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); } @@ -850,10 +194,10 @@ IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address) { ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family; if (family == AF_INET) - _pImpl = new IPv4AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin_addr); + new ((void*) _memory) IPv4AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin_addr); #if defined(POCO_HAVE_IPv6) else if (family == AF_INET6) - _pImpl = new IPv6AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin6_addr, reinterpret_cast(socket_address.lpSockaddr)->sin6_scope_id); + new ((void*) _memory) IPv6AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin6_addr, reinterpret_cast(socket_address.lpSockaddr)->sin6_scope_id); #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); } @@ -864,10 +208,10 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr) { unsigned short family = sockaddr.sa_family; if (family == AF_INET) - _pImpl = new IPv4AddressImpl(&reinterpret_cast(&sockaddr)->sin_addr); + new ((void*) _memory) IPv4AddressImpl(&reinterpret_cast(&sockaddr)->sin_addr); #if defined(POCO_HAVE_IPv6) else if (family == AF_INET6) - _pImpl = new IPv6AddressImpl(&reinterpret_cast(&sockaddr)->sin6_addr, reinterpret_cast(&sockaddr)->sin6_scope_id); + new ((void*) _memory) IPv6AddressImpl(&reinterpret_cast(&sockaddr)->sin6_addr, reinterpret_cast(&sockaddr)->sin6_scope_id); #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); } @@ -875,7 +219,6 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr) IPAddress::~IPAddress() { - _pImpl->release(); } @@ -883,58 +226,54 @@ IPAddress& IPAddress::operator = (const IPAddress& addr) { if (&addr != this) { - _pImpl->release(); - _pImpl = addr._pImpl; - _pImpl->duplicate(); + if (addr.family() == IPAddress::IPv4) + std::memcpy(pImpl(), addr.pImpl(), sizeof(IPv4AddressImpl)); + else + std::memcpy(pImpl(), addr.pImpl(), sizeof(IPv6AddressImpl)); } return *this; } -void IPAddress::swap(IPAddress& address) -{ - std::swap(_pImpl, address._pImpl); -} - - IPAddress::Family IPAddress::family() const { - return _pImpl->family(); + return static_cast(pImpl()->family()); } Poco::UInt32 IPAddress::scope() const { - return _pImpl->scope(); + return pImpl()->scope(); } std::string IPAddress::toString() const { - return _pImpl->toString(); + return pImpl()->toString(); } bool IPAddress::isWildcard() const { - return _pImpl->isWildcard(); + return pImpl()->isWildcard(); } - + + bool IPAddress::isBroadcast() const { - return _pImpl->isBroadcast(); + return pImpl()->isBroadcast(); } bool IPAddress::isLoopback() const { - return _pImpl->isLoopback(); + return pImpl()->isLoopback(); } bool IPAddress::isMulticast() const { - return _pImpl->isMulticast(); + return pImpl()->isMulticast(); } @@ -946,61 +285,61 @@ bool IPAddress::isUnicast() const bool IPAddress::isLinkLocal() const { - return _pImpl->isLinkLocal(); + return pImpl()->isLinkLocal(); } bool IPAddress::isSiteLocal() const { - return _pImpl->isSiteLocal(); + return pImpl()->isSiteLocal(); } bool IPAddress::isIPv4Compatible() const { - return _pImpl->isIPv4Compatible(); + return pImpl()->isIPv4Compatible(); } bool IPAddress::isIPv4Mapped() const { - return _pImpl->isIPv4Mapped(); + return pImpl()->isIPv4Mapped(); } bool IPAddress::isWellKnownMC() const { - return _pImpl->isWellKnownMC(); + return pImpl()->isWellKnownMC(); } bool IPAddress::isNodeLocalMC() const { - return _pImpl->isNodeLocalMC(); + return pImpl()->isNodeLocalMC(); } bool IPAddress::isLinkLocalMC() const { - return _pImpl->isLinkLocalMC(); + return pImpl()->isLinkLocalMC(); } bool IPAddress::isSiteLocalMC() const { - return _pImpl->isSiteLocalMC(); + return pImpl()->isSiteLocalMC(); } bool IPAddress::isOrgLocalMC() const { - return _pImpl->isOrgLocalMC(); + return pImpl()->isOrgLocalMC(); } bool IPAddress::isGlobalMC() const { - return _pImpl->isGlobalMC(); + return pImpl()->isGlobalMC(); } @@ -1076,15 +415,15 @@ IPAddress IPAddress::operator & (const IPAddress& other) const { if (family() == IPv4) { - IPv4AddressImpl t(_pImpl->addr()); - IPv4AddressImpl o(other._pImpl->addr()); + IPv4AddressImpl t(pImpl()->addr()); + IPv4AddressImpl o(other.pImpl()->addr()); return IPAddress((t & o).addr(), sizeof(struct in_addr)); } #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl t(_pImpl->addr()); - IPv6AddressImpl o(other._pImpl->addr()); + IPv6AddressImpl t(pImpl()->addr()); + IPv6AddressImpl o(other.pImpl()->addr()); return IPAddress((t & o).addr(), sizeof(struct in6_addr)); } #endif @@ -1102,15 +441,15 @@ IPAddress IPAddress::operator | (const IPAddress& other) const { if (family() == IPv4) { - IPv4AddressImpl t(_pImpl->addr()); - IPv4AddressImpl o(other._pImpl->addr()); + IPv4AddressImpl t(pImpl()->addr()); + IPv4AddressImpl o(other.pImpl()->addr()); return IPAddress((t | o).addr(), sizeof(struct in_addr)); } #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl t(_pImpl->addr()); - IPv6AddressImpl o(other._pImpl->addr()); + IPv6AddressImpl t(pImpl()->addr()); + IPv6AddressImpl o(other.pImpl()->addr()); return IPAddress((t | o).addr(), sizeof(struct in6_addr)); } #endif @@ -1128,15 +467,15 @@ IPAddress IPAddress::operator ^ (const IPAddress& other) const { if (family() == IPv4) { - IPv4AddressImpl t(_pImpl->addr()); - IPv4AddressImpl o(other._pImpl->addr()); + IPv4AddressImpl t(pImpl()->addr()); + IPv4AddressImpl o(other.pImpl()->addr()); return IPAddress((t ^ o).addr(), sizeof(struct in_addr)); } #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl t(_pImpl->addr()); - IPv6AddressImpl o(other._pImpl->addr()); + IPv6AddressImpl t(pImpl()->addr()); + IPv6AddressImpl o(other.pImpl()->addr()); return IPAddress((t ^ o).addr(), sizeof(struct in6_addr)); } #endif @@ -1152,13 +491,13 @@ IPAddress IPAddress::operator ~ () const { if (family() == IPv4) { - IPv4AddressImpl self(this->_pImpl->addr()); + IPv4AddressImpl self(this->pImpl()->addr()); return IPAddress((~self).addr(), sizeof(struct in_addr)); } #if defined(POCO_HAVE_IPv6) else if (family() == IPv6) { - IPv6AddressImpl self(this->_pImpl->addr()); + IPv6AddressImpl self(this->pImpl()->addr()); return IPAddress((~self).addr(), sizeof(struct in6_addr)); } #endif @@ -1169,31 +508,25 @@ IPAddress IPAddress::operator ~ () const poco_socklen_t IPAddress::length() const { - return _pImpl->length(); + return pImpl()->length(); } const void* IPAddress::addr() const { - return _pImpl->addr(); + return pImpl()->addr(); } int IPAddress::af() const { - return _pImpl->af(); + return pImpl()->af(); } unsigned IPAddress::prefixLength() const { - return _pImpl->prefixLength(); -} - -void IPAddress::init(IPAddressImpl* pImpl) -{ - _pImpl->release(); - _pImpl = pImpl; + return pImpl()->prefixLength(); } @@ -1205,35 +538,34 @@ IPAddress IPAddress::parse(const std::string& addr) bool IPAddress::tryParse(const std::string& addr, IPAddress& result) { - IPAddressImpl* pImpl = IPv4AddressImpl::parse(addr); -#if defined(POCO_HAVE_IPv6) - if (!pImpl) pImpl = IPv6AddressImpl::parse(addr); -#endif - if (pImpl) + IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr)); + if (impl4 != IPv4AddressImpl()) { - result.init(pImpl); + std::memcpy(result.pImpl(), &impl4, sizeof(impl4)); return true; } - else return false; +#if defined(POCO_HAVE_IPv6) + IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); + if (impl6 != IPv6AddressImpl()) + { + std::memcpy(result.pImpl(), &impl6, sizeof(impl6)); + return true; + } +#endif + return false; } void IPAddress::mask(const IPAddress& mask) { - IPAddressImpl* pClone = _pImpl->clone(); - _pImpl->release(); - _pImpl = pClone; IPAddress null; - _pImpl->mask(mask._pImpl, null._pImpl); + pImpl()->mask(mask.pImpl(), null.pImpl()); } void IPAddress::mask(const IPAddress& mask, const IPAddress& set) { - IPAddressImpl* pClone = _pImpl->clone(); - _pImpl->release(); - _pImpl = pClone; - _pImpl->mask(mask._pImpl, set._pImpl); + pImpl()->mask(mask.pImpl(), set.pImpl()); } diff --git a/Net/src/IPAddressImpl.cpp b/Net/src/IPAddressImpl.cpp new file mode 100644 index 000000000..2a5b08823 --- /dev/null +++ b/Net/src/IPAddressImpl.cpp @@ -0,0 +1,770 @@ +// +// IPAddress.cpp +// +// $Id: //poco/1.4/Net/src/IPAddress.cpp#5 $ +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Net/IPAddressImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/RefCountedObject.h" +#include "Poco/NumberFormatter.h" +#include "Poco/String.h" +#include "Poco/Types.h" + + +using Poco::RefCountedObject; +using Poco::NumberFormatter; +using Poco::toLower; +using Poco::UInt8; +using Poco::UInt16; +using Poco::UInt32; + + +namespace { + +template +unsigned maskBits(T val, unsigned size) + /// Returns the length of the mask (number of bits set in val). + /// The val should be either all zeros or two contiguos areas of 1s and 0s. + /// The algorithm ignores invalid non-contiguous series of 1s and treats val + /// as if all bits between MSb and last non-zero bit are set to 1. +{ + unsigned count = 0; + if (val) + { + val = (val ^ (val - 1)) >> 1; + for (count = 0; val; ++count) val >>= 1; + } + else count = size; + return size - count; +} + +} // namespace + + +namespace Poco { +namespace Net { +namespace Impl { + +// +// IPAddressImpl +// + + +IPAddressImpl::IPAddressImpl() +{ +} + + +IPAddressImpl::~IPAddressImpl() +{ +} + + +// +// IPv4AddressImpl +// + +IPv4AddressImpl::IPv4AddressImpl() +{ + std::memset(&_addr, 0, sizeof(_addr)); +} + + +IPv4AddressImpl::IPv4AddressImpl(const void* addr) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv4AddressImpl::IPv4AddressImpl(unsigned prefix) +{ + UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix); + _addr.s_addr = htonl(addr); +} + + +IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr) +{ + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); +} + + +IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr) +{ + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); + return *this; +} + + +std::string IPv4AddressImpl::toString() const +{ + const UInt8* bytes = reinterpret_cast(&_addr); + std::string result; + result.reserve(16); + NumberFormatter::append(result, bytes[0]); + result.append("."); + NumberFormatter::append(result, bytes[1]); + result.append("."); + NumberFormatter::append(result, bytes[2]); + result.append("."); + NumberFormatter::append(result, bytes[3]); + return result; +} + + +poco_socklen_t IPv4AddressImpl::length() const +{ + return sizeof(_addr); +} + + +const void* IPv4AddressImpl::addr() const +{ + return &_addr; +} + + +IPAddressImpl::Family IPv4AddressImpl::family() const +{ + return IPAddressImpl::IPv4; +} + + +int IPv4AddressImpl::af() const +{ + return AF_INET; +} + + +unsigned IPv4AddressImpl::prefixLength() const +{ + return maskBits(ntohl(_addr.s_addr), 32); +} + + +Poco::UInt32 IPv4AddressImpl::scope() const +{ + return 0; +} + + +bool IPv4AddressImpl::isWildcard() const +{ + return _addr.s_addr == INADDR_ANY; +} + + +bool IPv4AddressImpl::isBroadcast() const +{ + return _addr.s_addr == INADDR_NONE; +} + + +bool IPv4AddressImpl::isLoopback() const +{ + return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255 +} + + +bool IPv4AddressImpl::isMulticast() const +{ + return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24 +} + + +bool IPv4AddressImpl::isLinkLocal() const +{ + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16 +} + + +bool IPv4AddressImpl::isSiteLocal() const +{ + UInt32 addr = ntohl(_addr.s_addr); + return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24 + (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16 + (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255 +} + + +bool IPv4AddressImpl::isIPv4Compatible() const +{ + return true; +} + + +bool IPv4AddressImpl::isIPv4Mapped() const +{ + return true; +} + + +bool IPv4AddressImpl::isWellKnownMC() const +{ + return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8 +} + + +bool IPv4AddressImpl::isNodeLocalMC() const +{ + return false; +} + + +bool IPv4AddressImpl::isLinkLocalMC() const +{ + return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24 +} + + +bool IPv4AddressImpl::isSiteLocalMC() const +{ + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16 +} + + +bool IPv4AddressImpl::isOrgLocalMC() const +{ + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16 +} + + +bool IPv4AddressImpl::isGlobalMC() const +{ + UInt32 addr = ntohl(_addr.s_addr); + return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255 +} + + +IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr) +{ + if (addr.empty()) return IPv4AddressImpl(); +#if defined(_WIN32) + struct in_addr ia; + ia.s_addr = inet_addr(addr.c_str()); + if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") + return IPv4AddressImpl(); + else + return IPv4AddressImpl(&ia); +#else +#if __GNUC__ < 3 || defined(POCO_VXWORKS) + struct in_addr ia; + ia.s_addr = inet_addr(const_cast(addr.c_str())); + if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") + return IPv4AddressImpl(); + else + return IPv4AddressImpl(&ia); +#else + struct in_addr ia; + if (inet_aton(addr.c_str(), &ia)) + return IPv4AddressImpl(&ia); + else + return IPv4AddressImpl(); +#endif +#endif +} + + +void IPv4AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) +{ + poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET); + + _addr.s_addr &= static_cast(pMask)->_addr.s_addr; + _addr.s_addr |= static_cast(pSet)->_addr.s_addr & ~static_cast(pMask)->_addr.s_addr; +} + + +IPAddressImpl* IPv4AddressImpl::clone() const +{ + return new IPv4AddressImpl(&_addr); +} + + +IPv4AddressImpl IPv4AddressImpl::operator & (const IPv4AddressImpl& addr) const +{ + IPv4AddressImpl result(&_addr); + result._addr.s_addr &= addr._addr.s_addr; + return result; +} + + +IPv4AddressImpl IPv4AddressImpl::operator | (const IPv4AddressImpl& addr) const +{ + IPv4AddressImpl result(&_addr); + result._addr.s_addr |= addr._addr.s_addr; + return result; +} + + +IPv4AddressImpl IPv4AddressImpl::operator ^ (const IPv4AddressImpl& addr) const +{ + IPv4AddressImpl result(&_addr); + result._addr.s_addr ^= addr._addr.s_addr; + return result; +} + + +IPv4AddressImpl IPv4AddressImpl::operator ~ () const +{ +IPv4AddressImpl result(&_addr); + result._addr.s_addr ^= 0xffffffff; + return result; +} + + +bool IPv4AddressImpl::operator == (const IPv4AddressImpl& addr) const +{ + return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); +} + + +bool IPv4AddressImpl::operator != (const IPv4AddressImpl& addr) const +{ + return !(*this == addr); +} + + +#if defined(POCO_HAVE_IPv6) + + +// +// IPv6AddressImpl +// + + +IPv6AddressImpl::IPv6AddressImpl(): _scope(0) +{ + std::memset(&_addr, 0, sizeof(_addr)); +} + +IPv6AddressImpl::IPv6AddressImpl(const void* addr): _scope(0) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + +IPv6AddressImpl::IPv6AddressImpl(const void* addr, Poco::UInt32 scope): _scope(scope) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scope) +{ + std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr)); +} + + +IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr) +{ + _scope = addr._scope; + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); + return *this; +} + + +IPv6AddressImpl::IPv6AddressImpl(unsigned prefix): + _scope(0) +{ + unsigned i = 0; +#ifdef POCO_OS_FAMILY_WINDOWS + for (; prefix >= 16; ++i, prefix -= 16) { + _addr.s6_addr16[i] = 0xffff; + } + if (prefix > 0) + _addr.s6_addr16[i++] = htons(~(0xffff >> prefix)); + while (i < 8) + _addr.s6_addr16[i++] = 0; +#else + for (; prefix >= 32; ++i, prefix -= 32) { + _addr.s6_addr32[i] = 0xffffffff; + } + if (prefix > 0) + _addr.s6_addr32[i++] = htonl(~(0xffffffffU >> prefix)); + while (i < 4) + _addr.s6_addr32[i++] = 0; +#endif +} + +std::string IPv6AddressImpl::toString() const +{ + const UInt16* words = reinterpret_cast(&_addr); + if (isIPv4Compatible() || isIPv4Mapped()) + { + std::string result; + result.reserve(24); + if (words[5] == 0) + result.append("::"); + else + result.append("::ffff:"); + const UInt8* bytes = reinterpret_cast(&_addr); + NumberFormatter::append(result, bytes[12]); + result.append("."); + NumberFormatter::append(result, bytes[13]); + result.append("."); + NumberFormatter::append(result, bytes[14]); + result.append("."); + NumberFormatter::append(result, bytes[15]); + return result; + } + else + { + std::string result; + result.reserve(64); + bool zeroSequence = false; + int i = 0; + while (i < 8) + { + if (!zeroSequence && words[i] == 0) + { + int zi = i; + while (zi < 8 && words[zi] == 0) ++zi; + if (zi > i + 1) + { + i = zi; + result.append(":"); + zeroSequence = true; + } + } + if (i > 0) result.append(":"); + if (i < 8) NumberFormatter::appendHex(result, ntohs(words[i++])); + } + if (_scope > 0) + { + result.append("%"); +#if defined(_WIN32) + NumberFormatter::append(result, _scope); +#else + char buffer[IFNAMSIZ]; + if (if_indextoname(_scope, buffer)) + { + result.append(buffer); + } + else + { + NumberFormatter::append(result, _scope); + } +#endif + } + return toLower(result); + } +} + +poco_socklen_t IPv6AddressImpl::length() const +{ + return sizeof(_addr); +} + +const void* IPv6AddressImpl::addr() const +{ + return &_addr; +} + +IPAddressImpl::Family IPv6AddressImpl::family() const +{ + return IPAddressImpl::IPv6; +} + +int IPv6AddressImpl::af() const +{ + return AF_INET6; +} + +unsigned IPv6AddressImpl::prefixLength() const +{ + unsigned bits = 0; + unsigned bitPos = 128; +#if defined(POCO_OS_FAMILY_UNIX) + for (int i = 3; i >= 0; --i) + { + unsigned addr = ntohl(_addr.s6_addr32[i]); + if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits)); + bitPos -= 32; + } + return 0; +#elif defined(POCO_OS_FAMILY_WINDOWS) + for (int i = 7; i >= 0; --i) + { + unsigned short addr = ntohs(_addr.s6_addr16[i]); + if ((bits = maskBits(addr, 16))) return (bitPos - (16 - bits)); + bitPos -= 16; + } + return 0; +#else +#warning prefixLength() not implemented + throw NotImplementedException("prefixLength() not implemented"); +#endif +} +Poco::UInt32 IPv6AddressImpl::scope() const +{ + return _scope; +} + +bool IPv6AddressImpl::isWildcard() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0; +} + +bool IPv6AddressImpl::isBroadcast() const +{ + return false; +} + +bool IPv6AddressImpl::isLoopback() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && words[5] == 0 && words[6] == 0 && ntohs(words[7]) == 0x0001; +} + +bool IPv6AddressImpl::isMulticast() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFE0) == 0xFF00; +} + +bool IPv6AddressImpl::isLinkLocal() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFE0) == 0xFE80; +} + +bool IPv6AddressImpl::isSiteLocal() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return ((ntohs(words[0]) & 0xFFE0) == 0xFEC0) || ((ntohs(words[0]) & 0xFF00) == 0xFC00); +} + +bool IPv6AddressImpl::isIPv4Compatible() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0; +} + +bool IPv6AddressImpl::isIPv4Mapped() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ntohs(words[5]) == 0xFFFF; +} + +bool IPv6AddressImpl::isWellKnownMC() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFF0) == 0xFF00; +} + +bool IPv6AddressImpl::isNodeLocalMC() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFEF) == 0xFF01; +} + +bool IPv6AddressImpl::isLinkLocalMC() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFEF) == 0xFF02; +} + +bool IPv6AddressImpl::isSiteLocalMC() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFEF) == 0xFF05; +} + +bool IPv6AddressImpl::isOrgLocalMC() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFEF) == 0xFF08; +} + +bool IPv6AddressImpl::isGlobalMC() const +{ + const UInt16* words = reinterpret_cast(&_addr); + return (ntohs(words[0]) & 0xFFEF) == 0xFF0F; +} + +IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr) +{ + if (addr.empty()) return IPv6AddressImpl(); +#if defined(_WIN32) + struct addrinfo* pAI; + struct addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI); + if (rc == 0) + { + IPv6AddressImpl result = IPv6AddressImpl(&reinterpret_cast(pAI->ai_addr)->sin6_addr, static_cast(reinterpret_cast(pAI->ai_addr)->sin6_scope_id)); + freeaddrinfo(pAI); + return result; + } + else return IPv6AddressImpl(); +#else + struct in6_addr ia; + std::string::size_type pos = addr.find('%'); + if (std::string::npos != pos) + { + std::string::size_type start = ('[' == addr[0]) ? 1 : 0; + std::string unscopedAddr(addr, start, pos - start); + std::string scope(addr, pos + 1, addr.size() - start - pos); + Poco::UInt32 scopeId(0); + if (!(scopeId = if_nametoindex(scope.c_str()))) + return 0; + if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1) + return IPv6AddressImpl(&ia, scopeId); + else + return 0; + } + else + { + if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) + return new IPv6AddressImpl(&ia); + else + return 0; + } +#endif +} + +void IPv6AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) +{ + throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses"); +} + +IPAddressImpl* IPv6AddressImpl::clone() const +{ + return new IPv6AddressImpl(&_addr, _scope); +} + +IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const +{ + IPv6AddressImpl result(&_addr); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; + result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; + result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2]; + result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3]; + result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4]; + result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5]; + result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6]; + result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7]; +#else + result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0]; + result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1]; + result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2]; + result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3]; +#endif + return result; +} + +IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const +{ + IPv6AddressImpl result(&_addr); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; + result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; + result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2]; + result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3]; + result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4]; + result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5]; + result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6]; + result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7]; +#else + result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0]; + result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1]; + result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2]; + result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3]; +#endif + return result; +} + +IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const +{ + IPv6AddressImpl result(&_addr); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; + result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; + result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2]; + result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3]; + result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4]; + result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5]; + result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6]; + result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7]; +#else + result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0]; + result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1]; + result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2]; + result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3]; +#endif + return result; +} + +IPv6AddressImpl IPv6AddressImpl::operator ~ () const +{ + IPv6AddressImpl result(&_addr); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] ^= 0xffff; + result._addr.s6_addr16[1] ^= 0xffff; + result._addr.s6_addr16[2] ^= 0xffff; + result._addr.s6_addr16[3] ^= 0xffff; + result._addr.s6_addr16[4] ^= 0xffff; + result._addr.s6_addr16[5] ^= 0xffff; + result._addr.s6_addr16[6] ^= 0xffff; + result._addr.s6_addr16[7] ^= 0xffff; +#else + result._addr.s6_addr32[0] ^= 0xffffffff; + result._addr.s6_addr32[1] ^= 0xffffffff; + result._addr.s6_addr32[2] ^= 0xffffffff; + result._addr.s6_addr32[3] ^= 0xffffffff; +#endif + return result; +} + + +bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const +{ + return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); +} + + +bool IPv6AddressImpl::operator != (const IPv6AddressImpl& addr) const +{ + return !(*this == addr); +} + + +#endif // POCO_HAVE_IPv6 + + +} } } // namespace Poco::Net::Impl From f9243c20733c01dc0c14a10371f709a5934e29cc Mon Sep 17 00:00:00 2001 From: aleks-f Date: Thu, 17 Jan 2013 23:01:13 -0600 Subject: [PATCH 02/25] Removed old net initialization code --- Net/src/DNS.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/Net/src/DNS.cpp b/Net/src/DNS.cpp index ee3eddd44..1a7589d2c 100644 --- a/Net/src/DNS.cpp +++ b/Net/src/DNS.cpp @@ -245,23 +245,4 @@ void DNS::aierror(int code, const std::string& arg) } -void initializeNetwork() -{ -#if defined(_WIN32) - WORD version = MAKEWORD(2, 2); - WSADATA data; - if (WSAStartup(version, &data) != 0) - throw NetException("Failed to initialize network subsystem"); -#endif // _WIN32 -} - - -void uninitializeNetwork() -{ -#if defined(_WIN32) - WSACleanup(); -#endif // _WIN32 -} - - } } // namespace Poco::Net From 69f5d4e25ecc2014d995b93e20555052f56aa5be Mon Sep 17 00:00:00 2001 From: aleks-f Date: Thu, 24 Jan 2013 23:34:40 -0600 Subject: [PATCH 03/25] destructor call and some cleanup --- Net/include/Poco/Net/IPAddressImpl.h | 2 +- Net/src/IPAddress.cpp | 29 +++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Net/include/Poco/Net/IPAddressImpl.h b/Net/include/Poco/Net/IPAddressImpl.h index b1808e50d..d1e9ddfb9 100644 --- a/Net/include/Poco/Net/IPAddressImpl.h +++ b/Net/include/Poco/Net/IPAddressImpl.h @@ -86,10 +86,10 @@ public: virtual unsigned prefixLength() const = 0; virtual IPAddressImpl* clone() const = 0; + virtual ~IPAddressImpl(); protected: IPAddressImpl(); - virtual ~IPAddressImpl(); private: IPAddressImpl(const IPAddressImpl&); diff --git a/Net/src/IPAddress.cpp b/Net/src/IPAddress.cpp index 13bce33c1..0456f5777 100644 --- a/Net/src/IPAddress.cpp +++ b/Net/src/IPAddress.cpp @@ -64,7 +64,7 @@ namespace Net { IPAddress::IPAddress() { - new ((void*) _memory) IPv4AddressImpl(); + new (_memory) IPv4AddressImpl(); } @@ -80,10 +80,10 @@ IPAddress::IPAddress(const IPAddress& addr) IPAddress::IPAddress(Family family) { if (family == IPv4) - new ((void*) _memory) IPv4AddressImpl(); + new (_memory) IPv4AddressImpl(); #if defined(POCO_HAVE_IPv6) else if (family == IPv6) - new ((void*) _memory) IPv6AddressImpl(); + new (_memory) IPv6AddressImpl(); #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); @@ -149,10 +149,10 @@ IPAddress::IPAddress(const std::string& addr, Family family) IPAddress::IPAddress(const void* addr, poco_socklen_t length) { if (length == sizeof(struct in_addr)) - new ((void*) _memory) IPv4AddressImpl(addr); + new (_memory) IPv4AddressImpl(addr); #if defined(POCO_HAVE_IPv6) else if (length == sizeof(struct in6_addr)) - new ((void*) _memory) IPv6AddressImpl(addr); + new (_memory) IPv6AddressImpl(addr); #endif else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); } @@ -161,10 +161,10 @@ IPAddress::IPAddress(const void* addr, poco_socklen_t length) IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope) { if (length == sizeof(struct in_addr)) - new ((void*) _memory) IPv4AddressImpl(addr); + new (_memory) IPv4AddressImpl(addr); #if defined(POCO_HAVE_IPv6) else if (length == sizeof(struct in6_addr)) - new ((void*) _memory) IPv6AddressImpl(addr, scope); + new (_memory) IPv6AddressImpl(addr, scope); #endif else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); } @@ -175,13 +175,13 @@ IPAddress::IPAddress(unsigned prefix, Family family) if (family == IPv4) { if (prefix <= 32) - new ((void*) _memory) IPv4AddressImpl(prefix); + new (_memory) IPv4AddressImpl(prefix); } #if defined(POCO_HAVE_IPv6) else if (family == IPv6) { if (prefix <= 128) - new ((void*) _memory) IPv6AddressImpl(prefix); + new (_memory) IPv6AddressImpl(prefix); } #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); @@ -194,10 +194,11 @@ IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address) { ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family; if (family == AF_INET) - new ((void*) _memory) IPv4AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin_addr); + new (_memory) IPv4AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin_addr); #if defined(POCO_HAVE_IPv6) else if (family == AF_INET6) - new ((void*) _memory) IPv6AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin6_addr, reinterpret_cast(socket_address.lpSockaddr)->sin6_scope_id); + new (_memory) IPv6AddressImpl(&reinterpret_cast(socket_address.lpSockaddr)->sin6_addr, + reinterpret_cast(socket_address.lpSockaddr)->sin6_scope_id); #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); } @@ -208,10 +209,11 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr) { unsigned short family = sockaddr.sa_family; if (family == AF_INET) - new ((void*) _memory) IPv4AddressImpl(&reinterpret_cast(&sockaddr)->sin_addr); + new (_memory) IPv4AddressImpl(&reinterpret_cast(&sockaddr)->sin_addr); #if defined(POCO_HAVE_IPv6) else if (family == AF_INET6) - new ((void*) _memory) IPv6AddressImpl(&reinterpret_cast(&sockaddr)->sin6_addr, reinterpret_cast(&sockaddr)->sin6_scope_id); + new (_memory) IPv6AddressImpl(&reinterpret_cast(&sockaddr)->sin6_addr, + reinterpret_cast(&sockaddr)->sin6_scope_id); #endif else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); } @@ -219,6 +221,7 @@ IPAddress::IPAddress(const struct sockaddr& sockaddr) IPAddress::~IPAddress() { + pImpl()->~IPAddressImpl(); } From 911f22508e921c6077e8156892622ad32a928b6d Mon Sep 17 00:00:00 2001 From: aleks-f Date: Thu, 31 Jan 2013 21:12:13 -0600 Subject: [PATCH 04/25] Any SOO --- .../ApacheConnector_x64_vs100.vcxproj | 86 +-- Crypto/testsuite/TestSuite_x64_vs100.vcxproj | 162 +++--- Foundation/Foundation_CE_vs90.vcproj | 8 + Foundation/Foundation_vs100.vcxproj | 2 + Foundation/Foundation_vs100.vcxproj.filters | 6 + Foundation/Foundation_vs110.vcxproj | 2 + Foundation/Foundation_vs110.vcxproj.filters | 6 + Foundation/Foundation_vs71.vcproj | 9 + Foundation/Foundation_vs80.vcproj | 12 + Foundation/Foundation_vs90.vcproj | 12 + Foundation/Foundation_x64_vs100.vcxproj | 15 +- .../Foundation_x64_vs100.vcxproj.filters | 9 + Foundation/Foundation_x64_vs110.vcxproj | 3 + .../Foundation_x64_vs110.vcxproj.filters | 9 + Foundation/Foundation_x64_vs90.vcproj | 12 + Foundation/include/Poco/Any.h | 228 +++++++- Foundation/include/Poco/Config.h | 6 + .../include/Poco/SmallObjectAllocator.h | 251 +++++++++ Foundation/include/Poco/Types.h | 11 + Foundation/src/FIFOBufferStream.cpp | 4 +- .../testsuite/TestApp_x64_vs100.vcxproj | 12 +- .../testsuite/TestLibrary_x64_vs100.vcxproj | 4 +- .../testsuite/TestSuite_x64_vs100.vcxproj | 12 +- Foundation/testsuite/src/AnyTest.cpp | 3 + Foundation/testsuite/src/CoreTest.cpp | 165 ++++++ Foundation/testsuite/src/CoreTest.h | 1 + Net/Net_CE_vs90.vcproj | 4 + Net/Net_vs110.vcxproj | 2 + Net/Net_vs110.vcxproj.filters | 6 + Net/Net_vs71.vcproj | 4 + Net/Net_vs80.vcproj | 4 + Net/Net_vs90.vcproj | 4 + Net/Net_x64_vs100.vcxproj | 512 +++++++++--------- Net/Net_x64_vs100.vcxproj.filters | 6 + Net/Net_x64_vs110.vcxproj | 2 + Net/Net_x64_vs110.vcxproj.filters | 6 + Net/Net_x64_vs90.vcproj | 4 + Net/include/Poco/Net/Net.h | 20 - Net/include/Poco/Net/SocketDefs.h | 21 + Net/src/StreamSocket.cpp | 4 +- Net/testsuite/src/WebSocketTest.cpp | 10 +- Util/Util_vs100.vcxproj | 255 ++++----- Util/Util_vs100.vcxproj.filters | 3 + 43 files changed, 1345 insertions(+), 572 deletions(-) create mode 100644 Foundation/include/Poco/SmallObjectAllocator.h diff --git a/ApacheConnector/ApacheConnector_x64_vs100.vcxproj b/ApacheConnector/ApacheConnector_x64_vs100.vcxproj index 1fcb7634f..2583983fb 100644 --- a/ApacheConnector/ApacheConnector_x64_vs100.vcxproj +++ b/ApacheConnector/ApacheConnector_x64_vs100.vcxproj @@ -1,4 +1,4 @@ - + @@ -16,40 +16,40 @@ ApacheConnector Win32Proj - - + + DynamicLibrary MultiByte - + DynamicLibrary MultiByte - - - - + + + + - - + + - + <_ProjectFileVersion>10.0.40219.1 - ..\bin64\ - obj64\$(Configuration)\ - true - ..\bin64\ - obj64\$(Configuration)\ - false - mod_poco64d - mod_poco64 + ..\bin64\ + obj64\$(Configuration)\ + true + ..\bin64\ + obj64\$(Configuration)\ + false + mod_poco64d + mod_poco64 - + Disabled .\include;..\Foundation\include;..\Net\include;..\Util\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;ApacheHandlers_EXPORTS;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;_USRDLL;ApacheHandlers_EXPORTS;%(PreprocessorDefinitions) true true EnableFastChecks @@ -58,7 +58,7 @@ true true true - + Level3 ProgramDatabase Default @@ -76,7 +76,7 @@ MachineX64 - + Disabled OnlyExplicitInline @@ -84,16 +84,16 @@ Speed true .\include;..\Foundation\include;..\Net\include;..\Util\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;ApacheHandlers_EXPORTS;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;_USRDLL;ApacheHandlers_EXPORTS;%(PreprocessorDefinitions) true MultiThreadedDLL false true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -111,23 +111,23 @@ - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + \ No newline at end of file diff --git a/Crypto/testsuite/TestSuite_x64_vs100.vcxproj b/Crypto/testsuite/TestSuite_x64_vs100.vcxproj index 9b7eadef4..32bde0615 100644 --- a/Crypto/testsuite/TestSuite_x64_vs100.vcxproj +++ b/Crypto/testsuite/TestSuite_x64_vs100.vcxproj @@ -1,4 +1,4 @@ - + @@ -32,90 +32,92 @@ TestSuite Win32Proj - - + + Application Dynamic MultiByte - + Application Dynamic MultiByte - + Application Static MultiByte - + Application Static MultiByte - + Application Dynamic MultiByte - + Application Dynamic MultiByte - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + <_ProjectFileVersion>10.0.40219.1 - bin64\ - obj64\$(Configuration)\ - true - bin64\ - obj64\$(Configuration)\ - false - bin64\static_mt\ - obj64\$(Configuration)\ - true - bin64\static_mt\ - obj64\$(Configuration)\ - false - bin64\static_md\ - obj64\$(Configuration)\ - true - bin64\static_md\ - obj64\$(Configuration)\ - false - TestSuited - TestSuited - TestSuited - TestSuite - TestSuite - TestSuite + bin64\ + obj64\$(Configuration)\ + true + bin64\ + obj64\$(Configuration)\ + false + bin64\static_mt\ + obj64\$(Configuration)\ + true + bin64\static_mt\ + obj64\$(Configuration)\ + false + bin64\static_md\ + obj64\$(Configuration)\ + true + bin64\static_md\ + obj64\$(Configuration)\ + false + TestSuited + TestSuited + TestSuited + TestSuite + TestSuite + TestSuite + C:\openssl\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include; + C:\openssl\lib;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSdkDir)lib\x64; - + Disabled ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) true true EnableFastChecks @@ -124,7 +126,7 @@ true true true - + Level3 ProgramDatabase Default @@ -141,7 +143,7 @@ MachineX64 - + Disabled OnlyExplicitInline @@ -149,16 +151,16 @@ Speed true ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) true MultiThreadedDLL false true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -173,11 +175,11 @@ MachineX64 - + Disabled ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true true EnableFastChecks @@ -186,7 +188,7 @@ true true true - + Level3 ProgramDatabase Default @@ -204,7 +206,7 @@ MachineX64 - + Disabled OnlyExplicitInline @@ -212,16 +214,16 @@ Speed true ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true MultiThreaded false true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -237,11 +239,11 @@ MachineX64 - + Disabled ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true true EnableFastChecks @@ -250,7 +252,7 @@ true true true - + Level3 ProgramDatabase Default @@ -267,7 +269,7 @@ MachineX64 - + Disabled OnlyExplicitInline @@ -275,16 +277,16 @@ Speed true ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;..\..\Foundation\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true MultiThreadedDLL false true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -300,18 +302,18 @@ - - - - + + + + - - - - - + + + + + - - - + + + \ No newline at end of file diff --git a/Foundation/Foundation_CE_vs90.vcproj b/Foundation/Foundation_CE_vs90.vcproj index f3b552211..2c7aac1c2 100644 --- a/Foundation/Foundation_CE_vs90.vcproj +++ b/Foundation/Foundation_CE_vs90.vcproj @@ -6689,6 +6689,10 @@ RelativePath=".\include\Poco\ObjectPool.h" > + + @@ -6721,6 +6725,10 @@ RelativePath=".\include\Poco\SingletonHolder.h" > + + diff --git a/Foundation/Foundation_vs100.vcxproj b/Foundation/Foundation_vs100.vcxproj index a30a67b05..beac537ee 100644 --- a/Foundation/Foundation_vs100.vcxproj +++ b/Foundation/Foundation_vs100.vcxproj @@ -1024,6 +1024,7 @@ + @@ -1033,6 +1034,7 @@ + diff --git a/Foundation/Foundation_vs100.vcxproj.filters b/Foundation/Foundation_vs100.vcxproj.filters index c6f74b470..2821c72c5 100644 --- a/Foundation/Foundation_vs100.vcxproj.filters +++ b/Foundation/Foundation_vs100.vcxproj.filters @@ -1853,6 +1853,12 @@ Streams\Header Files + + Core\Header Files + + + Core\Header Files + diff --git a/Foundation/Foundation_vs110.vcxproj b/Foundation/Foundation_vs110.vcxproj index 30e807248..13fa6ac62 100644 --- a/Foundation/Foundation_vs110.vcxproj +++ b/Foundation/Foundation_vs110.vcxproj @@ -1027,6 +1027,7 @@ + @@ -1036,6 +1037,7 @@ + diff --git a/Foundation/Foundation_vs110.vcxproj.filters b/Foundation/Foundation_vs110.vcxproj.filters index ba3474bac..031b36aaf 100644 --- a/Foundation/Foundation_vs110.vcxproj.filters +++ b/Foundation/Foundation_vs110.vcxproj.filters @@ -1037,6 +1037,9 @@ Core\Header Files + + Core\Header Files + Core\Header Files @@ -1850,6 +1853,9 @@ Core\Header Files + + Core\Header Files + diff --git a/Foundation/Foundation_vs71.vcproj b/Foundation/Foundation_vs71.vcproj index 07e5855b0..6b214fa1e 100644 --- a/Foundation/Foundation_vs71.vcproj +++ b/Foundation/Foundation_vs71.vcproj @@ -904,6 +904,12 @@ + + + + @@ -928,6 +934,9 @@ + + diff --git a/Foundation/Foundation_vs80.vcproj b/Foundation/Foundation_vs80.vcproj index c321e3157..9154b8714 100644 --- a/Foundation/Foundation_vs80.vcproj +++ b/Foundation/Foundation_vs80.vcproj @@ -1207,6 +1207,14 @@ RelativePath=".\include\Poco\NumericString.h" > + + + + @@ -1239,6 +1247,10 @@ RelativePath=".\include\Poco\SingletonHolder.h" > + + diff --git a/Foundation/Foundation_vs90.vcproj b/Foundation/Foundation_vs90.vcproj index 3bb20cf15..d623507b4 100644 --- a/Foundation/Foundation_vs90.vcproj +++ b/Foundation/Foundation_vs90.vcproj @@ -1204,6 +1204,14 @@ RelativePath=".\include\Poco\NumericString.h" > + + + + @@ -1236,6 +1244,10 @@ RelativePath=".\include\Poco\SingletonHolder.h" > + + diff --git a/Foundation/Foundation_x64_vs100.vcxproj b/Foundation/Foundation_x64_vs100.vcxproj index 94b8ceb6a..1829287f9 100644 --- a/Foundation/Foundation_x64_vs100.vcxproj +++ b/Foundation/Foundation_x64_vs100.vcxproj @@ -108,7 +108,7 @@ Disabled .\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;PCRE_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;PCRE_STATIC;%(PreprocessorDefinitions) true true EnableFastChecks @@ -143,7 +143,7 @@ Speed true .\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;PCRE_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;_USRDLL;Foundation_EXPORTS;PCRE_STATIC;%(PreprocessorDefinitions) false false false @@ -183,7 +183,7 @@ Speed true .\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) false false false @@ -211,7 +211,7 @@ Disabled .\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) true true EnableFastChecks @@ -238,7 +238,7 @@ Disabled .\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) true true EnableFastChecks @@ -269,7 +269,7 @@ Speed true .\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;Foundation_EXPORTS;POCO_STATIC;PCRE_STATIC;%(PreprocessorDefinitions) false false false @@ -1025,6 +1025,8 @@ + + @@ -1034,6 +1036,7 @@ + diff --git a/Foundation/Foundation_x64_vs100.vcxproj.filters b/Foundation/Foundation_x64_vs100.vcxproj.filters index 94b5ee37e..835260466 100644 --- a/Foundation/Foundation_x64_vs100.vcxproj.filters +++ b/Foundation/Foundation_x64_vs100.vcxproj.filters @@ -1013,6 +1013,12 @@ Core\Header Files + + Core\Header Files + + + Core\Header Files + Core\Header Files @@ -1841,6 +1847,9 @@ Text\Header Files + + Core\Header Files + diff --git a/Foundation/Foundation_x64_vs110.vcxproj b/Foundation/Foundation_x64_vs110.vcxproj index 13a842e3a..a4b6d8638 100644 --- a/Foundation/Foundation_x64_vs110.vcxproj +++ b/Foundation/Foundation_x64_vs110.vcxproj @@ -1031,6 +1031,8 @@ + + @@ -1040,6 +1042,7 @@ + diff --git a/Foundation/Foundation_x64_vs110.vcxproj.filters b/Foundation/Foundation_x64_vs110.vcxproj.filters index 94b5ee37e..26e78a271 100644 --- a/Foundation/Foundation_x64_vs110.vcxproj.filters +++ b/Foundation/Foundation_x64_vs110.vcxproj.filters @@ -1013,6 +1013,12 @@ Core\Header Files + + Core\Header Files + + + Core\Header Files + Core\Header Files @@ -1037,6 +1043,9 @@ Core\Header Files + + Core\Header Files + Core\Header Files diff --git a/Foundation/Foundation_x64_vs90.vcproj b/Foundation/Foundation_x64_vs90.vcproj index 3ee699ca6..05fb27781 100644 --- a/Foundation/Foundation_x64_vs90.vcproj +++ b/Foundation/Foundation_x64_vs90.vcproj @@ -1198,6 +1198,14 @@ RelativePath=".\include\Poco\NumberParser.h" > + + + + @@ -1234,6 +1242,10 @@ RelativePath=".\include\Poco\SingletonHolder.h" > + + diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index 34cb595a7..eb8c14555 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -5,7 +5,7 @@ // // Library: Foundation // Package: Core -// Module: Any +// Module: Any // // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. // Extracted from Boost 1.33.1 lib and adapted for poco: Peter Schojer/AppliedInformatics 2006-02-02 @@ -52,17 +52,198 @@ class Any /// /// Code taken from the Boost 1.33.1 library. Original copyright by Kevlin Henney. Modified for Poco /// by Applied Informatics. + /// + /// Modified for small object optimization support (optionally supported through conditional compilation) + /// by Alex Fabijanic. { + +#ifndef POCO_NO_SOO + public: - Any(): - _content(0) + + Any() + /// Creates an empty any type. + { + } + + template + Any(const ValueType & value) + /// Creates an any which stores the init parameter inside. + /// + /// Example: + /// Any a(13); + /// Any a(string("12345")); + { + construct(value); + } + + Any(const Any& other) + /// Copy constructor, works with both empty and initialized Any values. + { + construct(other); + } + + ~Any() + { + if(!empty()) + { + if(flag()) + content()->~Placeholder(); + else + delete content(); + } + } + + template + Any & operator=(const ValueType& value) + /// Assignment operator for all types != Any. + /// + /// Example: + /// Any a = 13; + /// Any a = string("12345"); + { + this->~Any(); + construct(value); + return *this; + } + + Any& operator = (Any value) + /// Assignment operator for Any. + { + this->~Any(); + construct(value); + return *this; + } + + bool empty() const + /// Returns true if the Any is empty. + { + //return !(flags() & ASSIGNED); + return _placeholder.pHolder == 0; + } + + const std::type_info & type() const + /// Returns the type information of the stored content. + /// If the Any is empty typeid(void) is returned. + /// It is recommended to always query an Any for its type info before + /// trying to extract data via an AnyCast/RefAnyCast. + { + return empty() ? typeid(void) : content()->type(); + } + +private: + + class Placeholder + { + public: + + virtual ~Placeholder() + { + } + + virtual const std::type_info & type() const = 0; + virtual Placeholder * clone(Placeholder* pMem = 0) const = 0; + }; + + template + class Holder : public Placeholder + { + public: + Holder(const ValueType & value) : _held(value) + { + } + + virtual const std::type_info & type() const + { + return typeid(ValueType); + } + + virtual Placeholder * clone(Placeholder* pMem = 0) const + { + return pMem && (sizeof(_held) <= POCO_SMALL_OBJECT_SIZE) ? + new (pMem) Holder(_held) : + new Holder(_held); + } + + ValueType _held; + + private: + Holder & operator = (const Holder &); + }; + + Placeholder* content() const + { + if (empty()) return 0; + + if(flag()) + return (Placeholder *) &(_placeholder.holder); + else + return _placeholder.pHolder; + } + + template + void construct(const ValueType & value) + { + if (sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE) + { + new (_placeholder.holder) Holder(value); + flag() = 1; + } + else + { + _placeholder.pHolder = new Holder(value); + flag() = 0; + } + } + + void construct(const Any & other) + { + if(other.flag()) + { + other.content()->clone((Placeholder*) &_placeholder.holder); + flag() = 1; + return; + } + else if(!(other.empty())) + _placeholder.pHolder = other._placeholder.pHolder->clone(); + + flag() = 0; + } + + union PH + /// Placeholder union. If Holder fits into POCO_SMALL_OBJECT_SIZE + /// bytes of storage, it will be placement-new-allocated into the local buffer + /// (i.e. there will be no heap-allocation. The local buffer size is one byte + /// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating + /// where the object was allocated (0 => heap, 1 => local). + { + PH () + { + std::memset(holder, 0, sizeof(PH)); + } + + Placeholder* pHolder; + mutable unsigned char holder[POCO_SMALL_OBJECT_SIZE + 1]; + } _placeholder; + + unsigned char& flag() const + { + return _placeholder.holder[POCO_SMALL_OBJECT_SIZE]; + } + + +#else // if POCO_NO_SOO + + +public: + Any(): _pHolder(0) /// Creates an empty any type. { } template Any(const ValueType& value): - _content(new Holder(value)) + _pHolder(new Holder(value)) /// Creates an any which stores the init parameter inside. /// /// Example: @@ -72,20 +253,20 @@ public: } Any(const Any& other): - _content(other._content ? other._content->clone() : 0) - /// Copy constructor, works with empty Anys and initialized Any values. + _pHolder(other._pHolder ? other._pHolder->clone() : 0) + /// Copy constructor, works with both empty and initialized Any values. { } ~Any() { - delete _content; + delete _pHolder; } Any& swap(Any& rhs) /// Swaps the content of the two Anys. { - std::swap(_content, rhs._content); + std::swap(_pHolder, rhs._pHolder); return *this; } @@ -94,8 +275,8 @@ public: /// Assignment operator for all types != Any. /// /// Example: - /// Any a = 13; - /// Any a = string("12345"); + /// Any a = 13; + /// Any a = string("12345"); { Any(rhs).swap(*this); return *this; @@ -109,18 +290,18 @@ public: } bool empty() const - /// returns true if the Any is empty + /// Returns true if the Any is empty. { - return !_content; + return !_pHolder; } const std::type_info& type() const /// Returns the type information of the stored content. /// If the Any is empty typeid(void) is returned. - /// It is suggested to always query an Any for its type info before trying to extract - /// data via an AnyCast/RefAnyCast. + /// It is recommended to always query an Any for its type info before + /// trying to extract data via an AnyCast/RefAnyCast. { - return _content ? _content->type() : typeid(void); + return _pHolder ? _pHolder->type() : typeid(void); } private: @@ -155,16 +336,27 @@ private: } ValueType _held; + + private: + Holder & operator=(const Holder &); }; + Placeholder* content() const + { + return _pHolder; + } + private: + Placeholder* _pHolder; + +#endif // POCO_NO_SOO + template friend ValueType* AnyCast(Any*); template friend ValueType* UnsafeAnyCast(Any*); - Placeholder* _content; }; @@ -178,7 +370,7 @@ ValueType* AnyCast(Any* operand) /// Will return NULL if the cast fails, i.e. types don't match. { return operand && operand->type() == typeid(ValueType) - ? &static_cast*>(operand->_content)->_held + ? &static_cast*>(operand->content())->_held : 0; } @@ -264,7 +456,7 @@ ValueType* UnsafeAnyCast(Any* operand) /// use typeid() comparison, e.g., when our types may travel across /// different shared libraries. { - return &static_cast*>(operand->_content)->_held; + return &static_cast*>(operand->_pHolder)->_held; } diff --git a/Foundation/include/Poco/Config.h b/Foundation/include/Poco/Config.h index 0079ee0c3..fa69a1952 100644 --- a/Foundation/include/Poco/Config.h +++ b/Foundation/include/Poco/Config.h @@ -86,6 +86,12 @@ // #define POCO_THREAD_PRIORITY_MAX 31 +// Define to disable small object optimization. +// If not defined, Any and Dynamic::Var (and similar +// optimization candidates) will be auto-allocated on the +// stack in cases when value holder fits into . +// #define POCO_NO_SOO + // Following are options to remove certain features // to reduce library/executable size for smaller // embedded platforms. By enabling these options, diff --git a/Foundation/include/Poco/SmallObjectAllocator.h b/Foundation/include/Poco/SmallObjectAllocator.h new file mode 100644 index 000000000..be7cc8b19 --- /dev/null +++ b/Foundation/include/Poco/SmallObjectAllocator.h @@ -0,0 +1,251 @@ +// +// SmallObjectAllocator.h +// +// $Id: //poco/1.4/Foundation/include/Poco/SmallObjectAllocator.h#1 $ +// +// Library: Foundation +// Package: Core +// Module: SmallObjectAllocator +// +// Definition of the SmallObjectAllocator template. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Foundation_SmallObjectAllocator_INCLUDED +#define Foundation_SmallObjectAllocator_INCLUDED + + +#include "Poco/Foundation.h" +#include "Poco/Types.h" + + +namespace Poco { + + +template +class SmallObjectAllocator + /// SmallObjectAllocator template is a lightweight wrapper implementing + /// small object allocation optimization idiom. Class is statically + /// parameterized on type created and the size threshold, which defaults + /// to the created object size; it follows that the default behavior is + /// use of automatically allocated memory (i.e. the value wrapped is + /// stored in the pre-allocated buffer). To enforce heap allocation, + /// specify S parameter to a value smaller than the size of the type + /// being instantiated. + /// + /// The SmallObjectAllocator trade-off is the runtime check for memory + /// location where the value resides. The runtime check occurs at + /// construction/destruction as well as every value access. Value + /// access check can be alleviated by caching the value reference. + /// + /// Usage example: + /// + /// SmallObjectAllocator s; // on the stack + /// SmallObjectAllocator h; // force heap alloc + /// int& i = s.get(); // no runtime performance penalty after this point + /// i = 5; + /// +{ +public: + SmallObjectAllocator() + { + if (isOnHeap()) _memory.ptr = new T(); + else new (_memory.buf) T; + } + + SmallObjectAllocator(const T& val) + { + if (isOnHeap()) _memory.ptr = new T(val); + else new (_memory.buf) T(val); + } + + SmallObjectAllocator(const SmallObjectAllocator& other) + { + if (this != &other) + { + if (isOnHeap()) + _memory.ptr = new T(*other._memory.ptr); + else + new (_memory.buf) T(*reinterpret_cast(other._memory.buf)); + } + } + + ~SmallObjectAllocator() + { + if (isOnHeap()) delete _memory.ptr; + else reinterpret_cast(_memory.buf)->~T(); + } + + SmallObjectAllocator& operator =(const SmallObjectAllocator& other) + { + if (this != &other) + { + if (isOnHeap()) + _memory.ptr = new T(*other._memory.ptr); + else + new (_memory.buf) T(*reinterpret_cast(other._memory.buf)); + } + + return *this; + } + + T& get() + { + if (isOnHeap()) + return *_memory.ptr; + else + return reinterpret_cast(*(_memory.buf)); + } + + const T& get() const + { + if (isOnHeap()) + return *_memory.ptr; + else + return reinterpret_cast(*_memory.buf); + } + + bool isOnHeap() const + { + return sizeof(T) > S; + } + +private: + union + { + unsigned char buf[S]; + T* ptr; + } _memory; +}; + + +template <> +class SmallObjectAllocator + /// SmallObjectAllocator char* specialization. + /// + /// The treshold between auto and heap allocation + /// is controlled through POCO_SMALL_OBJECT_SIZE compile + /// time constant, which on 32 or 64 systems defaults + /// to 31 or 63 bytes respectively. This specialization + /// adds an extra byte to indicate the allocation strategy. + /// + /// To summarize, e.g. POCO_SMALL_OBJECT_SIZE value of 7 will + /// take up at least 8 bytes of storage (for auto allocation) + /// with 6 bytes as the effective string length: + /// + /// +---+---+---+---+---+---+---+---+ + /// | c | c | c | c | c | c | 0 | f | + /// +---+---+---+---+---+---+---+---+ + /// + /// Legend: + /// c - character + /// 0 - terminating zero + /// f - allocation flag + /// +{ +public: + static const std::size_t Size = POCO_SMALL_OBJECT_SIZE; + + SmallObjectAllocator(std::size_t sz) + { + _memory.buf[Size] = (sz > Size) ? 1 : 0; + if (_memory.buf[Size]) _memory.ptr = new char[sz + 1]; + } + + SmallObjectAllocator(const char* pCh, std::size_t sz) + { + allocateAndAssign(pCh, sz); + } + + SmallObjectAllocator(const char* pCh) + { + allocateAndAssign(pCh, strlen(pCh)); + } + + ~SmallObjectAllocator() + { + if (_memory.buf[Size]) delete _memory.ptr; + } + + SmallObjectAllocator & operator = (const char* pCh) + { + allocateAndAssign(pCh, strlen(pCh)); + return *this; + } + + char* get() + { + if (_memory.buf[Size]) return _memory.ptr; + else return _memory.buf; + } + + const char* get() const + { + if (_memory.buf[Size]) return _memory.ptr; + else return _memory.buf; + } + + bool isOnHeap() const + { + return _memory.buf[Size] != 0; + } + +private: + SmallObjectAllocator(); + + void allocateAndAssign(const char* pCh, std::size_t sz) + { + _memory.buf[Size] = (sz > Size) ? 1 : 0; + if (_memory.buf[Size]) + { + _memory.ptr = new char[sz + 1]; + _memory.ptr[sz] = '\0'; + std::memcpy(_memory.ptr, pCh, sz); + } + else + { + _memory.buf[sz] = '\0'; + std::memcpy(_memory.buf, pCh, sz); + } + } + + union + { + char buf[Size + 1]; + char* ptr; + } _memory; +}; + + +typedef SmallObjectAllocator SmallStringAllocator; + + +} // namespace Poco + + +#endif // Foundation_SmallObjectAllocator_INCLUDED diff --git a/Foundation/include/Poco/Types.h b/Foundation/include/Poco/Types.h index 6f1c41a27..6c87ef118 100644 --- a/Foundation/include/Poco/Types.h +++ b/Foundation/include/Poco/Types.h @@ -220,6 +220,17 @@ namespace Poco { #endif +// Small object size in bytes. Where applicable (e.g. +// SmallObjectAllocator specialization of , Any, etc) +// objects longer than this value will be alocated on the heap. +// See Poco/SmallObjectAllocator.h for details. +#if (POCO_PTR_IS_64_BIT == 1) + #define POCO_SMALL_OBJECT_SIZE 63 +#else + #define POCO_SMALL_OBJECT_SIZE 31 +#endif + + } // namespace Poco diff --git a/Foundation/src/FIFOBufferStream.cpp b/Foundation/src/FIFOBufferStream.cpp index 212c2b22c..ccf42fa33 100644 --- a/Foundation/src/FIFOBufferStream.cpp +++ b/Foundation/src/FIFOBufferStream.cpp @@ -95,14 +95,14 @@ FIFOBufferStreamBuf::~FIFOBufferStreamBuf() int FIFOBufferStreamBuf::readFromDevice(char* buffer, std::streamsize length) { poco_assert (length > 0); - return _fifoBuffer.read(buffer, static_cast(length)); + return static_cast(_fifoBuffer.read(buffer, static_cast(length))); } int FIFOBufferStreamBuf::writeToDevice(const char* buffer, std::streamsize length) { poco_assert (length > 0); - return _fifoBuffer.write(buffer, static_cast(length)); + return static_cast(_fifoBuffer.write(buffer, static_cast(length))); } diff --git a/Foundation/testsuite/TestApp_x64_vs100.vcxproj b/Foundation/testsuite/TestApp_x64_vs100.vcxproj index 84d3cd7d8..a777c7291 100644 --- a/Foundation/testsuite/TestApp_x64_vs100.vcxproj +++ b/Foundation/testsuite/TestApp_x64_vs100.vcxproj @@ -122,7 +122,7 @@ Disabled %(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -152,7 +152,7 @@ Speed true %(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -185,7 +185,7 @@ Speed true %(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -214,7 +214,7 @@ Disabled %(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -240,7 +240,7 @@ Disabled %(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -270,7 +270,7 @@ Speed true %(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions) true MultiThreaded false diff --git a/Foundation/testsuite/TestLibrary_x64_vs100.vcxproj b/Foundation/testsuite/TestLibrary_x64_vs100.vcxproj index 9c407dfb1..8ab0988a6 100644 --- a/Foundation/testsuite/TestLibrary_x64_vs100.vcxproj +++ b/Foundation/testsuite/TestLibrary_x64_vs100.vcxproj @@ -51,7 +51,7 @@ Disabled ..\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true true EnableFastChecks @@ -85,7 +85,7 @@ Speed true ..\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true MultiThreadedDLL false diff --git a/Foundation/testsuite/TestSuite_x64_vs100.vcxproj b/Foundation/testsuite/TestSuite_x64_vs100.vcxproj index ed762843e..baae24b0c 100644 --- a/Foundation/testsuite/TestSuite_x64_vs100.vcxproj +++ b/Foundation/testsuite/TestSuite_x64_vs100.vcxproj @@ -115,7 +115,7 @@ Disabled ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -146,7 +146,7 @@ Speed true ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0600;%(PreprocessorDefinitions) true MultiThreadedDLL false @@ -180,7 +180,7 @@ Speed true ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true Default MultiThreadedDLL @@ -211,7 +211,7 @@ Disabled ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -238,7 +238,7 @@ Disabled ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;_DEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -270,7 +270,7 @@ Speed true ..\include;..\..\CppUnit\include;..\..\CppUnit\WinTestRunner\include;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) + WIN32;_WIN64;NDEBUG;_WINDOWS;WINVER=0x0600;POCO_STATIC;%(PreprocessorDefinitions) true false Default diff --git a/Foundation/testsuite/src/AnyTest.cpp b/Foundation/testsuite/src/AnyTest.cpp index 82dbe8f9d..3fee242d9 100644 --- a/Foundation/testsuite/src/AnyTest.cpp +++ b/Foundation/testsuite/src/AnyTest.cpp @@ -72,6 +72,9 @@ AnyTest::~AnyTest() void AnyTest::testInt() { + Any e; + assert (e.empty()); + Any a = 13; assert (a.type() == typeid(int)); int* i = AnyCast(&a); diff --git a/Foundation/testsuite/src/CoreTest.cpp b/Foundation/testsuite/src/CoreTest.cpp index 0a2bf5e9e..78187e8e9 100644 --- a/Foundation/testsuite/src/CoreTest.cpp +++ b/Foundation/testsuite/src/CoreTest.cpp @@ -45,6 +45,7 @@ #include "Poco/Ascii.h" #include "Poco/BasicEvent.h" #include "Poco/Delegate.h" +#include "Poco/SmallObjectAllocator.h" #include "Poco/Exception.h" #include #include @@ -64,6 +65,7 @@ using Poco::AtomicCounter; using Poco::Nullable; using Poco::Ascii; using Poco::BasicEvent; +using Poco::SmallObjectAllocator; using Poco::delegate; using Poco::NullType; using Poco::InvalidAccessException; @@ -96,6 +98,37 @@ namespace } +class Small +{ +}; + + +struct Parent +{ + Parent() { i = -1; } + virtual ~Parent() { i= -2; } + + static int i; +}; + + +int Parent::i = 0; + + +struct Medium : public Parent +{ + +}; + + +struct Large +{ + Large() : i(1), j(2), k(3), l(4) { } + long i,j,k; + const long l; +}; + + // // The bugcheck test is normally disabled, as it // causes a break into the debugger. @@ -1031,6 +1064,137 @@ void CoreTest::testAscii() } +void CoreTest::testSmallObjectAllocator() +{ + { + SmallObjectAllocator soa1; + assert (!soa1.isOnHeap()); + int& i = soa1.get(); + i = 42; + int j = i; + assert (j == 42); + int* pi = &i; + assert (*pi == 42); + *pi = 24; + assert (i == 24); + SmallObjectAllocator soa2(soa1); + assert (soa1.get() == soa2.get()); + assert (soa2.get() == 24); + + SmallObjectAllocator soa3; + soa3 = soa2; + assert (soa3.get() == soa2.get()); + assert (soa3.get() == 24); + } + { + // force heap alloc + SmallObjectAllocator soa1; + assert (soa1.isOnHeap()); + int& i = soa1.get(); + i = 42; + int j = i; + assert (j == 42); + int* pi = &i; + assert (*pi == 42); + *pi = 24; + assert (i == 24); + SmallObjectAllocator soa2(soa1); + assert (soa1.get() == soa2.get()); + assert (soa2.get() == 24); + + SmallObjectAllocator soa3; + soa3 = soa2; + assert (soa3.get() == soa2.get()); + assert (soa3.get() == 24); + } + + SmallObjectAllocator soa2; + assert (!soa2.isOnHeap()); + + { + assert (Parent::i == 0); + SmallObjectAllocator soa3; + assert (!soa3.isOnHeap()); + assert (Parent::i == -1); + } + assert (Parent::i == -2); + + { + typedef SmallObjectAllocator LargeType; + LargeType soa4; + assert (soa4.isOnHeap()); + Large large = soa4.get(); + assert (large.i == 1); + assert (large.j == 2); + assert (large.k == 3); + + const LargeType soa5; + assert (soa5.get().l == 4); + } + + Parent::i = 0; // only to make sure subsequent runs don't fail + + SmallObjectAllocator soa6(2); + assert (!soa6.isOnHeap()); + char* pC2 = soa6.get(); + pC2[0] = 'x'; + pC2[1] = '\0'; + std::string str2(pC2); + assert (str2 == "x"); + + std::size_t sz = POCO_SMALL_OBJECT_SIZE + 1; + Poco::SmallStringAllocator soa7(sz); + assert (soa7.isOnHeap()); + char* pC = soa7.get(); + char c = '0'; + int i = 0; + + // test this only for default values + if (POCO_SMALL_OBJECT_SIZE == 15) + { + for (i = 0; i < sz - 1; ++i) + pC[i] = c++; + pC[i] = '\0'; + std::string str(pC); + assert (str == "0123456789:;<=>"); + + Poco::SmallStringAllocator soa7("0123456789:;<=>"); + assert (str == soa7.get()); + + soa7 = ""; + assert (soa7.get()[0] == '\0'); + soa7 = "0123456789:;<=>"; + assert (str == soa7.get()); + } + else if (POCO_SMALL_OBJECT_SIZE == 7) + { + for (i = 0; i < sz - 1; ++i) + pC[i] = c++; + pC[i] = '\0'; + std::string str(pC); + assert (str == "0123456"); + + Poco::SmallStringAllocator soa7("0123456"); + assert (str == soa7.get()); + + soa7 = ""; + assert (soa7.get()[0] == '\0'); + soa7 = "0123456"; + assert (str == soa7.get()); + } + + std::string str("0123456789"); + Poco::SmallObjectAllocator soa8(str); + assert (!soa8.isOnHeap()); + assert(soa8.get() == str); + + Poco::SmallObjectAllocator soa9; + assert (soa9.isOnHeap()); + soa9 = str; + assert(soa9.get() == str); +} + + void CoreTest::onReadable(bool& b) { if (b) ++_notToReadable; @@ -1074,6 +1238,7 @@ CppUnit::Test* CoreTest::suite() CppUnit_addTest(pSuite, CoreTest, testAtomicCounter); CppUnit_addTest(pSuite, CoreTest, testNullable); CppUnit_addTest(pSuite, CoreTest, testAscii); + CppUnit_addTest(pSuite, CoreTest, testSmallObjectAllocator); return pSuite; } diff --git a/Foundation/testsuite/src/CoreTest.h b/Foundation/testsuite/src/CoreTest.h index a521fce91..4d4eed110 100644 --- a/Foundation/testsuite/src/CoreTest.h +++ b/Foundation/testsuite/src/CoreTest.h @@ -58,6 +58,7 @@ public: void testAtomicCounter(); void testNullable(); void testAscii(); + void testSmallObjectAllocator(); void setUp(); void tearDown(); diff --git a/Net/Net_CE_vs90.vcproj b/Net/Net_CE_vs90.vcproj index e052a621f..47a58b2ec 100644 --- a/Net/Net_CE_vs90.vcproj +++ b/Net/Net_CE_vs90.vcproj @@ -438,6 +438,8 @@ RelativePath=".\include\Poco\Net\HostEntry.h"/> + + + @@ -375,6 +376,7 @@ + diff --git a/Net/Net_vs110.vcxproj.filters b/Net/Net_vs110.vcxproj.filters index 2a92c74b7..7bca18a6b 100644 --- a/Net/Net_vs110.vcxproj.filters +++ b/Net/Net_vs110.vcxproj.filters @@ -138,6 +138,9 @@ NetCore\Header Files + + NetCore\Header Files + NetCore\Header Files @@ -431,6 +434,9 @@ NetCore\Source Files + + NetCore\Source Files + NetCore\Source Files diff --git a/Net/Net_vs71.vcproj b/Net/Net_vs71.vcproj index bcd35cd99..440c65da4 100644 --- a/Net/Net_vs71.vcproj +++ b/Net/Net_vs71.vcproj @@ -370,6 +370,8 @@ RelativePath=".\include\Poco\Net\HostEntry.h"/> + + + + + + + @@ -32,76 +32,76 @@ Net Win32Proj - - + + StaticLibrary MultiByte - + StaticLibrary MultiByte - + StaticLibrary MultiByte - + StaticLibrary MultiByte - + DynamicLibrary MultiByte - + DynamicLibrary MultiByte - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + <_ProjectFileVersion>10.0.40219.1 - ..\bin64\ - obj64\$(Configuration)\ - true - ..\bin64\ - obj64\$(Configuration)\ - false - ..\lib64\ - obj64\$(Configuration)\ - ..\lib64\ - obj64\$(Configuration)\ - ..\lib64\ - obj64\$(Configuration)\ - ..\lib64\ - obj64\$(Configuration)\ - PocoNet64d - PocoNetmdd - PocoNetmtd - PocoNet64 - PocoNetmd - PocoNetmt + ..\bin64\ + obj64\$(Configuration)\ + true + ..\bin64\ + obj64\$(Configuration)\ + false + ..\lib64\ + obj64\$(Configuration)\ + ..\lib64\ + obj64\$(Configuration)\ + ..\lib64\ + obj64\$(Configuration)\ + ..\lib64\ + obj64\$(Configuration)\ + PocoNet64d + PocoNetmdd + PocoNetmtd + PocoNet64 + PocoNetmd + PocoNetmt - + Disabled .\include;..\Foundation\include;%(AdditionalIncludeDirectories) @@ -114,7 +114,7 @@ true true true - + Level3 ProgramDatabase Default @@ -132,7 +132,7 @@ MachineX64 - + Disabled OnlyExplicitInline @@ -147,9 +147,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -166,7 +166,7 @@ MachineX64 - + Disabled .\include;..\Foundation\include;%(AdditionalIncludeDirectories) @@ -179,7 +179,7 @@ true true true - + ..\lib64\PocoNetmtd.pdb Level3 ProgramDatabase @@ -190,7 +190,7 @@ ..\lib64\PocoNetmtd.lib - + Disabled OnlyExplicitInline @@ -205,9 +205,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -215,7 +215,7 @@ ..\lib64\PocoNetmt.lib - + Disabled .\include;..\Foundation\include;%(AdditionalIncludeDirectories) @@ -228,7 +228,7 @@ true true true - + ..\lib64\PocoNetmdd.pdb Level3 ProgramDatabase @@ -239,7 +239,7 @@ ..\lib64\PocoNetmdd.lib - + Disabled OnlyExplicitInline @@ -254,9 +254,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -265,207 +265,209 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - true - true - true - true - true - true + true + true + true + true + true + true - - - + + + \ No newline at end of file diff --git a/Net/Net_x64_vs100.vcxproj.filters b/Net/Net_x64_vs100.vcxproj.filters index cc5d83829..392d423af 100644 --- a/Net/Net_x64_vs100.vcxproj.filters +++ b/Net/Net_x64_vs100.vcxproj.filters @@ -420,6 +420,9 @@ WebSocket\Header Files + + NetCore\Header Files + @@ -695,6 +698,9 @@ WebSocket\Source Files + + NetCore\Source Files + diff --git a/Net/Net_x64_vs110.vcxproj b/Net/Net_x64_vs110.vcxproj index 9d16c8861..810f6dfc9 100644 --- a/Net/Net_x64_vs110.vcxproj +++ b/Net/Net_x64_vs110.vcxproj @@ -274,6 +274,7 @@ + @@ -373,6 +374,7 @@ + diff --git a/Net/Net_x64_vs110.vcxproj.filters b/Net/Net_x64_vs110.vcxproj.filters index 5ed32e62e..18dd8f2dd 100644 --- a/Net/Net_x64_vs110.vcxproj.filters +++ b/Net/Net_x64_vs110.vcxproj.filters @@ -138,6 +138,9 @@ NetCore\Header Files + + NetCore\Header Files + NetCore\Header Files @@ -431,6 +434,9 @@ NetCore\Source Files + + NetCore\Source Files + NetCore\Source Files diff --git a/Net/Net_x64_vs90.vcproj b/Net/Net_x64_vs90.vcproj index 153ea2f46..d087f6a66 100644 --- a/Net/Net_x64_vs90.vcproj +++ b/Net/Net_x64_vs90.vcproj @@ -395,6 +395,8 @@ RelativePath=".\include\Poco\Net\HostEntry.h"/> + + sendBytes(&fifoBuf.buffer()[0], fifoBuf.used()); + int ret = impl()->sendBytes(&fifoBuf.buffer()[0], (int) fifoBuf.used()); if (ret > 0) fifoBuf.drain(ret); return ret; } @@ -150,7 +150,7 @@ int StreamSocket::receiveBytes(void* buffer, int length, int flags) int StreamSocket::receiveBytes(FIFOBuffer& fifoBuf) { - int ret = impl()->receiveBytes(fifoBuf.next(), fifoBuf.available()); + int ret = impl()->receiveBytes(fifoBuf.next(), (int) fifoBuf.available()); if (ret > 0) fifoBuf.advance(ret); return ret; } diff --git a/Net/testsuite/src/WebSocketTest.cpp b/Net/testsuite/src/WebSocketTest.cpp index 568dbfa5b..2daf0ce26 100644 --- a/Net/testsuite/src/WebSocketTest.cpp +++ b/Net/testsuite/src/WebSocketTest.cpp @@ -129,7 +129,7 @@ void WebSocketTest::testWebSocket() WebSocket ws(cs, request, response); std::string payload("x"); - ws.sendFrame(payload.data(), payload.size()); + ws.sendFrame(payload.data(), (int) payload.size()); char buffer[1024]; int flags; int n = ws.receiveFrame(buffer, sizeof(buffer), flags); @@ -140,7 +140,7 @@ void WebSocketTest::testWebSocket() for (int i = 2; i < 20; i++) { payload.assign(i, 'x'); - ws.sendFrame(payload.data(), payload.size()); + ws.sendFrame(payload.data(), (int) payload.size()); n = ws.receiveFrame(buffer, sizeof(buffer), flags); assert (n == payload.size()); assert (payload.compare(0, payload.size(), buffer, 0, n) == 0); @@ -150,7 +150,7 @@ void WebSocketTest::testWebSocket() for (int i = 125; i < 129; i++) { payload.assign(i, 'x'); - ws.sendFrame(payload.data(), payload.size()); + ws.sendFrame(payload.data(), (int) payload.size()); n = ws.receiveFrame(buffer, sizeof(buffer), flags); assert (n == payload.size()); assert (payload.compare(0, payload.size(), buffer, 0, n) == 0); @@ -158,14 +158,14 @@ void WebSocketTest::testWebSocket() } payload = "Hello, world!"; - ws.sendFrame(payload.data(), payload.size()); + ws.sendFrame(payload.data(), (int) payload.size()); n = ws.receiveFrame(buffer, sizeof(buffer), flags); assert (n == payload.size()); assert (payload.compare(0, payload.size(), buffer, 0, n) == 0); assert (flags == WebSocket::FRAME_TEXT); payload = "Hello, universe!"; - ws.sendFrame(payload.data(), payload.size(), WebSocket::FRAME_BINARY); + ws.sendFrame(payload.data(), (int) payload.size(), WebSocket::FRAME_BINARY); n = ws.receiveFrame(buffer, sizeof(buffer), flags); assert (n == payload.size()); assert (payload.compare(0, payload.size(), buffer, 0, n) == 0); diff --git a/Util/Util_vs100.vcxproj b/Util/Util_vs100.vcxproj index 5319633ff..094a48e2c 100644 --- a/Util/Util_vs100.vcxproj +++ b/Util/Util_vs100.vcxproj @@ -1,4 +1,4 @@ - + @@ -32,76 +32,76 @@ Util Win32Proj - - + + StaticLibrary MultiByte - + StaticLibrary MultiByte - + StaticLibrary MultiByte - + StaticLibrary MultiByte - + DynamicLibrary MultiByte - + DynamicLibrary MultiByte - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + <_ProjectFileVersion>10.0.40219.1 - ..\bin\ - obj\$(Configuration)\ - true - ..\bin\ - obj\$(Configuration)\ - false - ..\lib\ - obj\$(Configuration)\ - ..\lib\ - obj\$(Configuration)\ - ..\lib\ - obj\$(Configuration)\ - ..\lib\ - obj\$(Configuration)\ - PocoUtild - PocoUtilmdd - PocoUtilmtd - PocoUtil - PocoUtilmd - PocoUtilmt + ..\bin\ + obj\$(Configuration)\ + true + ..\bin\ + obj\$(Configuration)\ + false + ..\lib\ + obj\$(Configuration)\ + ..\lib\ + obj\$(Configuration)\ + ..\lib\ + obj\$(Configuration)\ + ..\lib\ + obj\$(Configuration)\ + PocoUtild + PocoUtilmdd + PocoUtilmtd + PocoUtil + PocoUtilmd + PocoUtilmt - + Disabled .\include;..\Foundation\include;..\XML\include;..\JSON\include;%(AdditionalIncludeDirectories) @@ -114,7 +114,7 @@ true true true - + Level3 EditAndContinue Default @@ -132,7 +132,7 @@ MachineX86 - + Disabled OnlyExplicitInline @@ -147,9 +147,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -166,7 +166,7 @@ MachineX86 - + Disabled .\include;..\Foundation\include;..\XML\include;..\JSON\include;%(AdditionalIncludeDirectories) @@ -179,7 +179,7 @@ true true true - + ..\lib\PocoUtilmtd.pdb Level3 EditAndContinue @@ -190,7 +190,7 @@ ..\lib\PocoUtilmtd.lib - + Disabled OnlyExplicitInline @@ -205,9 +205,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -215,7 +215,7 @@ ..\lib\PocoUtilmt.lib - + Disabled .\include;..\Foundation\include;..\XML\include;..\JSON\include;%(AdditionalIncludeDirectories) @@ -228,7 +228,7 @@ true true true - + ..\lib\PocoUtilmdd.pdb Level3 EditAndContinue @@ -239,7 +239,7 @@ ..\lib\PocoUtilmdd.lib - + Disabled OnlyExplicitInline @@ -254,10 +254,10 @@ true true true - + ..\lib\PocoUtilmd.pdb Level3 - + Default %(DisableSpecificWarnings) @@ -267,79 +267,80 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - true - true - true - true + true + true + true + true - - - + + + \ No newline at end of file diff --git a/Util/Util_vs100.vcxproj.filters b/Util/Util_vs100.vcxproj.filters index f6724f69b..7d6736c6c 100644 --- a/Util/Util_vs100.vcxproj.filters +++ b/Util/Util_vs100.vcxproj.filters @@ -153,6 +153,9 @@ Timer\Header Files + + Util\Header Files + From ba9d8574d3017a1a88496bc0469083ee9945fcf6 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 2 Feb 2013 15:10:20 -0600 Subject: [PATCH 05/25] few more fixes and refactoring --- Foundation/include/Poco/Any.h | 73 ++++++++++++++++++++--------------- Net/samples/Ping/src/Ping.cpp | 16 ++++---- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index eb8c14555..31c13f005 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -87,7 +87,7 @@ public: { if(!empty()) { - if(flag()) + if(isLocal()) content()->~Placeholder(); else delete content(); @@ -102,7 +102,7 @@ public: /// Any a = 13; /// Any a = string("12345"); { - this->~Any(); + if (isLocal()) this->~Any(); construct(value); return *this; } @@ -110,7 +110,7 @@ public: Any& operator = (Any value) /// Assignment operator for Any. { - this->~Any(); + if (isLocal()) this->~Any(); construct(value); return *this; } @@ -118,8 +118,8 @@ public: bool empty() const /// Returns true if the Any is empty. { - //return !(flags() & ASSIGNED); - return _placeholder.pHolder == 0; + char buf[POCO_SMALL_OBJECT_SIZE] = { 0 }; + return 0 == std::memcmp(_placeholder.holder, buf, POCO_SMALL_OBJECT_SIZE); } const std::type_info & type() const @@ -140,9 +140,9 @@ private: virtual ~Placeholder() { } - + virtual const std::type_info & type() const = 0; - virtual Placeholder * clone(Placeholder* pMem = 0) const = 0; + virtual void clone(Placeholder**) const = 0; }; template @@ -152,17 +152,29 @@ private: Holder(const ValueType & value) : _held(value) { } - + virtual const std::type_info & type() const { return typeid(ValueType); } - - virtual Placeholder * clone(Placeholder* pMem = 0) const + + static void setFlag(Placeholder** pMem, unsigned char val) { - return pMem && (sizeof(_held) <= POCO_SMALL_OBJECT_SIZE) ? - new (pMem) Holder(_held) : - new Holder(_held); + reinterpret_cast(pMem)[POCO_SMALL_OBJECT_SIZE] = val; + } + + virtual void clone(Placeholder** ppMem) const + { + if ((sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE)) + { + new (ppMem) Holder(_held); + setFlag(ppMem, 1); + } + else + { + *ppMem = new Holder(_held); + setFlag(ppMem, 0); + } } ValueType _held; @@ -173,10 +185,8 @@ private: Placeholder* content() const { - if (empty()) return 0; - - if(flag()) - return (Placeholder *) &(_placeholder.holder); + if(isLocal()) + return reinterpret_cast(&(_placeholder.holder)); else return _placeholder.pHolder; } @@ -187,27 +197,26 @@ private: if (sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE) { new (_placeholder.holder) Holder(value); - flag() = 1; + isLocal() = 1; } else { _placeholder.pHolder = new Holder(value); - flag() = 0; + isLocal() = 0; } } - + void construct(const Any & other) { - if(other.flag()) - { - other.content()->clone((Placeholder*) &_placeholder.holder); - flag() = 1; - return; - } - else if(!(other.empty())) - _placeholder.pHolder = other._placeholder.pHolder->clone(); - - flag() = 0; + if(other.empty()) + erase(_placeholder.holder); + else + other.content()->clone(&_placeholder.pHolder); + } + + inline static void erase(unsigned char* pHolder, std::size_t sz= POCO_SMALL_OBJECT_SIZE + 1) + { + std::memset(pHolder, 0, sz); } union PH @@ -219,14 +228,14 @@ private: { PH () { - std::memset(holder, 0, sizeof(PH)); + erase(holder); } Placeholder* pHolder; mutable unsigned char holder[POCO_SMALL_OBJECT_SIZE + 1]; } _placeholder; - unsigned char& flag() const + unsigned char& isLocal() const { return _placeholder.holder[POCO_SMALL_OBJECT_SIZE]; } diff --git a/Net/samples/Ping/src/Ping.cpp b/Net/samples/Ping/src/Ping.cpp index 185fb76d0..56b3e0f09 100644 --- a/Net/samples/Ping/src/Ping.cpp +++ b/Net/samples/Ping/src/Ping.cpp @@ -84,18 +84,18 @@ protected: loadConfiguration(); // load default configuration files, if present Application::initialize(self); - _icmpClient.pingBegin += Delegate(this, &Ping::onBegin); - _icmpClient.pingReply += Delegate(this, &Ping::onReply); - _icmpClient.pingError += Delegate(this, &Ping::onError); - _icmpClient.pingEnd += Delegate(this, &Ping::onEnd); + _icmpClient.pingBegin += delegate(this, &Ping::onBegin); + _icmpClient.pingReply += delegate(this, &Ping::onReply); + _icmpClient.pingError += delegate(this, &Ping::onError); + _icmpClient.pingEnd += delegate(this, &Ping::onEnd); } void uninitialize() { - _icmpClient.pingBegin -= Delegate(this, &Ping::onBegin); - _icmpClient.pingReply -= Delegate(this, &Ping::onReply); - _icmpClient.pingError -= Delegate(this, &Ping::onError); - _icmpClient.pingEnd -= Delegate(this, &Ping::onEnd); + _icmpClient.pingBegin -= delegate(this, &Ping::onBegin); + _icmpClient.pingReply -= delegate(this, &Ping::onReply); + _icmpClient.pingError -= delegate(this, &Ping::onError); + _icmpClient.pingEnd -= delegate(this, &Ping::onEnd); Application::uninitialize(); } From 1821716d29d682c8f69f997c9b0a64accd5dd724 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 2 Feb 2013 20:37:39 -0600 Subject: [PATCH 06/25] more tests and other changes - ported complete suite of boost::any tests - improved reference casting - added swap in SOO version --- Foundation/include/Poco/Any.h | 49 ++++++-- Foundation/testsuite/src/AnyTest.cpp | 164 +++++++++++++++++++++++++++ Foundation/testsuite/src/AnyTest.h | 10 ++ 3 files changed, 211 insertions(+), 12 deletions(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index 31c13f005..9243dcb97 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -39,6 +39,7 @@ #include "Poco/Exception.h" +#include "Poco/MetaProgramming.h" #include #include @@ -84,6 +85,8 @@ public: } ~Any() + /// Destructor. If Any is locally held, calls Placeholder destructor; + /// otherwise, deletes the placeholder from the heap. { if(!empty()) { @@ -94,24 +97,44 @@ public: } } + Any& swap(Any& other) + /// Swaps the content of the two Anys. + /// + /// When small object optimizaton (SOO) is enabled, + /// swap is only exception-safe when both (*this and + /// other) objects are allocated on the heap. + { + if (!isLocal() && !other.isLocal()) + { + std::swap(_placeholder.pHolder, other._placeholder.pHolder); + } + else + { + Any tmp(*this); + if (isLocal()) this->~Any(); + construct(other); + other = tmp; + } + + return *this; + } + template - Any & operator=(const ValueType& value) + Any & operator = (const ValueType& rhs) /// Assignment operator for all types != Any. /// /// Example: /// Any a = 13; /// Any a = string("12345"); { - if (isLocal()) this->~Any(); - construct(value); + Any(rhs).swap(*this); return *this; } - Any& operator = (Any value) + Any& operator = (Any rhs) /// Assignment operator for Any. { - if (isLocal()) this->~Any(); - construct(value); + Any(rhs).swap(*this); return *this; } @@ -192,7 +215,7 @@ private: } template - void construct(const ValueType & value) + void construct(const ValueType& value) { if (sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE) { @@ -206,7 +229,7 @@ private: } } - void construct(const Any & other) + void construct(const Any& other) { if(other.empty()) erase(_placeholder.holder); @@ -408,9 +431,9 @@ ValueType AnyCast(const Any& operand) /// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in /// these cases. { - ValueType* result = AnyCast(const_cast(&operand)); - if (!result) throw BadCastException("Failed to convert between const Any types"); - return *result; + typedef TypeWrapper::TYPE NonRef; + + return AnyCast(const_cast(operand)); } @@ -425,7 +448,9 @@ ValueType AnyCast(Any& operand) /// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in /// these cases. { - ValueType* result = AnyCast(&operand); + typedef TypeWrapper::TYPE NonRef; + + NonRef* result = AnyCast(&operand); if (!result) throw BadCastException("Failed to convert between Any types"); return *result; } diff --git a/Foundation/testsuite/src/AnyTest.cpp b/Foundation/testsuite/src/AnyTest.cpp index 3fee242d9..0c456e9d3 100644 --- a/Foundation/testsuite/src/AnyTest.cpp +++ b/Foundation/testsuite/src/AnyTest.cpp @@ -70,6 +70,156 @@ AnyTest::~AnyTest() } +void AnyTest::testDefaultCtor() +{ + const Any value; + + assert (value.empty()); + assert (0 == AnyCast(&value)); + assert (value.type() == typeid(void)); +} + + +void AnyTest::testConvertingCtor() +{ + std::string text = "test message"; + Any value = text; + + assert (!value.empty()); + assert (value.type() == typeid(std::string)); + assert (0 == AnyCast(&value)); + assert (0 != AnyCast(&value)); + assert (AnyCast(value) == text); + assert (AnyCast(&value) != &text); +} + + +void AnyTest::testCopyCtor() +{ + std::string text = "test message"; + Any original = text, copy = original; + + assert (!copy.empty()); + assert (original.type() == copy.type()); + assert (AnyCast(original) == AnyCast(copy)); + assert (text == AnyCast(copy)); + assert(AnyCast(&original) != AnyCast(©)); +} + + +void AnyTest::testCopyAssign() +{ + std::string text = "test message"; + Any original = text, copy; + Any* assignResult = &(copy = original); + + assert(!copy.empty()); + assert(original.type() == copy.type()); + assert(AnyCast(original) == AnyCast(copy)); + assert(text == AnyCast(copy)); + assert(AnyCast(&original) != AnyCast(©)); + assert(assignResult == ©); +} + + +void AnyTest::testConvertingAssign() +{ + std::string text = "test message"; + Any value; + Any* assignResult = &(value = text); + + assert (!value.empty()); + assert(value.type() == typeid(std::string)); + assert(0 == AnyCast(&value)); + assert(0 != AnyCast(&value)); + assert(AnyCast(value) == text); + assert(AnyCast(&value) != &text); + assert(assignResult == &value); +} + + +void AnyTest::testCastToReference() +{ + Any a(137); + const Any b(a); + + int& ra = AnyCast(a); + int const& ra_c = AnyCast(a); + int volatile& ra_v = AnyCast(a); + int const volatile& ra_cv = AnyCast(a); + + // cv references to same obj + assert (&ra == &ra_c && &ra == &ra_v && &ra == &ra_cv); + + int const & rb_c = AnyCast(b); + int const volatile & rb_cv = AnyCast(b); + + assert (&rb_c == &rb_cv); // cv references to copied const obj + assert (&ra != &rb_c); // copies hold different objects + + ++ra; + int incremented = AnyCast(a); + assert (incremented == 138); // increment by reference changes value + + try + { + AnyCast(a); + failmsg ("AnyCast to incorrect reference type"); + } + catch (BadCastException&) { } + + try + { + AnyCast(b), + failmsg ("AnyCast to incorrect const reference type"); + } + catch (BadCastException&) { } +} + + +void AnyTest::testBadCast() +{ + std::string text = "test message"; + Any value = text; + + try + { + AnyCast(value); + fail ("must throw"); + } + catch (BadCastException&) { } +} + + +void AnyTest::testSwap() +{ + std::string text = "test message"; + Any original = text, swapped; + std::string* originalPtr = AnyCast(&original); + Any* swapResult = &original.swap(swapped); + + assert (original.empty()); + assert (!swapped.empty()); + assert (swapped.type() == typeid(std::string)); + assert (text == AnyCast(swapped)); + assert (0 != originalPtr); + assert (originalPtr == AnyCast(&swapped)); + assert (swapResult == &original); +} + + +void AnyTest::testEmptyCopy() +{ + const Any null; + Any copied = null, assigned; + assigned = null; + + assert (null.empty()); + assert (copied.empty()); + assert (assigned.empty()); +} + + void AnyTest::testInt() { Any e; @@ -119,8 +269,13 @@ void AnyTest::testVector() Any a = tmp; assert (a.type() == typeid(std::vector)); std::vector tmp2 = AnyCast >(a); + assert (tmp2.size() == 3); const std::vector& vecCRef = RefAnyCast >(a); std::vector& vecRef = RefAnyCast >(a); + + assert (vecRef[0] == 1); + assert (vecRef[1] == 2); + assert (vecRef[2] == 3); vecRef[0] = 0; assert (vecRef[0] == vecCRef[0]); } @@ -140,6 +295,15 @@ CppUnit::Test* AnyTest::suite() { CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("AnyTest"); + CppUnit_addTest(pSuite, AnyTest, testConvertingCtor); + CppUnit_addTest(pSuite, AnyTest, testDefaultCtor); + CppUnit_addTest(pSuite, AnyTest, testCopyCtor); + CppUnit_addTest(pSuite, AnyTest, testCopyAssign); + CppUnit_addTest(pSuite, AnyTest, testConvertingAssign); + CppUnit_addTest(pSuite, AnyTest, testBadCast); + CppUnit_addTest(pSuite, AnyTest, testSwap); + CppUnit_addTest(pSuite, AnyTest, testEmptyCopy); + CppUnit_addTest(pSuite, AnyTest, testCastToReference); CppUnit_addTest(pSuite, AnyTest, testInt); CppUnit_addTest(pSuite, AnyTest, testComplexType); CppUnit_addTest(pSuite, AnyTest, testVector); diff --git a/Foundation/testsuite/src/AnyTest.h b/Foundation/testsuite/src/AnyTest.h index 0a1302836..246cb8124 100644 --- a/Foundation/testsuite/src/AnyTest.h +++ b/Foundation/testsuite/src/AnyTest.h @@ -45,6 +45,16 @@ public: AnyTest(const std::string& name); ~AnyTest(); + void testConvertingCtor(); + void testDefaultCtor(); + void testCopyCtor(); + void testCopyAssign(); + void testConvertingAssign(); + void testBadCast(); + void testSwap(); + void testEmptyCopy(); + void testCastToReference(); + void testInt(); void testComplexType(); void testVector(); From 0c7e345d8917749468a09ba7d0c758aa68c77a2c Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 3 Feb 2013 07:16:06 -0600 Subject: [PATCH 07/25] clang mac compile --- Foundation/include/Poco/Any.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index 9243dcb97..33b79b5df 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -431,7 +431,7 @@ ValueType AnyCast(const Any& operand) /// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in /// these cases. { - typedef TypeWrapper::TYPE NonRef; + typedef typename TypeWrapper::TYPE NonRef; return AnyCast(const_cast(operand)); } @@ -448,7 +448,7 @@ ValueType AnyCast(Any& operand) /// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in /// these cases. { - typedef TypeWrapper::TYPE NonRef; + typedef typename TypeWrapper::TYPE NonRef; NonRef* result = AnyCast(&operand); if (!result) throw BadCastException("Failed to convert between Any types"); @@ -490,7 +490,7 @@ ValueType* UnsafeAnyCast(Any* operand) /// use typeid() comparison, e.g., when our types may travel across /// different shared libraries. { - return &static_cast*>(operand->_pHolder)->_held; + return &static_cast*>(operand->content())->_held; } From ddfa52eefad1a0bf0387a73342b4a99218c641eb Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sun, 3 Feb 2013 12:03:01 -0600 Subject: [PATCH 08/25] some refactoring --- Foundation/include/Poco/Any.h | 92 ++++++++++++++++------------ Foundation/testsuite/src/AnyTest.cpp | 35 +++++++---- 2 files changed, 75 insertions(+), 52 deletions(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index 33b79b5df..9f938a603 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -60,6 +60,8 @@ class Any #ifndef POCO_NO_SOO + union PH; + public: Any() @@ -81,7 +83,8 @@ public: Any(const Any& other) /// Copy constructor, works with both empty and initialized Any values. { - construct(other); + if ((this != &other) && !other.empty()) + construct(other); } ~Any() @@ -90,7 +93,7 @@ public: { if(!empty()) { - if(isLocal()) + if(_placeholder.isLocal()) content()->~Placeholder(); else delete content(); @@ -100,18 +103,20 @@ public: Any& swap(Any& other) /// Swaps the content of the two Anys. /// - /// When small object optimizaton (SOO) is enabled, + /// When small object optimizaton is enabled, /// swap is only exception-safe when both (*this and /// other) objects are allocated on the heap. { - if (!isLocal() && !other.isLocal()) + if (this == &other) return *this; + + if (!_placeholder.isLocal() && !other._placeholder.isLocal()) { std::swap(_placeholder.pHolder, other._placeholder.pHolder); } else { Any tmp(*this); - if (isLocal()) this->~Any(); + if (_placeholder.isLocal()) this->~Any(); construct(other); other = tmp; } @@ -127,14 +132,18 @@ public: /// Any a = 13; /// Any a = string("12345"); { - Any(rhs).swap(*this); + construct(rhs); return *this; } - Any& operator = (Any rhs) + Any& operator = (const Any& rhs) /// Assignment operator for Any. { - Any(rhs).swap(*this); + if ((this != &rhs) && !rhs.empty()) + construct(rhs); + else if ((this != &rhs) && rhs.empty()) + _placeholder.erase(); + return *this; } @@ -165,7 +174,7 @@ private: } virtual const std::type_info & type() const = 0; - virtual void clone(Placeholder**) const = 0; + virtual void clone(Any::PH*) const = 0; }; template @@ -181,22 +190,17 @@ private: return typeid(ValueType); } - static void setFlag(Placeholder** pMem, unsigned char val) - { - reinterpret_cast(pMem)[POCO_SMALL_OBJECT_SIZE] = val; - } - - virtual void clone(Placeholder** ppMem) const + virtual void clone(Any::PH* pPlaceholder) const { if ((sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE)) { - new (ppMem) Holder(_held); - setFlag(ppMem, 1); + new ((Placeholder*) pPlaceholder->holder) Holder(_held); + pPlaceholder->setLocal(true); } else { - *ppMem = new Holder(_held); - setFlag(ppMem, 0); + pPlaceholder->pHolder = new Holder(_held); + pPlaceholder->setLocal(false); } } @@ -208,10 +212,7 @@ private: Placeholder* content() const { - if(isLocal()) - return reinterpret_cast(&(_placeholder.holder)); - else - return _placeholder.pHolder; + return _placeholder.content(); } template @@ -220,26 +221,21 @@ private: if (sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE) { new (_placeholder.holder) Holder(value); - isLocal() = 1; + _placeholder.setLocal(true); } else { _placeholder.pHolder = new Holder(value); - isLocal() = 0; + _placeholder.setLocal(false); } } void construct(const Any& other) { - if(other.empty()) - erase(_placeholder.holder); + if(!other.empty()) + other.content()->clone(&_placeholder); else - other.content()->clone(&_placeholder.pHolder); - } - - inline static void erase(unsigned char* pHolder, std::size_t sz= POCO_SMALL_OBJECT_SIZE + 1) - { - std::memset(pHolder, 0, sz); + _placeholder.erase(); } union PH @@ -251,18 +247,36 @@ private: { PH () { - erase(holder); + erase(); + } + + void erase() + { + std::memset(holder, 0, sizeof(PH)); + } + + bool isLocal() const + { + return holder[POCO_SMALL_OBJECT_SIZE] != 0; + } + + void setLocal(bool local) const + { + holder[POCO_SMALL_OBJECT_SIZE] = local ? 1 : 0; + } + + Placeholder* content() const + { + if(isLocal()) + return reinterpret_cast(&holder[0]); + else + return pHolder; } Placeholder* pHolder; mutable unsigned char holder[POCO_SMALL_OBJECT_SIZE + 1]; } _placeholder; - unsigned char& isLocal() const - { - return _placeholder.holder[POCO_SMALL_OBJECT_SIZE]; - } - #else // if POCO_NO_SOO diff --git a/Foundation/testsuite/src/AnyTest.cpp b/Foundation/testsuite/src/AnyTest.cpp index 0c456e9d3..f75897b2b 100644 --- a/Foundation/testsuite/src/AnyTest.cpp +++ b/Foundation/testsuite/src/AnyTest.cpp @@ -103,7 +103,7 @@ void AnyTest::testCopyCtor() assert (original.type() == copy.type()); assert (AnyCast(original) == AnyCast(copy)); assert (text == AnyCast(copy)); - assert(AnyCast(&original) != AnyCast(©)); + assert (AnyCast(&original) != AnyCast(©)); } @@ -113,12 +113,19 @@ void AnyTest::testCopyAssign() Any original = text, copy; Any* assignResult = &(copy = original); - assert(!copy.empty()); - assert(original.type() == copy.type()); - assert(AnyCast(original) == AnyCast(copy)); - assert(text == AnyCast(copy)); - assert(AnyCast(&original) != AnyCast(©)); - assert(assignResult == ©); + assert (!copy.empty()); + assert (original.type() == copy.type()); + assert (AnyCast(original) == AnyCast(copy)); + assert (text == AnyCast(copy)); + assert (AnyCast(&original) != AnyCast(©)); + assert (assignResult == ©); + + // test self assignment + Any& ref = original; + original = ref; + assert (AnyCast(original) == AnyCast(copy)); + original = original; + assert (AnyCast(original) == AnyCast(copy)); } @@ -129,12 +136,12 @@ void AnyTest::testConvertingAssign() Any* assignResult = &(value = text); assert (!value.empty()); - assert(value.type() == typeid(std::string)); - assert(0 == AnyCast(&value)); - assert(0 != AnyCast(&value)); - assert(AnyCast(value) == text); - assert(AnyCast(&value) != &text); - assert(assignResult == &value); + assert (value.type() == typeid(std::string)); + assert (0 == AnyCast(&value)); + assert (0 != AnyCast(&value)); + assert (AnyCast(value) == text); + assert (AnyCast(&value) != &text); + assert (assignResult == &value); } @@ -203,7 +210,9 @@ void AnyTest::testSwap() assert (swapped.type() == typeid(std::string)); assert (text == AnyCast(swapped)); assert (0 != originalPtr); +#ifdef POCO_NO_SOO // pointers only match when heap-allocated assert (originalPtr == AnyCast(&swapped)); +#endif assert (swapResult == &original); } From 1523a87926fb56ea2bc9673c202877c3e0d73370 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 3 Feb 2013 20:19:14 -0600 Subject: [PATCH 09/25] IPAddress Mac clang compile --- Foundation/include/Poco/Config.h | 9 +++++---- Net/Makefile | 2 +- Net/include/Poco/Net/IPAddress.h | 3 +++ Net/src/IPAddress.cpp | 25 +++++++++++++------------ Net/src/IPAddressImpl.cpp | 8 ++++---- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Foundation/include/Poco/Config.h b/Foundation/include/Poco/Config.h index fa69a1952..c64853a00 100644 --- a/Foundation/include/Poco/Config.h +++ b/Foundation/include/Poco/Config.h @@ -86,10 +86,11 @@ // #define POCO_THREAD_PRIORITY_MAX 31 -// Define to disable small object optimization. -// If not defined, Any and Dynamic::Var (and similar -// optimization candidates) will be auto-allocated on the -// stack in cases when value holder fits into . +// Define to disable small object optimization. If not +// defined, Any and Dynamic::Var (and similar optimization +// candidates) will be auto-allocated on the stack in +// cases when value holder fits into POCO_SMALL_OBJECT_SIZE +// (see Poco/Types.h for default values). // #define POCO_NO_SOO // Following are options to remove certain features diff --git a/Net/Makefile b/Net/Makefile index 6d3a041ca..ec808f2f9 100644 --- a/Net/Makefile +++ b/Net/Makefile @@ -12,7 +12,7 @@ SHAREDOPT_CXX += -DNet_EXPORTS objects = \ DNS HTTPResponse HostEntry Socket \ - DatagramSocket HTTPServer IPAddress SocketAddress \ + DatagramSocket HTTPServer IPAddress IPAddressImpl SocketAddress \ HTTPBasicCredentials HTTPCookie HTMLForm MediaType DialogSocket \ DatagramSocketImpl FilePartSource HTTPServerConnection MessageHeader \ HTTPChunkedStream HTTPServerConnectionFactory MulticastSocket SocketStream \ diff --git a/Net/include/Poco/Net/IPAddress.h b/Net/include/Poco/Net/IPAddress.h index 1843354a9..d1f5069cd 100644 --- a/Net/include/Poco/Net/IPAddress.h +++ b/Net/include/Poco/Net/IPAddress.h @@ -392,6 +392,9 @@ private: Ptr pImpl() const; char _memory[sizeof(Poco::Net::Impl::IPv6AddressImpl)]; + + friend class IPv4AddressImpl; + friend class IPv6AddressImpl; }; diff --git a/Net/src/IPAddress.cpp b/Net/src/IPAddress.cpp index 0456f5777..8b7f7940a 100644 --- a/Net/src/IPAddress.cpp +++ b/Net/src/IPAddress.cpp @@ -71,9 +71,9 @@ IPAddress::IPAddress() IPAddress::IPAddress(const IPAddress& addr) { if (addr.family() == IPv4) - std::memcpy(pImpl(), addr.pImpl(), sizeof (IPv4AddressImpl)); + new (_memory) IPv4AddressImpl(addr.addr()); else - std::memcpy(pImpl(), addr.pImpl(), sizeof (IPv6AddressImpl)); + new (_memory) IPv6AddressImpl(addr.addr()); } @@ -95,14 +95,14 @@ IPAddress::IPAddress(const std::string& addr) IPv4AddressImpl empty4 = IPv4AddressImpl(); if (addr.empty() || trim(addr) == "0.0.0.0") { - std::memcpy(pImpl(), &empty4, sizeof(empty4)); + new (_memory) IPv4AddressImpl(empty4.addr()); return; } IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); if (addr4 != empty4) { - std::memcpy(pImpl(), &addr4, sizeof(addr4)); + new (_memory) IPv4AddressImpl(addr4.addr()); return; } @@ -110,14 +110,14 @@ IPAddress::IPAddress(const std::string& addr) IPv6AddressImpl empty6 = IPv6AddressImpl(); if (addr.empty() || trim(addr) == "::") { - std::memcpy(pImpl(), &empty6, sizeof(empty6)); + new (_memory) IPv6AddressImpl(empty6.addr()); return; } IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); if (addr6 != IPv6AddressImpl()) { - std::memcpy(pImpl(), &addr6, sizeof(addr6)); + new (_memory) IPv6AddressImpl(addr6.addr()); return; } #endif @@ -131,14 +131,14 @@ IPAddress::IPAddress(const std::string& addr, Family family) if (family == IPv4) { IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); - std::memcpy(pImpl(), &addr4, sizeof(addr4)); + new (_memory) IPv4AddressImpl(addr4.addr()); return; } #if defined(POCO_HAVE_IPv6) else if (family == IPv6) { IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); - std::memcpy(pImpl(), &addr6, sizeof(addr6)); + new (_memory) IPv6AddressImpl(addr6.addr()); return; } #endif @@ -230,9 +230,9 @@ IPAddress& IPAddress::operator = (const IPAddress& addr) if (&addr != this) { if (addr.family() == IPAddress::IPv4) - std::memcpy(pImpl(), addr.pImpl(), sizeof(IPv4AddressImpl)); + new (_memory) IPv4AddressImpl(addr.addr()); else - std::memcpy(pImpl(), addr.pImpl(), sizeof(IPv6AddressImpl)); + new (_memory) IPv6AddressImpl(addr.addr()); } return *this; } @@ -544,14 +544,15 @@ bool IPAddress::tryParse(const std::string& addr, IPAddress& result) IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr)); if (impl4 != IPv4AddressImpl()) { - std::memcpy(result.pImpl(), &impl4, sizeof(impl4)); + + new (result._memory) IPv4AddressImpl(impl4.addr()); return true; } #if defined(POCO_HAVE_IPv6) IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); if (impl6 != IPv6AddressImpl()) { - std::memcpy(result.pImpl(), &impl6, sizeof(impl6)); + new (result._memory) IPv6AddressImpl(impl6.addr()); return true; } #endif diff --git a/Net/src/IPAddressImpl.cpp b/Net/src/IPAddressImpl.cpp index 2a5b08823..7650278b5 100644 --- a/Net/src/IPAddressImpl.cpp +++ b/Net/src/IPAddressImpl.cpp @@ -641,18 +641,18 @@ IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr) std::string scope(addr, pos + 1, addr.size() - start - pos); Poco::UInt32 scopeId(0); if (!(scopeId = if_nametoindex(scope.c_str()))) - return 0; + return IPv6AddressImpl(); if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1) return IPv6AddressImpl(&ia, scopeId); else - return 0; + return IPv6AddressImpl(); } else { if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) - return new IPv6AddressImpl(&ia); + return IPv6AddressImpl(&ia); else - return 0; + return IPv6AddressImpl(); } #endif } From 54a92c59e55d2d6b49aaac6b4bc76632cf6cf503 Mon Sep 17 00:00:00 2001 From: Alex Fabijanic Date: Sun, 3 Feb 2013 22:39:09 -0600 Subject: [PATCH 10/25] gcc/linux compile --- Foundation/include/Poco/Any.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index 9f938a603..ec89c06e3 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -42,6 +42,7 @@ #include "Poco/MetaProgramming.h" #include #include +#include namespace Poco { @@ -220,7 +221,7 @@ private: { if (sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE) { - new (_placeholder.holder) Holder(value); + new (reinterpret_cast(_placeholder.holder)) Holder(value); _placeholder.setLocal(true); } else @@ -268,7 +269,7 @@ private: Placeholder* content() const { if(isLocal()) - return reinterpret_cast(&holder[0]); + return reinterpret_cast(holder); else return pHolder; } From 21da0129b636f969a239c5c1917fb9552bfdd97c Mon Sep 17 00:00:00 2001 From: aleks-f Date: Tue, 5 Feb 2013 22:12:21 -0600 Subject: [PATCH 11/25] Dynamic::Var SOO Dynamic::Var small object optimization and some refactoring --- .gitignore | 3 + Data/include/Poco/Data/Date.h | 4 +- Data/include/Poco/Data/LOB.h | 8 +- Data/include/Poco/Data/Time.h | 4 +- Foundation/include/Poco/Any.h | 175 ++++++++++-------- Foundation/include/Poco/Config.h | 10 + Foundation/include/Poco/Dynamic/Pair.h | 8 +- Foundation/include/Poco/Dynamic/Struct.h | 8 +- Foundation/include/Poco/Dynamic/Var.h | 160 +++++++++++++--- Foundation/include/Poco/Dynamic/VarHolder.h | 144 ++++++++------ .../include/Poco/SmallObjectAllocator.h | 2 +- Foundation/include/Poco/Types.h | 11 -- Foundation/src/Var.cpp | 51 ++++- JSON/include/Poco/JSON/Array.h | 10 +- JSON/include/Poco/JSON/Object.h | 7 +- Net/include/Poco/Net/IPAddress.h | 4 +- 16 files changed, 401 insertions(+), 208 deletions(-) diff --git a/.gitignore b/.gitignore index 951d94454..cf52c1cab 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,6 @@ lib/ lib64/ pocomsg.h +# Temporary files # +################### +*.bak diff --git a/Data/include/Poco/Data/Date.h b/Data/include/Poco/Data/Date.h index db11d1b2e..876c70555 100644 --- a/Data/include/Poco/Data/Date.h +++ b/Data/include/Poco/Data/Date.h @@ -225,9 +225,9 @@ public: val = DateTimeFormatter::format(dt, "%Y/%m/%d"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Poco::Data::Date& value() const diff --git a/Data/include/Poco/Data/LOB.h b/Data/include/Poco/Data/LOB.h index e2b1f7392..82c1d686e 100644 --- a/Data/include/Poco/Data/LOB.h +++ b/Data/include/Poco/Data/LOB.h @@ -272,9 +272,9 @@ public: val.assign(_val.begin(), _val.end()); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Poco::Data::BLOB& value() const @@ -310,9 +310,9 @@ public: val.assign(_val.begin(), _val.end()); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Poco::Data::CLOB& value() const diff --git a/Data/include/Poco/Data/Time.h b/Data/include/Poco/Data/Time.h index eb9e477f0..758e7cf94 100644 --- a/Data/include/Poco/Data/Time.h +++ b/Data/include/Poco/Data/Time.h @@ -229,9 +229,9 @@ public: val = DateTimeFormatter::format(dt, "%H:%M:%S"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Poco::Data::Time& value() const diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index ec89c06e3..3b030abbd 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -48,6 +48,68 @@ namespace Poco { +namespace Dynamic { + +class Var; +class VarHolder; +template class VarHolderImpl; + +} + + +template +union Placeholder + /// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small + /// object optimization). + /// + /// If Holder fits into POCO_SMALL_OBJECT_SIZE bytes of storage, + /// it will be placement-new-allocated into the local buffer + /// (i.e. there will be no heap-allocation). The local buffer size is one byte + /// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating + /// where the object was allocated (0 => heap, 1 => local). +{ +public: + static const unsigned int SIZE = SizeV; + + Placeholder () + { + erase(); + } + + void erase() + { + std::memset(holder, 0, sizeof(Placeholder)); + } + + bool isLocal() const + { + return holder[SIZE] != 0; + } + + void setLocal(bool local) const + { + holder[SIZE] = local ? 1 : 0; + } + + PlaceholderT* content() const + { + if(isLocal()) + return reinterpret_cast(holder); + else + return pHolder; + } + +private: + PlaceholderT* pHolder; + mutable unsigned char holder[SIZE + 1]; + + friend class Any; + friend class Dynamic::Var; + friend class Dynamic::VarHolder; + template friend class VarHolderImpl; +}; + + class Any /// An Any class represents a general type and is capable of storing any type, supporting type-safe extraction /// of the internally stored data. @@ -58,13 +120,10 @@ class Any /// Modified for small object optimization support (optionally supported through conditional compilation) /// by Alex Fabijanic. { +public: #ifndef POCO_NO_SOO - union PH; - -public: - Any() /// Creates an empty any type. { @@ -75,8 +134,8 @@ public: /// Creates an any which stores the init parameter inside. /// /// Example: - /// Any a(13); - /// Any a(string("12345")); + /// Any a(13); + /// Any a(string("12345")); { construct(value); } @@ -89,13 +148,13 @@ public: } ~Any() - /// Destructor. If Any is locally held, calls Placeholder destructor; + /// Destructor. If Any is locally held, calls ValueHolder destructor; /// otherwise, deletes the placeholder from the heap. { if(!empty()) { - if(_placeholder.isLocal()) - content()->~Placeholder(); + if(_valueHolder.isLocal()) + content()->~ValueHolder(); else delete content(); } @@ -110,14 +169,14 @@ public: { if (this == &other) return *this; - if (!_placeholder.isLocal() && !other._placeholder.isLocal()) + if (!_valueHolder.isLocal() && !other._valueHolder.isLocal()) { - std::swap(_placeholder.pHolder, other._placeholder.pHolder); + std::swap(_valueHolder.pHolder, other._valueHolder.pHolder); } else { Any tmp(*this); - if (_placeholder.isLocal()) this->~Any(); + if (_valueHolder.isLocal()) this->~Any(); construct(other); other = tmp; } @@ -143,7 +202,7 @@ public: if ((this != &rhs) && !rhs.empty()) construct(rhs); else if ((this != &rhs) && rhs.empty()) - _placeholder.erase(); + _valueHolder.erase(); return *this; } @@ -152,7 +211,7 @@ public: /// Returns true if the Any is empty. { char buf[POCO_SMALL_OBJECT_SIZE] = { 0 }; - return 0 == std::memcmp(_placeholder.holder, buf, POCO_SMALL_OBJECT_SIZE); + return 0 == std::memcmp(_valueHolder.holder, buf, _valueHolder.SIZE); } const std::type_info & type() const @@ -166,20 +225,20 @@ public: private: - class Placeholder + class ValueHolder { public: - virtual ~Placeholder() + virtual ~ValueHolder() { } virtual const std::type_info & type() const = 0; - virtual void clone(Any::PH*) const = 0; + virtual void clone(Placeholder*) const = 0; }; template - class Holder : public Placeholder + class Holder : public ValueHolder { public: Holder(const ValueType & value) : _held(value) @@ -191,11 +250,11 @@ private: return typeid(ValueType); } - virtual void clone(Any::PH* pPlaceholder) const + virtual void clone(Placeholder* pPlaceholder) const { - if ((sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE)) + if ((sizeof(Holder) <= pPlaceholder->SIZE)) { - new ((Placeholder*) pPlaceholder->holder) Holder(_held); + new ((ValueHolder*) pPlaceholder->holder) Holder(_held); pPlaceholder->setLocal(true); } else @@ -211,78 +270,40 @@ private: Holder & operator = (const Holder &); }; - Placeholder* content() const + ValueHolder* content() const { - return _placeholder.content(); + return _valueHolder.content(); } template void construct(const ValueType& value) { - if (sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE) + if (sizeof(Holder) <= _valueHolder.SIZE) { - new (reinterpret_cast(_placeholder.holder)) Holder(value); - _placeholder.setLocal(true); + new (reinterpret_cast(_valueHolder.holder)) Holder(value); + _valueHolder.setLocal(true); } else { - _placeholder.pHolder = new Holder(value); - _placeholder.setLocal(false); + _valueHolder.pHolder = new Holder(value); + _valueHolder.setLocal(false); } } void construct(const Any& other) { if(!other.empty()) - other.content()->clone(&_placeholder); + other.content()->clone(&_valueHolder); else - _placeholder.erase(); + _valueHolder.erase(); } - - union PH - /// Placeholder union. If Holder fits into POCO_SMALL_OBJECT_SIZE - /// bytes of storage, it will be placement-new-allocated into the local buffer - /// (i.e. there will be no heap-allocation. The local buffer size is one byte - /// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating - /// where the object was allocated (0 => heap, 1 => local). - { - PH () - { - erase(); - } - - void erase() - { - std::memset(holder, 0, sizeof(PH)); - } - - bool isLocal() const - { - return holder[POCO_SMALL_OBJECT_SIZE] != 0; - } - - void setLocal(bool local) const - { - holder[POCO_SMALL_OBJECT_SIZE] = local ? 1 : 0; - } - - Placeholder* content() const - { - if(isLocal()) - return reinterpret_cast(holder); - else - return pHolder; - } - - Placeholder* pHolder; - mutable unsigned char holder[POCO_SMALL_OBJECT_SIZE + 1]; - } _placeholder; + + Placeholder _valueHolder; #else // if POCO_NO_SOO -public: Any(): _pHolder(0) /// Creates an empty any type. { @@ -352,19 +373,19 @@ public: } private: - class Placeholder + class ValueHolder { public: - virtual ~Placeholder() + virtual ~ValueHolder() { } virtual const std::type_info& type() const = 0; - virtual Placeholder* clone() const = 0; + virtual ValueHolder* clone() const = 0; }; template - class Holder: public Placeholder + class Holder: public ValueHolder { public: Holder(const ValueType& value): @@ -377,7 +398,7 @@ private: return typeid(ValueType); } - virtual Placeholder* clone() const + virtual ValueHolder* clone() const { return new Holder(_held); } @@ -388,13 +409,13 @@ private: Holder & operator=(const Holder &); }; - Placeholder* content() const + ValueHolder* content() const { return _pHolder; } private: - Placeholder* _pHolder; + ValueHolder* _pHolder; #endif // POCO_NO_SOO diff --git a/Foundation/include/Poco/Config.h b/Foundation/include/Poco/Config.h index c64853a00..49cd79bc0 100644 --- a/Foundation/include/Poco/Config.h +++ b/Foundation/include/Poco/Config.h @@ -93,6 +93,16 @@ // (see Poco/Types.h for default values). // #define POCO_NO_SOO + +// Small object size in bytes. Where applicable (e.g. +// SmallObjectAllocator specialization, Any, Var, etc) +// objects longer than this value will be alocated on the heap. +// See Poco/SmallObjectAllocator.h for usage of this value. +#if !defined(POCO_SMALL_OBJECT_SIZE) + #define POCO_SMALL_OBJECT_SIZE 32 +#endif + + // Following are options to remove certain features // to reduce library/executable size for smaller // embedded platforms. By enabling these options, diff --git a/Foundation/include/Poco/Dynamic/Pair.h b/Foundation/include/Poco/Dynamic/Pair.h index a119bdaae..4578a5c2d 100644 --- a/Foundation/include/Poco/Dynamic/Pair.h +++ b/Foundation/include/Poco/Dynamic/Pair.h @@ -229,9 +229,9 @@ public: throw BadCastException("Pair -> Poco::Timestamp"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Pair& value() const @@ -378,9 +378,9 @@ public: throw BadCastException("Pair -> Poco::Timestamp"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Pair& value() const diff --git a/Foundation/include/Poco/Dynamic/Struct.h b/Foundation/include/Poco/Dynamic/Struct.h index fcfac5428..e8e0897ba 100644 --- a/Foundation/include/Poco/Dynamic/Struct.h +++ b/Foundation/include/Poco/Dynamic/Struct.h @@ -325,9 +325,9 @@ public: throw BadCastException("Struct -> Poco::Timestamp"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Struct& value() const @@ -496,9 +496,9 @@ public: throw BadCastException("Struct -> Poco::Timestamp"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Struct& value() const diff --git a/Foundation/include/Poco/Dynamic/Var.h b/Foundation/include/Poco/Dynamic/Var.h index 77b52939c..5b8f58ec9 100644 --- a/Foundation/include/Poco/Dynamic/Var.h +++ b/Foundation/include/Poco/Dynamic/Var.h @@ -53,6 +53,7 @@ namespace Dynamic { template class Struct; + class Foundation_API Var /// Var allows to store data of different types and to convert between these types transparently. /// Var puts forth the best effort to provide intuitive and reasonable conversion semantics and prevent @@ -88,7 +89,7 @@ class Foundation_API Var /// '+', '+=', '-', '-=', '*', '*=' , '/' and '/=' /// /// - for integral values, following operations are supported: - /// prefix and postfix increment (++) and decement (--) + /// prefix and postfix increment (++) and decrement (--) /// /// - for all other types, InvalidArgumentException is thrown upon attempt of an arithmetic operation /// @@ -100,11 +101,15 @@ public: /// Creates an empty Var. template - Var(const T& val): - _pHolder(new VarHolderImpl(val)) + Var(const T& val) /// Creates the Var from the given value. +#ifdef POCO_NO_SOO + :_pHolder(new VarHolderImpl(val)) { } +#else { + construct(val); } +#endif Var(const char* pVal); // Convenience constructor for const char* which gets mapped to a std::string internally, i.e. pVal is deep-copied. @@ -133,10 +138,12 @@ public: /// not available for the given type. /// Throws InvalidAccessException if Var is empty. { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - _pHolder->convert(val); + pHolder->convert(val); } template @@ -153,13 +160,15 @@ public: /// not available for the given type. /// Throws InvalidAccessException if Var is empty. { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(T) == _pHolder->type()) return extract(); + if (typeid(T) == pHolder->type()) return extract(); T result; - _pHolder->convert(result); + pHolder->convert(result); return result; } @@ -177,15 +186,17 @@ public: /// not available for the given type. /// Throws InvalidAccessException if Var is empty. { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(T) == _pHolder->type()) + if (typeid(T) == pHolder->type()) return extract(); else { T result; - _pHolder->convert(result); + pHolder->convert(result); return result; } } @@ -199,16 +210,18 @@ public: /// is thrown. /// Throws InvalidAccessException if Var is empty. { - if (_pHolder && _pHolder->type() == typeid(T)) + VarHolder* pHolder = content(); + + if (pHolder && pHolder->type() == typeid(T)) { - VarHolderImpl* pHolderImpl = static_cast*>(_pHolder); + VarHolderImpl* pHolderImpl = static_cast*>(pHolder); return pHolderImpl->value(); } - else if (!_pHolder) + else if (!pHolder) throw InvalidAccessException("Can not extract empty value."); else throw BadCastException(format("Can not convert %s to %s.", - _pHolder->type().name(), + pHolder->type().name(), typeid(T).name())); } @@ -216,8 +229,12 @@ public: Var& operator = (const T& other) /// Assignment operator for assigning POD to Var { +#ifdef POCO_NO_SOO Var tmp(other); swap(tmp); +#else + construct(other); +#endif return *this; } @@ -536,9 +553,11 @@ private: template VarHolderImpl* holderImpl(const std::string errorMessage = "") const { - if (_pHolder && _pHolder->type() == typeid(T)) - return static_cast*>(_pHolder); - else if (!_pHolder) + VarHolder* pHolder = content(); + + if (pHolder && pHolder->type() == typeid(T)) + return static_cast*>(pHolder); + else if (!pHolder) throw InvalidAccessException("Can not access empty value."); else throw E(errorMessage); @@ -546,7 +565,64 @@ private: Var& structIndexOperator(VarHolderImpl >* pStr, int n) const; +#ifdef POCO_NO_SOO + + VarHolder* content() const + { + return _pHolder; + } + VarHolder* _pHolder; + +#else + + VarHolder* content() const + { + return _placeholder.content(); + } + + template + void construct(const ValueType& value) + { + if (sizeof(VarHolderImpl) <= _placeholder.SIZE) + { + new (reinterpret_cast(_placeholder.holder)) VarHolderImpl(value); + _placeholder.setLocal(true); + } + else + { + _placeholder.pHolder = new VarHolderImpl(value); + _placeholder.setLocal(false); + } + } + + void construct(const char* value) + { + std::string val(value); + if (sizeof(VarHolderImpl) <= _placeholder.SIZE) + { + new (reinterpret_cast(_placeholder.holder)) VarHolderImpl(val); + _placeholder.setLocal(true); + } + else + { + _placeholder.pHolder = new VarHolderImpl(val); + _placeholder.setLocal(false); + } + } + + void construct(const Var& other) + { + if(!other.isEmpty()) + other.content()->clone(&_placeholder); + else + _placeholder.erase(); + } + + Placeholder _placeholder; + +#endif // POCO_NO_SOO + }; @@ -559,15 +635,36 @@ private: /// Var members /// -inline void Var::swap(Var& ptr) +inline void Var::swap(Var& other) { - std::swap(_pHolder, ptr._pHolder); +#ifdef POCO_NO_SOO + + std::swap(_pHolder, other._pHolder); + +#else + + if (this == &other) return; + + if (!_placeholder.isLocal() && !other._placeholder.isLocal()) + { + std::swap(_placeholder.pHolder, other._placeholder.pHolder); + } + else + { + Var tmp(*this); + if (_placeholder.isLocal()) this->~Var(); + construct(other); + other = tmp; + } + +#endif } inline const std::type_info& Var::type() const { - return _pHolder ? _pHolder->type() : typeid(void); + VarHolder* pHolder = content(); + return pHolder ? pHolder->type() : typeid(void); } @@ -603,49 +700,56 @@ inline bool Var::operator ! () const inline bool Var::isEmpty() const { - return 0 == _pHolder; + return 0 == content(); } inline bool Var::isArray() const { - return _pHolder ? _pHolder->isArray() : false; + VarHolder* pHolder = content(); + return pHolder ? pHolder->isArray() : false; } inline bool Var::isStruct() const { - return _pHolder ? _pHolder->isStruct() : false; + VarHolder* pHolder = content(); + return pHolder ? pHolder->isStruct() : false; } inline bool Var::isInteger() const { - return _pHolder ? _pHolder->isInteger() : false; + VarHolder* pHolder = content(); + return pHolder ? pHolder->isInteger() : false; } inline bool Var::isSigned() const { - return _pHolder ? _pHolder->isSigned() : false; + VarHolder* pHolder = content(); + return pHolder ? pHolder->isSigned() : false; } inline bool Var::isNumeric() const { - return _pHolder ? _pHolder->isNumeric() : false; + VarHolder* pHolder = content(); + return pHolder ? pHolder->isNumeric() : false; } inline bool Var::isString() const { - return _pHolder ? _pHolder->isString() : false; + VarHolder* pHolder = content(); + return pHolder ? pHolder->isString() : false; } /// /// Var non-member functions /// + inline const Var operator + (const char* other, const Var& da) /// Addition operator for adding Var to const char* { diff --git a/Foundation/include/Poco/Dynamic/VarHolder.h b/Foundation/include/Poco/Dynamic/VarHolder.h index 52a96b193..0dbdfb0ff 100644 --- a/Foundation/include/Poco/Dynamic/VarHolder.h +++ b/Foundation/include/Poco/Dynamic/VarHolder.h @@ -50,6 +50,7 @@ #include "Poco/DateTimeFormatter.h" #include "Poco/DateTimeParser.h" #include "Poco/String.h" +#include "Poco/Any.h" #include "Poco/Exception.h" #include #include @@ -68,6 +69,7 @@ class Var; bool Foundation_API isJSONString(const Var& any); /// Returns true for values that should be JSON-formatted as string. + void Foundation_API appendJSONString(std::string& val, const Var& any); /// Converts the any to a JSON value and adds it to val @@ -92,13 +94,17 @@ public: virtual ~VarHolder(); /// Destroys the VarHolder. - virtual VarHolder* clone() const; - /// Throws NotImplementedException. Implementation should + virtual VarHolder* clone(Placeholder* pHolder = 0) const = 0; + /// Implementation must implement this function to /// deep-copy the VarHolder. - - virtual const std::type_info& type() const; - /// Throws NotImplementedException. Implementation should - /// return the type information for the stored content. + /// If small object optimization is enabled (i.e. if + /// POCO_NO_SOO is not defined), VarHolder will be + /// instantiated in-place if it's size is smaller + /// than POCO_SMALL_OBJECT_SIZE. + + virtual const std::type_info& type() const = 0; + /// Implementation must return the type information + /// (typeid) for the stored content. virtual void convert(Int8& val) const; /// Throws BadCastException. Must be overriden in a type @@ -145,12 +151,15 @@ public: /// specialization in order to suport the conversion. #ifndef POCO_LONG_IS_64_BIT + void convert(long& val) const; /// Calls convert(Int32). void convert(unsigned long& val) const; /// Calls convert(UInt32). + #endif + virtual void convert(bool& val) const; /// Throws BadCastException. Must be overriden in a type /// specialization in order to suport the conversion. @@ -199,6 +208,35 @@ protected: VarHolder(); /// Creates the VarHolder. + template + VarHolder* cloneHolder(Placeholder* pVarHolder, const T& val) const + /// Instantiates value holder wrapper. If size of the wrapper is + /// larger than POCO_SMALL_OBJECT_SIZE, holder is instantiated on + /// the heap, otherwise it is instantiated in-place (in the + /// pre-allocated buffer inside the holder). + /// + /// Called from clone() member function of the implementation when + /// smal object optimization is enabled. + { +#ifdef POCO_NO_SOO + return new VarHolderImpl(val); +#else + poco_check_ptr (pVarHolder); + if ((sizeof(VarHolderImpl) <= pVarHolder->SIZE)) + { + new ((VarHolder*) pVarHolder->holder) VarHolderImpl(val); + pVarHolder->setLocal(true); + return (VarHolder*) pVarHolder->holder; + } + else + { + pVarHolder->pHolder = new VarHolderImpl(val); + pVarHolder->setLocal(false); + return pVarHolder->pHolder; + } +#endif + } + template void convertToSmaller(const F& from, T& to) const /// This function is meant to convert signed numeric values from @@ -338,16 +376,6 @@ private: // inlines // -inline VarHolder* VarHolder::clone() const -{ - throw NotImplementedException("Not implemented: VarHolder::clone()"); -} - - -inline const std::type_info& VarHolder::type() const -{ - throw NotImplementedException("Not implemented: VarHolder::type()"); -} inline void VarHolder::convert(Int8& /*val*/) const { @@ -414,8 +442,8 @@ inline void VarHolder::convert(Timestamp& /*val*/) const throw BadCastException("Can not convert to Timestamp"); } - #ifndef POCO_LONG_IS_64_BIT + inline void VarHolder::convert(long& val) const { Int32 tmp; @@ -430,8 +458,8 @@ inline void VarHolder::convert(unsigned long& val) const convert(tmp); val = tmp; } -#endif +#endif inline void VarHolder::convert(bool& /*val*/) const { @@ -533,9 +561,9 @@ public: return typeid(T); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const T& value() const @@ -634,9 +662,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Int8& value() const @@ -767,9 +795,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Int16& value() const @@ -900,9 +928,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Int32& value() const @@ -1048,9 +1076,9 @@ public: val = Timestamp(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Int64& value() const @@ -1181,9 +1209,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const UInt8& value() const @@ -1314,9 +1342,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const UInt16& value() const @@ -1447,9 +1475,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const UInt32& value() const @@ -1601,9 +1629,9 @@ public: val = Timestamp(tmp); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const UInt64& value() const @@ -1732,9 +1760,9 @@ public: val = (_val ? "true" : "false"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const bool& value() const @@ -1866,9 +1894,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const float& value() const @@ -2006,9 +2034,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const double& value() const @@ -2137,9 +2165,9 @@ public: val = std::string(1, _val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const char& value() const @@ -2316,9 +2344,9 @@ public: ts = tmp.timestamp(); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const std::string& value() const @@ -2452,9 +2480,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const long& value() const @@ -2585,9 +2613,9 @@ public: val = NumberFormatter::format(_val); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const unsigned long& value() const @@ -2678,9 +2706,9 @@ public: val.append(" ]"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const std::vector& value() const @@ -2799,9 +2827,9 @@ public: ts = _val.timestamp(); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const DateTime& value() const @@ -2895,9 +2923,9 @@ public: ts = _val.timestamp(); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const LocalDateTime& value() const @@ -2991,9 +3019,9 @@ public: ts = _val; } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const Timestamp& value() const diff --git a/Foundation/include/Poco/SmallObjectAllocator.h b/Foundation/include/Poco/SmallObjectAllocator.h index be7cc8b19..f30ba438b 100644 --- a/Foundation/include/Poco/SmallObjectAllocator.h +++ b/Foundation/include/Poco/SmallObjectAllocator.h @@ -150,7 +150,7 @@ class SmallObjectAllocator /// /// The treshold between auto and heap allocation /// is controlled through POCO_SMALL_OBJECT_SIZE compile - /// time constant, which on 32 or 64 systems defaults + /// time constant, which on 32 or 64-bit systems defaults /// to 31 or 63 bytes respectively. This specialization /// adds an extra byte to indicate the allocation strategy. /// diff --git a/Foundation/include/Poco/Types.h b/Foundation/include/Poco/Types.h index 6c87ef118..6f1c41a27 100644 --- a/Foundation/include/Poco/Types.h +++ b/Foundation/include/Poco/Types.h @@ -220,17 +220,6 @@ namespace Poco { #endif -// Small object size in bytes. Where applicable (e.g. -// SmallObjectAllocator specialization of , Any, etc) -// objects longer than this value will be alocated on the heap. -// See Poco/SmallObjectAllocator.h for details. -#if (POCO_PTR_IS_64_BIT == 1) - #define POCO_SMALL_OBJECT_SIZE 63 -#else - #define POCO_SMALL_OBJECT_SIZE 31 -#endif - - } // namespace Poco diff --git a/Foundation/src/Var.cpp b/Foundation/src/Var.cpp index e9457946d..94edbedff 100644 --- a/Foundation/src/Var.cpp +++ b/Foundation/src/Var.cpp @@ -44,35 +44,64 @@ namespace Poco { namespace Dynamic { -Var::Var(): _pHolder(0) +Var::Var() +#ifdef POCO_NO_SOO + : _pHolder(0) +#endif { } -Var::Var(const char* pVal): - _pHolder(new VarHolderImpl(pVal)) +Var::Var(const char* pVal) +#ifdef POCO_NO_SOO + : _pHolder(new VarHolderImpl(pVal)) { } +#else { + construct(std::string(pVal)); } +#endif -Var::Var(const Var& other): - _pHolder(0) +Var::Var(const Var& other) +#ifdef POCO_NO_SOO + : _pHolder(0) { if (other._pHolder) _pHolder = other._pHolder->clone(); } +#else +{ + if ((this != &other) && !other.isEmpty()) + construct(other); +} +#endif Var::~Var() { - delete _pHolder; + if(!isEmpty()) + { +#ifndef POCO_NO_SOO + if(_placeholder.isLocal()) + content()->~VarHolder(); + else +#endif + delete content(); + } } -Var& Var::operator = (const Var& other) +Var& Var::operator = (const Var& rhs) { - Var tmp(other); +#ifdef POCO_NO_SOO + Var tmp(rhs); swap(tmp); +#else + if ((this != &rhs) && !rhs.isEmpty()) + construct(rhs); + else if ((this != &rhs) && rhs.isEmpty()) + _placeholder.erase(); +#endif return *this; } @@ -320,8 +349,14 @@ bool Var::operator && (const Var& other) const void Var::empty() { +#ifdef POCO_NO_SOO delete _pHolder; _pHolder = 0; +#else + if (_placeholder.isLocal()) this->~Var(); + else delete content(); + _placeholder.erase(); +#endif } diff --git a/JSON/include/Poco/JSON/Array.h b/JSON/include/Poco/JSON/Array.h index 413e9001f..9c4fc598a 100644 --- a/JSON/include/Poco/JSON/Array.h +++ b/JSON/include/Poco/JSON/Array.h @@ -279,22 +279,22 @@ public: void convert(DateTime& /*val*/) const { - throw BadCastException(); + throw BadCastException("Cannot convert Array to DateTime"); } void convert(LocalDateTime& /*ldt*/) const { - throw BadCastException(); + throw BadCastException("Cannot convert Array to LocalDateTime"); } void convert(Timestamp& /*ts*/) const { - throw BadCastException(); + throw BadCastException("Cannot convert Array to Timestamp"); } - VarHolder* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const JSON::Array::Ptr& value() const diff --git a/JSON/include/Poco/JSON/Object.h b/JSON/include/Poco/JSON/Object.h index 38fb610bb..1ea3cc3b7 100644 --- a/JSON/include/Poco/JSON/Object.h +++ b/JSON/include/Poco/JSON/Object.h @@ -291,21 +291,24 @@ public: void convert(DateTime& /*val*/) const { //TODO: val = _val; + throw NotImplementedException("Conversion not implemented: JSON:Object => DateTime"); } void convert(LocalDateTime& /*ldt*/) const { //TODO: ldt = _val.timestamp(); + throw NotImplementedException("Conversion not implemented: JSON:Object => LocalDateTime"); } void convert(Timestamp& /*ts*/) const { //TODO: ts = _val.timestamp(); + throw NotImplementedException("Conversion not implemented: JSON:Object => Timestamp"); } - VarHolderImpl* clone() const + VarHolder* clone(Placeholder* pVarHolder = 0) const { - return new VarHolderImpl(_val); + return cloneHolder(pVarHolder, _val); } const JSON::Object::Ptr& value() const diff --git a/Net/include/Poco/Net/IPAddress.h b/Net/include/Poco/Net/IPAddress.h index d1f5069cd..58c37f79a 100644 --- a/Net/include/Poco/Net/IPAddress.h +++ b/Net/include/Poco/Net/IPAddress.h @@ -393,8 +393,8 @@ private: char _memory[sizeof(Poco::Net::Impl::IPv6AddressImpl)]; - friend class IPv4AddressImpl; - friend class IPv6AddressImpl; + friend class Poco::Net::Impl::IPv4AddressImpl; + friend class Poco::Net::Impl::IPv6AddressImpl; }; From 2661b54ff68e0c7a9c3da6c62f03c6137af299a0 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 5 Feb 2013 22:56:03 -0600 Subject: [PATCH 12/25] work around static union member (non-C++03) --- Foundation/include/Poco/Any.h | 18 +++++++++++------- Foundation/include/Poco/Dynamic/Var.h | 4 ++-- Foundation/include/Poco/Dynamic/VarHolder.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index 3b030abbd..abf6620da 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -69,7 +69,11 @@ union Placeholder /// where the object was allocated (0 => heap, 1 => local). { public: - static const unsigned int SIZE = SizeV; + + struct Size + { + static const unsigned int value = SizeV; + }; Placeholder () { @@ -83,12 +87,12 @@ public: bool isLocal() const { - return holder[SIZE] != 0; + return holder[SizeV] != 0; } void setLocal(bool local) const { - holder[SIZE] = local ? 1 : 0; + holder[SizeV] = local ? 1 : 0; } PlaceholderT* content() const @@ -101,7 +105,7 @@ public: private: PlaceholderT* pHolder; - mutable unsigned char holder[SIZE + 1]; + mutable unsigned char holder[SizeV + 1]; friend class Any; friend class Dynamic::Var; @@ -211,7 +215,7 @@ public: /// Returns true if the Any is empty. { char buf[POCO_SMALL_OBJECT_SIZE] = { 0 }; - return 0 == std::memcmp(_valueHolder.holder, buf, _valueHolder.SIZE); + return 0 == std::memcmp(_valueHolder.holder, buf, POCO_SMALL_OBJECT_SIZE); } const std::type_info & type() const @@ -252,7 +256,7 @@ private: virtual void clone(Placeholder* pPlaceholder) const { - if ((sizeof(Holder) <= pPlaceholder->SIZE)) + if ((sizeof(Holder) <= POCO_SMALL_OBJECT_SIZE)) { new ((ValueHolder*) pPlaceholder->holder) Holder(_held); pPlaceholder->setLocal(true); @@ -278,7 +282,7 @@ private: template void construct(const ValueType& value) { - if (sizeof(Holder) <= _valueHolder.SIZE) + if (sizeof(Holder) <= Placeholder::Size::value) { new (reinterpret_cast(_valueHolder.holder)) Holder(value); _valueHolder.setLocal(true); diff --git a/Foundation/include/Poco/Dynamic/Var.h b/Foundation/include/Poco/Dynamic/Var.h index 5b8f58ec9..569e7e65f 100644 --- a/Foundation/include/Poco/Dynamic/Var.h +++ b/Foundation/include/Poco/Dynamic/Var.h @@ -584,7 +584,7 @@ private: template void construct(const ValueType& value) { - if (sizeof(VarHolderImpl) <= _placeholder.SIZE) + if (sizeof(VarHolderImpl) <= Placeholder::Size::value) { new (reinterpret_cast(_placeholder.holder)) VarHolderImpl(value); _placeholder.setLocal(true); @@ -599,7 +599,7 @@ private: void construct(const char* value) { std::string val(value); - if (sizeof(VarHolderImpl) <= _placeholder.SIZE) + if (sizeof(VarHolderImpl) <= Placeholder::Size::value) { new (reinterpret_cast(_placeholder.holder)) VarHolderImpl(val); _placeholder.setLocal(true); diff --git a/Foundation/include/Poco/Dynamic/VarHolder.h b/Foundation/include/Poco/Dynamic/VarHolder.h index 0dbdfb0ff..327a0850a 100644 --- a/Foundation/include/Poco/Dynamic/VarHolder.h +++ b/Foundation/include/Poco/Dynamic/VarHolder.h @@ -222,7 +222,7 @@ protected: return new VarHolderImpl(val); #else poco_check_ptr (pVarHolder); - if ((sizeof(VarHolderImpl) <= pVarHolder->SIZE)) + if ((sizeof(VarHolderImpl) <= Placeholder::Size::value)) { new ((VarHolder*) pVarHolder->holder) VarHolderImpl(val); pVarHolder->setLocal(true); From 7dcee53937268e49bb7314a46e41916b8290c619 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Tue, 5 Feb 2013 23:10:54 -0600 Subject: [PATCH 13/25] gcc compile --- Foundation/include/Poco/Any.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Foundation/include/Poco/Any.h b/Foundation/include/Poco/Any.h index abf6620da..e9208bcbd 100644 --- a/Foundation/include/Poco/Any.h +++ b/Foundation/include/Poco/Any.h @@ -110,7 +110,7 @@ private: friend class Any; friend class Dynamic::Var; friend class Dynamic::VarHolder; - template friend class VarHolderImpl; + template friend class Dynamic::VarHolderImpl; }; From d6042065eca4f90b4846f1788ffa07716b465618 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 9 Feb 2013 22:39:07 -0600 Subject: [PATCH 14/25] Auto init for Net and SQLite (win) Auto init for Net and SQLite (only tested on Windows) --- CppUnit/WinTestRunner/src/ActiveTest.h | 16 +- Data/SQLite/SQLite_vs100.vcxproj | 156 +++++++++--------- .../include/Poco/Data/SQLite/Connector.h | 59 ++++++- Data/SQLite/include/Poco/Data/SQLite/SQLite.h | 2 +- .../include/Poco/Data/SQLite/SessionImpl.h | 2 +- Data/SQLite/src/Connector.cpp | 7 +- Data/SQLite/src/SessionImpl.cpp | 1 - Data/SQLite/testsuite/src/SQLiteTest.cpp | 2 - Data/samples/Binding/src/Binding.cpp | 3 - .../samples/RecordSet/RecordSet_vs100.vcxproj | 134 +++++++-------- Data/samples/RecordSet/src/RecordSet.cpp | 3 - .../samples/RowFormatter/src/RowFormatter.cpp | 3 - Data/samples/Tuple/src/Tuple.cpp | 3 - Data/samples/TypeHandler/src/TypeHandler.cpp | 3 - Foundation/include/Poco/Config.h | 8 + Net/include/Poco/Net/Net.h | 36 ++-- Net/src/Net.cpp | 71 +++----- 17 files changed, 273 insertions(+), 236 deletions(-) diff --git a/CppUnit/WinTestRunner/src/ActiveTest.h b/CppUnit/WinTestRunner/src/ActiveTest.h index 232747a9c..bf9df5e7d 100644 --- a/CppUnit/WinTestRunner/src/ActiveTest.h +++ b/CppUnit/WinTestRunner/src/ActiveTest.h @@ -38,16 +38,16 @@ public: ActiveTest(Test* test); ~ActiveTest(); - void run(TestResult* result); + void run(TestResult* result); protected: - HANDLE _threadHandle; - CEvent _runCompleted; - TestResult* _currentTestResult; - - void run (); - void setTestResult(TestResult* result); - static UINT threadFunction(LPVOID thisInstance); + HANDLE _threadHandle; + CEvent _runCompleted; + TestResult* _currentTestResult; + + void run (); + void setTestResult(TestResult* result); + static UINT threadFunction(LPVOID thisInstance); }; diff --git a/Data/SQLite/SQLite_vs100.vcxproj b/Data/SQLite/SQLite_vs100.vcxproj index 64a095484..c7d8b1cb8 100644 --- a/Data/SQLite/SQLite_vs100.vcxproj +++ b/Data/SQLite/SQLite_vs100.vcxproj @@ -1,4 +1,4 @@ - + @@ -32,76 +32,76 @@ SQLite Win32Proj - - + + StaticLibrary MultiByte - + StaticLibrary MultiByte - + StaticLibrary MultiByte - + StaticLibrary MultiByte - + DynamicLibrary MultiByte - + DynamicLibrary MultiByte - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + <_ProjectFileVersion>10.0.40219.1 - ..\..\bin\ - obj\$(Configuration)\ - true - ..\..\bin\ - obj\$(Configuration)\ - false - ..\..\lib\ - obj\$(Configuration)\ - ..\..\lib\ - obj\$(Configuration)\ - ..\..\lib\ - obj\$(Configuration)\ - ..\..\lib\ - obj\$(Configuration)\ - PocoDataSQLited - PocoDataSQLitemdd - PocoDataSQLitemtd - PocoDataSQLite - PocoDataSQLitemd - PocoDataSQLitemt + ..\..\bin\ + obj\$(Configuration)\ + true + ..\..\bin\ + obj\$(Configuration)\ + false + ..\..\lib\ + obj\$(Configuration)\ + ..\..\lib\ + obj\$(Configuration)\ + ..\..\lib\ + obj\$(Configuration)\ + ..\..\lib\ + obj\$(Configuration)\ + PocoDataSQLited + PocoDataSQLitemdd + PocoDataSQLitemtd + PocoDataSQLite + PocoDataSQLitemd + PocoDataSQLitemt - + Disabled .\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories) @@ -114,7 +114,7 @@ true true true - + Level3 EditAndContinue Default @@ -132,7 +132,7 @@ MachineX86 - + Disabled OnlyExplicitInline @@ -147,9 +147,9 @@ true true true - + Level3 - + Default 4996;4244;4018;%(DisableSpecificWarnings) @@ -166,7 +166,7 @@ MachineX86 - + Disabled .\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories) @@ -179,7 +179,7 @@ true true true - + ..\..\lib\PocoDataSQLitemtd.pdb Level3 EditAndContinue @@ -190,7 +190,7 @@ ..\..\lib\PocoDataSQLitemtd.lib - + Disabled OnlyExplicitInline @@ -205,9 +205,9 @@ true true true - + Level3 - + Default 4996;4244;4018;%(DisableSpecificWarnings) @@ -215,7 +215,7 @@ ..\..\lib\PocoDataSQLitemt.lib - + Disabled .\include;..\..\Foundation\include;..\..\Data\include;%(AdditionalIncludeDirectories) @@ -228,7 +228,7 @@ true true true - + ..\..\lib\PocoDataSQLitemdd.pdb Level3 EditAndContinue @@ -239,7 +239,7 @@ ..\..\lib\PocoDataSQLitemdd.lib - + Disabled OnlyExplicitInline @@ -254,10 +254,10 @@ true true true - + ..\..\lib\PocoDataSQLitemd.pdb Level3 - + Default 4996;4244;4018;%(DisableSpecificWarnings) @@ -267,26 +267,26 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + \ No newline at end of file diff --git a/Data/SQLite/include/Poco/Data/SQLite/Connector.h b/Data/SQLite/include/Poco/Data/SQLite/Connector.h index eefe6961f..2ee8afcc6 100644 --- a/Data/SQLite/include/Poco/Data/SQLite/Connector.h +++ b/Data/SQLite/include/Poco/Data/SQLite/Connector.h @@ -44,6 +44,12 @@ #include "Poco/Data/Connector.h" +// Note: to avoid static (de)initialization problems, +// during connector automatic (un)registration, it is +// best to have this as a macro. +#define POCO_DATA_SQLITE_CONNECTOR_NAME "sqlite" + + namespace Poco { namespace Data { namespace SQLite { @@ -91,11 +97,62 @@ public: /// inline const std::string& Connector::name() const { - return KEY; + static const std::string name(POCO_DATA_SQLITE_CONNECTOR_NAME); + return name; } } } } // namespace Poco::Data::SQLite +// +// Automatic Connector registration +// + +struct SQLite_API SQLiteConnectorRegistrator + /// Connector registering class. + /// A global instance of this class is instantiated + /// with sole purpose to automatically register the + /// SQLite connector with central Poco Data registry. +{ + SQLiteConnectorRegistrator() + /// Calls Poco::Data::SQLite::registerConnector(); + { + Poco::Data::SQLite::Connector::registerConnector(); + } + + ~SQLiteConnectorRegistrator() + /// Calls Poco::Data::SQLite::unregisterConnector(); + { + Poco::Data::SQLite::Connector::unregisterConnector(); + } +}; + + +#if !defined(POCO_NO_AUTOMATIC_LIB_INIT) + #if defined(POCO_OS_FAMILY_WINDOWS) + extern "C" const struct SQLite_API SQLiteConnectorRegistrator pocoSQLiteConnectorRegistrator; + #if defined(SQLite_EXPORTS) + #if defined(_WIN64) + #define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:"#s)) + #elif defined(_WIN32) + #define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:_"#s)) + #endif + #else // SQLite_EXPORTS + #if defined(_WIN64) + #define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:"#s)) + #elif defined(_WIN32) + #define POCO_DATA_SQLITE_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:_"#s)) + #endif + #endif // SQLite_EXPORTS + #else // !POCO_OS_FAMILY_WINDOWS + #define POCO_DATA_SQLITE_FORCE_SYMBOL(s) extern "C" const struct SQLiteConnectorRegistrator s; + #endif // POCO_OS_FAMILY_WINDOWS + POCO_DATA_SQLITE_FORCE_SYMBOL(pocoSQLiteConnectorRegistrator) +#endif // POCO_NO_AUTOMATIC_LIB_INIT + +// +// End automatic Connector registration +// + #endif // Data_SQLite_Connector_INCLUDED diff --git a/Data/SQLite/include/Poco/Data/SQLite/SQLite.h b/Data/SQLite/include/Poco/Data/SQLite/SQLite.h index ea013103a..15ea80b9b 100644 --- a/Data/SQLite/include/Poco/Data/SQLite/SQLite.h +++ b/Data/SQLite/include/Poco/Data/SQLite/SQLite.h @@ -84,7 +84,7 @@ // // Thread safety mode defaults to "serialized". // See http://www.sqlite.org/threadsafe.html for details. -// Threading mode significantly affects performance +// Threading mode may significantly affect performance // (see TestSuite::benchmarkThreadModesTiming) // #ifndef SQLITE_THREADSAFE diff --git a/Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h b/Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h index 912c74c57..a9118087b 100644 --- a/Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h +++ b/Data/SQLite/include/Poco/Data/SQLite/SessionImpl.h @@ -41,6 +41,7 @@ #include "Poco/Data/SQLite/SQLite.h" +#include "Poco/Data/SQLite/Connector.h" #include "Poco/Data/SQLite/Binder.h" #include "Poco/Data/AbstractSessionImpl.h" #include "Poco/SharedPtr.h" @@ -128,7 +129,6 @@ public: /// Returns the name of the connector. private: - std::string _connector; sqlite3* _pDB; bool _connected; diff --git a/Data/SQLite/src/Connector.cpp b/Data/SQLite/src/Connector.cpp index c4c6fa6db..70de69a80 100644 --- a/Data/SQLite/src/Connector.cpp +++ b/Data/SQLite/src/Connector.cpp @@ -44,12 +44,15 @@ #endif +const SQLiteConnectorRegistrator pocoSQLiteConnectorRegistrator; + + namespace Poco { namespace Data { namespace SQLite { -const std::string Connector::KEY("sqlite"); +const std::string Connector::KEY(POCO_DATA_SQLITE_CONNECTOR_NAME); Connector::Connector() @@ -77,7 +80,7 @@ void Connector::registerConnector() void Connector::unregisterConnector() { - Poco::Data::SessionFactory::instance().remove(KEY); + Poco::Data::SessionFactory::instance().remove(POCO_DATA_SQLITE_CONNECTOR_NAME); } diff --git a/Data/SQLite/src/SessionImpl.cpp b/Data/SQLite/src/SessionImpl.cpp index 91bbb0029..9dde4c34d 100644 --- a/Data/SQLite/src/SessionImpl.cpp +++ b/Data/SQLite/src/SessionImpl.cpp @@ -37,7 +37,6 @@ #include "Poco/Data/SQLite/SessionImpl.h" #include "Poco/Data/SQLite/Utility.h" #include "Poco/Data/SQLite/SQLiteStatementImpl.h" -#include "Poco/Data/SQLite/Connector.h" #include "Poco/Data/SQLite/SQLiteException.h" #include "Poco/Data/Session.h" #include "Poco/ActiveMethod.h" diff --git a/Data/SQLite/testsuite/src/SQLiteTest.cpp b/Data/SQLite/testsuite/src/SQLiteTest.cpp index 443ed141b..ee3a9a9e4 100644 --- a/Data/SQLite/testsuite/src/SQLiteTest.cpp +++ b/Data/SQLite/testsuite/src/SQLiteTest.cpp @@ -251,13 +251,11 @@ private: SQLiteTest::SQLiteTest(const std::string& name): CppUnit::TestCase(name) { - Poco::Data::SQLite::Connector::registerConnector(); } SQLiteTest::~SQLiteTest() { - Poco::Data::SQLite::Connector::unregisterConnector(); } diff --git a/Data/samples/Binding/src/Binding.cpp b/Data/samples/Binding/src/Binding.cpp index 214b1fedd..07964acd8 100644 --- a/Data/samples/Binding/src/Binding.cpp +++ b/Data/samples/Binding/src/Binding.cpp @@ -52,9 +52,6 @@ struct Person int main(int argc, char** argv) { - // register SQLite connector - Poco::Data::SQLite::Connector::registerConnector(); - // create a session Session session("SQLite", "sample.db"); diff --git a/Data/samples/RecordSet/RecordSet_vs100.vcxproj b/Data/samples/RecordSet/RecordSet_vs100.vcxproj index 47b6e5310..234912723 100644 --- a/Data/samples/RecordSet/RecordSet_vs100.vcxproj +++ b/Data/samples/RecordSet/RecordSet_vs100.vcxproj @@ -1,4 +1,4 @@ - + @@ -32,84 +32,84 @@ RecordSet Win32Proj - - + + Application MultiByte - + Application MultiByte - + Application MultiByte - + Application MultiByte - + Application MultiByte - + Application MultiByte - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + <_ProjectFileVersion>10.0.40219.1 - bin\ - obj\$(Configuration)\ - true - bin\ - obj\$(Configuration)\ - false - bin\static_mt\ - obj\$(Configuration)\ - true - bin\static_mt\ - obj\$(Configuration)\ - false - bin\static_md\ - obj\$(Configuration)\ - true - bin\static_md\ - obj\$(Configuration)\ - false - RecordSetd - RecordSetd - RecordSetd - RecordSet - RecordSet - RecordSet + bin\ + obj\$(Configuration)\ + true + bin\ + obj\$(Configuration)\ + false + bin\static_mt\ + obj\$(Configuration)\ + true + bin\static_mt\ + obj\$(Configuration)\ + false + bin\static_md\ + obj\$(Configuration)\ + true + bin\static_md\ + obj\$(Configuration)\ + false + RecordSetd + RecordSetd + RecordSetd + RecordSet + RecordSet + RecordSet - + Disabled .\include;..\..\..\Foundation\include;..\..\..\XML\include;..\..\..\Util\include;..\..\..\Data\include;..\..\..\Data\SQLite\include;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_DLL;%(PreprocessorDefinitions) true true EnableFastChecks @@ -118,7 +118,7 @@ true true true - + Level3 EditAndContinue Default @@ -135,7 +135,7 @@ MachineX86 - + Disabled OnlyExplicitInline @@ -150,9 +150,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -167,7 +167,7 @@ MachineX86 - + Disabled .\include;..\..\..\Foundation\include;..\..\..\XML\include;..\..\..\Util\include;..\..\..\Data\include;..\..\..\Data\SQLite\include;%(AdditionalIncludeDirectories) @@ -180,7 +180,7 @@ true true true - + Level3 EditAndContinue Default @@ -197,7 +197,7 @@ MachineX86 - + Disabled OnlyExplicitInline @@ -212,9 +212,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -229,7 +229,7 @@ MachineX86 - + Disabled .\include;..\..\..\Foundation\include;..\..\..\XML\include;..\..\..\Util\include;..\..\..\Data\include;..\..\..\Data\SQLite\include;%(AdditionalIncludeDirectories) @@ -242,7 +242,7 @@ true true true - + Level3 EditAndContinue Default @@ -259,7 +259,7 @@ MachineX86 - + Disabled OnlyExplicitInline @@ -274,9 +274,9 @@ true true true - + Level3 - + Default %(DisableSpecificWarnings) @@ -292,8 +292,8 @@ - + - - - + + + \ No newline at end of file diff --git a/Data/samples/RecordSet/src/RecordSet.cpp b/Data/samples/RecordSet/src/RecordSet.cpp index a1a4823fb..f9a6c438c 100644 --- a/Data/samples/RecordSet/src/RecordSet.cpp +++ b/Data/samples/RecordSet/src/RecordSet.cpp @@ -58,9 +58,6 @@ struct Person int main(int argc, char** argv) { - // register SQLite connector - Poco::Data::SQLite::Connector::registerConnector(); - // create a session Session session("SQLite", "sample.db"); diff --git a/Data/samples/RowFormatter/src/RowFormatter.cpp b/Data/samples/RowFormatter/src/RowFormatter.cpp index 37da2ac10..87b8f80eb 100644 --- a/Data/samples/RowFormatter/src/RowFormatter.cpp +++ b/Data/samples/RowFormatter/src/RowFormatter.cpp @@ -103,9 +103,6 @@ public: int main(int argc, char** argv) { - // register SQLite connector - Poco::Data::SQLite::Connector::registerConnector(); - // create a session Session session("SQLite", "sample.db"); diff --git a/Data/samples/Tuple/src/Tuple.cpp b/Data/samples/Tuple/src/Tuple.cpp index a0aa8636d..91c60384b 100644 --- a/Data/samples/Tuple/src/Tuple.cpp +++ b/Data/samples/Tuple/src/Tuple.cpp @@ -50,9 +50,6 @@ int main(int argc, char** argv) typedef Poco::Tuple Person; typedef std::vector People; - // register SQLite connector - Poco::Data::SQLite::Connector::registerConnector(); - // create a session Session session("SQLite", "sample.db"); diff --git a/Data/samples/TypeHandler/src/TypeHandler.cpp b/Data/samples/TypeHandler/src/TypeHandler.cpp index 52d8315f1..8e193d3e2 100644 --- a/Data/samples/TypeHandler/src/TypeHandler.cpp +++ b/Data/samples/TypeHandler/src/TypeHandler.cpp @@ -103,9 +103,6 @@ public: int main(int argc, char** argv) { - // register SQLite connector - Poco::Data::SQLite::Connector::registerConnector(); - // create a session Session session("SQLite", "sample.db"); diff --git a/Foundation/include/Poco/Config.h b/Foundation/include/Poco/Config.h index 49cd79bc0..2924e61e1 100644 --- a/Foundation/include/Poco/Config.h +++ b/Foundation/include/Poco/Config.h @@ -51,6 +51,14 @@ // #define POCO_NO_AUTOMATIC_LIBS +// Define to disable automatic initialization +// Defining this will disable ALL automatic +// initialization framework-wide (e.g. Net +// on Windows, all Data back-ends, etc). +// +// #define POCO_NO_AUTOMATIC_LIB_INIT + + // Define to disable FPEnvironment support // #define POCO_NO_FPENVIRONMENT diff --git a/Net/include/Poco/Net/Net.h b/Net/include/Poco/Net/Net.h index ebe456cb6..dcfad07fb 100644 --- a/Net/include/Poco/Net/Net.h +++ b/Net/include/Poco/Net/Net.h @@ -95,28 +95,42 @@ namespace Net { inline void Net_API initializeNetwork(); /// Initialize the network subsystem. + /// (Windows only, no-op elsewhere) inline void Net_API uninitializeNetwork(); /// Uninitialize the network subsystem. + /// (Windows only, no-op elsewhere) }} // namespace Poco::Net // -// Automate network initialization on Windows. +// Automate network initialization (only relevant on Windows). // -#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_NET_NO_WINDOWS_INIT) - #if defined(POCO_STATIC) - extern "C" const struct NetworkInitializer pocoNetworkInitializer; - #ifdef _WIN64 - #pragma comment(linker, "/include:pocoNetworkInitializer") - #else - #pragma comment(linker, "/include:_pocoNetworkInitializer") - #endif - #endif // POCO_STATIC -#endif // POCO_NET_NO_WINDOWS_INIT + +#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_NO_AUTOMATIC_LIB_INIT) + +extern "C" const struct Net_API NetworkInitializer pocoNetworkInitializer; + +#if defined(Net_EXPORTS) + #if defined(_WIN64) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:"#s)) + #elif defined(_WIN32) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:_"#s)) + #endif +#else // !Net_EXPORTS + #if defined(_WIN64) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:"#s)) + #elif defined(_WIN32) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:_"#s)) + #endif +#endif // Net_EXPORTS + +POCO_NET_FORCE_SYMBOL(pocoNetworkInitializer) + +#endif // POCO_OS_FAMILY_WINDOWS // diff --git a/Net/src/Net.cpp b/Net/src/Net.cpp index 2aa9c2f2a..520e22d13 100644 --- a/Net/src/Net.cpp +++ b/Net/src/Net.cpp @@ -37,9 +37,6 @@ #include "Poco/Net/Net.h" -#if defined(POCO_OS_FAMILY_WINDOWS) - - #include "Poco/Net/SocketDefs.h" #include "Poco/Net/NetException.h" @@ -50,68 +47,44 @@ namespace Net { void Net_API initializeNetwork() { +#if defined(POCO_OS_FAMILY_WINDOWS) WORD version = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(version, &data) != 0) throw NetException("Failed to initialize network subsystem"); +#endif } void Net_API uninitializeNetwork() { +#if defined(POCO_OS_FAMILY_WINDOWS) WSACleanup(); +#endif } } } // namespace Poco::Net -#if !defined(POCO_NET_NO_WINDOWS_INIT) - #if defined (POCO_DLL) - BOOL APIENTRY DllMain(HANDLE, DWORD reasonForCall, LPVOID) - { - switch(reasonForCall) - { - case DLL_PROCESS_ATTACH: - Poco::Net::initializeNetwork(); - break; - case DLL_PROCESS_DETACH: - Poco::Net::uninitializeNetwork(); - } - return TRUE; - } - #else // POCO_STATIC - struct NetworkInitializer - /// Network initializer for windows statically - /// linked library. - { - NetworkInitializer() - /// Calls Poco::Net::initializeNetwork(); - { - Poco::Net::initializeNetwork(); - } - - ~NetworkInitializer() - /// Calls Poco::Net::uninitializeNetwork(); - { - Poco::Net::uninitializeNetwork(); - } - }; - - const NetworkInitializer pocoNetworkInitializer; - #endif // POCO_DLL/POCO_STATIC - -#endif // POCO_NET_NO_WINDOWS_INIT - - -#else // POCO_OS_FAMILY_WINDOWS - -void Net_API initializeNetwork() +struct NetworkInitializer + /// Network initializer for windows statically + /// linked library. { -} + NetworkInitializer() + /// Calls Poco::Net::initializeNetwork(); + { + Poco::Net::initializeNetwork(); + } -void Net_API uninitializeNetwork() -{ -} + ~NetworkInitializer() + /// Calls Poco::Net::uninitializeNetwork(); + { + Poco::Net::uninitializeNetwork(); + } +}; -#endif // POCO_OS_FAMILY_WINDOWS + +#ifndef POCO_NO_AUTOMATIC_LIB_INIT + const NetworkInitializer pocoNetworkInitializer; +#endif From 6a859abb41bd0d8a381c4c853aa3ca9e832dc1a2 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 9 Feb 2013 22:48:56 -0600 Subject: [PATCH 15/25] gcc Var Date conversion fix --- Data/src/Date.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/src/Date.cpp b/Data/src/Date.cpp index 254ef69ad..718ee85a9 100644 --- a/Data/src/Date.cpp +++ b/Data/src/Date.cpp @@ -145,7 +145,7 @@ Var::operator Date () const if (!_pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(Date) == _pHolder->type()) + if (typeid(Date) == content()->type()) return extract(); else { From 134a2b9a736fe42b805f5d8dc75f5d0e7397cb62 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 9 Feb 2013 22:50:32 -0600 Subject: [PATCH 16/25] gcc Var Date compile fix --- Data/src/Date.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Data/src/Date.cpp b/Data/src/Date.cpp index 718ee85a9..94b831105 100644 --- a/Data/src/Date.cpp +++ b/Data/src/Date.cpp @@ -142,10 +142,12 @@ using Poco::DateTime; template <> Var::operator Date () const { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(Date) == content()->type()) + if (typeid(Date) == pHolder->type()) return extract(); else { From 317fd37d2b44a9e87cd49c5418a9b7212730ee1b Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 9 Feb 2013 22:51:28 -0600 Subject: [PATCH 17/25] another compile fix --- Data/src/Date.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data/src/Date.cpp b/Data/src/Date.cpp index 94b831105..b371e5dfe 100644 --- a/Data/src/Date.cpp +++ b/Data/src/Date.cpp @@ -152,7 +152,7 @@ Var::operator Date () const else { Poco::DateTime result; - _pHolder->convert(result); + pHolder->convert(result); return Date(result); } } From f09e1820cd269abe871d6fbad2058fa285981574 Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 9 Feb 2013 22:53:10 -0600 Subject: [PATCH 18/25] LOB gcc compile fix --- Data/src/DynamicLOB.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Data/src/DynamicLOB.cpp b/Data/src/DynamicLOB.cpp index b99d70825..5b76e4a28 100644 --- a/Data/src/DynamicLOB.cpp +++ b/Data/src/DynamicLOB.cpp @@ -53,15 +53,17 @@ using Poco::Data::BLOB; template <> Var::operator CLOB () const { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(CLOB) == _pHolder->type()) + if (typeid(CLOB) == pHolder->type()) return extract(); else { std::string result; - _pHolder->convert(result); + pHolder->convert(result); return CLOB(result); } } @@ -70,15 +72,17 @@ Var::operator CLOB () const template <> Var::operator BLOB () const { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(BLOB) == _pHolder->type()) + if (typeid(BLOB) == pHolder->type()) return extract(); else { std::string result; - _pHolder->convert(result); + pHolder->convert(result); return BLOB(reinterpret_cast(result.data()), result.size()); } From c7cb7e4498ecafcacf3c694e6da8d4441c7e048f Mon Sep 17 00:00:00 2001 From: aleks-f Date: Sat, 9 Feb 2013 22:54:28 -0600 Subject: [PATCH 19/25] Time gcc compile fix --- Data/src/Time.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Data/src/Time.cpp b/Data/src/Time.cpp index cc57cc697..e9d01082f 100644 --- a/Data/src/Time.cpp +++ b/Data/src/Time.cpp @@ -139,15 +139,17 @@ using Poco::DateTime; template <> Var::operator Time () const { - if (!_pHolder) + VarHolder* pHolder = content(); + + if (!pHolder) throw InvalidAccessException("Can not convert empty value."); - if (typeid(Time) == _pHolder->type()) + if (typeid(Time) == pHolder->type()) return extract