From a50875c9b8d2ab712f21b0ae514b997181ade06e Mon Sep 17 00:00:00 2001
From: "de@itstall.de" <de@itstall.de>
Date: Tue, 11 Feb 2020 11:20:12 +0100
Subject: [PATCH] =?UTF-8?q?Funktionierende=20Version=20mit=20Abh=C3=A4ngig?=
 =?UTF-8?q?keiten?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .gitignore                               |     1 +
 MqttClient.h                             |     2 +-
 Poco/ASCIIEncoding.h                     |    51 +
 Poco/AbstractCache.h                     |   366 +
 Poco/AbstractDelegate.h                  |   110 +
 Poco/AbstractEvent.h                     |   558 +
 Poco/AbstractObserver.h                  |    50 +
 Poco/AbstractPriorityDelegate.h          |    63 +
 Poco/AbstractStrategy.h                  |    77 +
 Poco/AccessExpirationDecorator.h         |    83 +
 Poco/AccessExpireCache.h                 |    63 +
 Poco/AccessExpireLRUCache.h              |    62 +
 Poco/AccessExpireStrategy.h              |    74 +
 Poco/ActiveDispatcher.h                  |   116 +
 Poco/ActiveMethod.h                      |   218 +
 Poco/ActiveResult.h                      |   495 +
 Poco/ActiveRunnable.h                    |   231 +
 Poco/ActiveStarter.h                     |    48 +
 Poco/Activity.h                          |   208 +
 Poco/Alignment.h                         |   246 +
 Poco/Any.h                               |   599 +
 Poco/ArchiveStrategy.h                   |   146 +
 Poco/Array.h                             |   249 +
 Poco/Ascii.h                             |   220 +
 Poco/AsyncChannel.h                      |   100 +
 Poco/AtomicCounter.h                     |   417 +
 Poco/AutoPtr.h                           |   386 +
 Poco/AutoReleasePool.h                   |    86 +
 Poco/Base32Decoder.h                     |   104 +
 Poco/Base32Encoder.h                     |   110 +
 Poco/Base64Decoder.h                     |   108 +
 Poco/Base64Encoder.h                     |   138 +
 Poco/BasicEvent.h                        |    60 +
 Poco/BinaryReader.h                      |   265 +
 Poco/BinaryWriter.h                      |   269 +
 Poco/Buffer.h                            |   329 +
 Poco/BufferAllocator.h                   |    52 +
 Poco/BufferedBidirectionalStreamBuf.h    |   181 +
 Poco/BufferedStreamBuf.h                 |   173 +
 Poco/Bugcheck.h                          |   206 +
 Poco/ByteOrder.h                         |   239 +
 Poco/Channel.h                           |    78 +
 Poco/Checksum.h                          |   108 +
 Poco/ClassLibrary.h                      |   101 +
 Poco/ClassLoader.h                       |   365 +
 Poco/Clock.h                             |   238 +
 Poco/Condition.h                         |   137 +
 Poco/Config.h                            |   207 +
 Poco/Configurable.h                      |    70 +
 Poco/ConsoleChannel.h                    |   187 +
 Poco/CountingStream.h                    |   237 +
 Poco/CppParser/Attributes.h              |   123 +
 Poco/CppParser/AttributesParser.h        |   114 +
 Poco/CppParser/BuiltIn.h                 |    47 +
 Poco/CppParser/CppParser.h               |    58 +
 Poco/CppParser/CppToken.h                |   281 +
 Poco/CppParser/Decl.h                    |    62 +
 Poco/CppParser/Enum.h                    |    77 +
 Poco/CppParser/EnumValue.h               |    66 +
 Poco/CppParser/Function.h                |   166 +
 Poco/CppParser/NameSpace.h               |   138 +
 Poco/CppParser/Parameter.h               |   142 +
 Poco/CppParser/Parser.h                  |   127 +
 Poco/CppParser/Struct.h                  |   205 +
 Poco/CppParser/Symbol.h                  |   266 +
 Poco/CppParser/Tokenizer.h               |    44 +
 Poco/CppParser/TypeDef.h                 |    49 +
 Poco/CppParser/Utility.h                 |    85 +
 Poco/CppParser/Variable.h                |    92 +
 Poco/Crypto/Cipher.h                     |   138 +
 Poco/Crypto/CipherFactory.h              |    75 +
 Poco/Crypto/CipherImpl.h                 |    69 +
 Poco/Crypto/CipherKey.h                  |   201 +
 Poco/Crypto/CipherKeyImpl.h              |   168 +
 Poco/Crypto/Crypto.h                     |   185 +
 Poco/Crypto/CryptoException.h            |    56 +
 Poco/Crypto/CryptoStream.h               |   192 +
 Poco/Crypto/CryptoTransform.h            |    87 +
 Poco/Crypto/DigestEngine.h               |    80 +
 Poco/Crypto/ECDSADigestEngine.h          |   101 +
 Poco/Crypto/ECKey.h                      |   136 +
 Poco/Crypto/ECKeyImpl.h                  |   174 +
 Poco/Crypto/EVPPKey.h                    |   354 +
 Poco/Crypto/KeyPair.h                    |   133 +
 Poco/Crypto/KeyPairImpl.h                |   107 +
 Poco/Crypto/OpenSSLInitializer.h         |   115 +
 Poco/Crypto/PKCS12Container.h            |   159 +
 Poco/Crypto/RSACipherImpl.h              |    77 +
 Poco/Crypto/RSADigestEngine.h            |   111 +
 Poco/Crypto/RSAKey.h                     |   125 +
 Poco/Crypto/RSAKeyImpl.h                 |   141 +
 Poco/Crypto/X509Certificate.h            |   245 +
 Poco/DOM/AbstractContainerNode.h         |    78 +
 Poco/DOM/AbstractNode.h                  |   125 +
 Poco/DOM/Attr.h                          |   180 +
 Poco/DOM/AttrMap.h                       |    65 +
 Poco/DOM/AutoPtr.h                       |    35 +
 Poco/DOM/CDATASection.h                  |    84 +
 Poco/DOM/CharacterData.h                 |   123 +
 Poco/DOM/ChildNodesList.h                |    55 +
 Poco/DOM/Comment.h                       |    58 +
 Poco/DOM/DOMBuilder.h                    |   112 +
 Poco/DOM/DOMException.h                  |   112 +
 Poco/DOM/DOMImplementation.h             |    82 +
 Poco/DOM/DOMObject.h                     |   103 +
 Poco/DOM/DOMParser.h                     |   114 +
 Poco/DOM/DOMSerializer.h                 |   122 +
 Poco/DOM/DOMWriter.h                     |   127 +
 Poco/DOM/DTDMap.h                        |    67 +
 Poco/DOM/Document.h                      |   285 +
 Poco/DOM/DocumentEvent.h                 |    65 +
 Poco/DOM/DocumentFragment.h              |    84 +
 Poco/DOM/DocumentType.h                  |   125 +
 Poco/DOM/Element.h                       |   219 +
 Poco/DOM/ElementsByTagNameList.h         |    86 +
 Poco/DOM/Entity.h                        |   126 +
 Poco/DOM/EntityReference.h               |    73 +
 Poco/DOM/Event.h                         |   209 +
 Poco/DOM/EventDispatcher.h               |    97 +
 Poco/DOM/EventException.h                |    81 +
 Poco/DOM/EventListener.h                 |    57 +
 Poco/DOM/EventTarget.h                   |    76 +
 Poco/DOM/MutationEvent.h                 |   143 +
 Poco/DOM/NamedNodeMap.h                  |    93 +
 Poco/DOM/Node.h                          |   285 +
 Poco/DOM/NodeAppender.h                  |    81 +
 Poco/DOM/NodeFilter.h                    |   146 +
 Poco/DOM/NodeIterator.h                  |   167 +
 Poco/DOM/NodeList.h                      |    61 +
 Poco/DOM/Notation.h                      |    93 +
 Poco/DOM/ProcessingInstruction.h         |    99 +
 Poco/DOM/Text.h                          |    79 +
 Poco/DOM/TreeWalker.h                    |   211 +
 Poco/Data/AbstractBinder.h               |   373 +
 Poco/Data/AbstractBinding.h              |   144 +
 Poco/Data/AbstractExtraction.h           |   278 +
 Poco/Data/AbstractExtractor.h            |   351 +
 Poco/Data/AbstractPreparation.h          |    71 +
 Poco/Data/AbstractPreparator.h           |   388 +
 Poco/Data/AbstractSessionImpl.h          |   315 +
 Poco/Data/ArchiveStrategy.h              |   222 +
 Poco/Data/AutoTransaction.h              |    35 +
 Poco/Data/Binding.h                      |  1496 ++
 Poco/Data/Bulk.h                         |    96 +
 Poco/Data/BulkBinding.h                  |   148 +
 Poco/Data/BulkExtraction.h               |   276 +
 Poco/Data/Column.h                       |   490 +
 Poco/Data/Connector.h                    |    56 +
 Poco/Data/Constants.h                    |    36 +
 Poco/Data/Data.h                         |    62 +
 Poco/Data/DataException.h                |    50 +
 Poco/Data/Date.h                         |   225 +
 Poco/Data/DynamicDateTime.h              |    47 +
 Poco/Data/DynamicLOB.h                   |    45 +
 Poco/Data/Extraction.h                   |   869 +
 Poco/Data/LOB.h                          |   309 +
 Poco/Data/LOBStream.h                    |   150 +
 Poco/Data/Limit.h                        |   113 +
 Poco/Data/MetaColumn.h                   |   188 +
 Poco/Data/ODBC/Binder.h                  |  1516 ++
 Poco/Data/ODBC/ConnectionHandle.h        |    96 +
 Poco/Data/ODBC/Connector.h               |    70 +
 Poco/Data/ODBC/Diagnostics.h             |   239 +
 Poco/Data/ODBC/EnvironmentHandle.h       |    94 +
 Poco/Data/ODBC/Error.h                   |   124 +
 Poco/Data/ODBC/Extractor.h               |   728 +
 Poco/Data/ODBC/Handle.h                  |   116 +
 Poco/Data/ODBC/ODBC.h                    |    69 +
 Poco/Data/ODBC/ODBCException.h           |   150 +
 Poco/Data/ODBC/ODBCMetaColumn.h          |    92 +
 Poco/Data/ODBC/ODBCStatementImpl.h       |   206 +
 Poco/Data/ODBC/Parameter.h               |   111 +
 Poco/Data/ODBC/Preparator.h              |  1271 ++
 Poco/Data/ODBC/SessionImpl.h             |   290 +
 Poco/Data/ODBC/TypeInfo.h                |   117 +
 Poco/Data/ODBC/Unicode.h                 |   985 +
 Poco/Data/ODBC/Unicode_UNIXODBC.h        |    51 +
 Poco/Data/ODBC/Unicode_WIN32.h           |    57 +
 Poco/Data/ODBC/Utility.h                 |   207 +
 Poco/Data/PooledSessionHolder.h          |    99 +
 Poco/Data/PooledSessionImpl.h            |    97 +
 Poco/Data/Position.h                     |    75 +
 Poco/Data/Preparation.h                  |   161 +
 Poco/Data/Range.h                        |   104 +
 Poco/Data/RecordSet.h                    |   653 +
 Poco/Data/Row.h                          |   312 +
 Poco/Data/RowFilter.h                    |   276 +
 Poco/Data/RowFormatter.h                 |   231 +
 Poco/Data/RowIterator.h                  |   150 +
 Poco/Data/SQLChannel.h                   |   217 +
 Poco/Data/SQLite/Binder.h                |   220 +
 Poco/Data/SQLite/Connector.h             |    79 +
 Poco/Data/SQLite/Extractor.h             |   313 +
 Poco/Data/SQLite/Notifier.h              |   195 +
 Poco/Data/SQLite/SQLite.h                |    62 +
 Poco/Data/SQLite/SQLiteException.h       |    60 +
 Poco/Data/SQLite/SQLiteStatementImpl.h   |   155 +
 Poco/Data/SQLite/SessionImpl.h           |   168 +
 Poco/Data/SQLite/Utility.h               |   240 +
 Poco/Data/Session.h                      |   494 +
 Poco/Data/SessionFactory.h               |    99 +
 Poco/Data/SessionImpl.h                  |   221 +
 Poco/Data/SessionPool.h                  |   233 +
 Poco/Data/SessionPoolContainer.h         |   114 +
 Poco/Data/SimpleRowFormatter.h           |   122 +
 Poco/Data/Statement.h                    |   822 +
 Poco/Data/StatementCreator.h             |    73 +
 Poco/Data/StatementImpl.h                |   632 +
 Poco/Data/Time.h                         |   229 +
 Poco/Data/Transaction.h                  |   194 +
 Poco/Data/TypeHandler.h                  |  2090 ++
 Poco/DateTime.h                          |   415 +
 Poco/DateTimeFormat.h                    |   109 +
 Poco/DateTimeFormatter.h                 |   215 +
 Poco/DateTimeParser.h                    |   116 +
 Poco/Debugger.h                          |    70 +
 Poco/DefaultStrategy.h                   |   226 +
 Poco/DeflatingStream.h                   |   201 +
 Poco/Delegate.h                          |   452 +
 Poco/DigestEngine.h                      |   111 +
 Poco/DigestStream.h                      |   100 +
 Poco/DirectoryIterator.h                 |   153 +
 Poco/DirectoryIteratorStrategy.h         |    92 +
 Poco/DirectoryIterator_UNIX.h            |    72 +
 Poco/DirectoryIterator_WIN32.h           |    73 +
 Poco/DirectoryIterator_WIN32U.h          |    73 +
 Poco/DirectoryWatcher.h                  |   232 +
 Poco/DoubleByteEncoding.h                |   122 +
 Poco/Dynamic/Pair.h                      |   412 +
 Poco/Dynamic/Struct.h                    |   567 +
 Poco/Dynamic/Var.h                       |  2228 ++
 Poco/Dynamic/VarHolder.h                 |  4186 ++++
 Poco/Dynamic/VarIterator.h               |   150 +
 Poco/DynamicAny.h                        |    24 +
 Poco/DynamicAnyHolder.h                  |    24 +
 Poco/DynamicFactory.h                    |   141 +
 Poco/DynamicStruct.h                     |    24 +
 Poco/Encodings.h                         |    73 +
 Poco/Environment.h                       |   123 +
 Poco/Environment_UNIX.h                  |    56 +
 Poco/Environment_VX.h                    |    56 +
 Poco/Environment_WIN32.h                 |    48 +
 Poco/Environment_WIN32U.h                |    48 +
 Poco/Environment_WINCE.h                 |    59 +
 Poco/Error.h                             |    52 +
 Poco/ErrorHandler.h                      |   120 +
 Poco/Event.h                             |   123 +
 Poco/EventArgs.h                         |    45 +
 Poco/EventChannel.h                      |    54 +
 Poco/EventLogChannel.h                   |   105 +
 Poco/Event_POSIX.h                       |    77 +
 Poco/Event_VX.h                          |    49 +
 Poco/Event_WIN32.h                       |    68 +
 Poco/Exception.h                         |   261 +
 Poco/ExpirationDecorator.h               |    92 +
 Poco/Expire.h                            |   194 +
 Poco/ExpireCache.h                       |    65 +
 Poco/ExpireLRUCache.h                    |    62 +
 Poco/ExpireStrategy.h                    |   132 +
 Poco/FIFOBuffer.h                        |   556 +
 Poco/FIFOBufferStream.h                  |   154 +
 Poco/FIFOEvent.h                         |    63 +
 Poco/FIFOStrategy.h                      |    59 +
 Poco/FPEnvironment.h                     |   207 +
 Poco/FPEnvironment_C99.h                 |   125 +
 Poco/FPEnvironment_DEC.h                 |    89 +
 Poco/FPEnvironment_DUMMY.h               |   125 +
 Poco/FPEnvironment_QNX.h                 |   133 +
 Poco/FPEnvironment_SUN.h                 |    74 +
 Poco/FPEnvironment_WIN32.h               |   150 +
 Poco/File.h                              |   315 +
 Poco/FileChannel.h                       |   270 +
 Poco/FileStream.h                        |   176 +
 Poco/FileStreamFactory.h                 |    61 +
 Poco/FileStream_POSIX.h                  |    72 +
 Poco/FileStream_WIN32.h                  |    71 +
 Poco/File_UNIX.h                         |    86 +
 Poco/File_VX.h                           |    84 +
 Poco/File_WIN32.h                        |    87 +
 Poco/File_WIN32U.h                       |    91 +
 Poco/File_WINCE.h                        |    90 +
 Poco/Format.h                            |   138 +
 Poco/Formatter.h                         |    74 +
 Poco/FormattingChannel.h                 |    96 +
 Poco/Foundation.h                        |   168 +
 Poco/FunctionDelegate.h                  |   438 +
 Poco/FunctionPriorityDelegate.h          |   450 +
 Poco/Glob.h                              |   152 +
 Poco/HMACEngine.h                        |   146 +
 Poco/Hash.h                              |   105 +
 Poco/HashFunction.h                      |    57 +
 Poco/HashMap.h                           |   228 +
 Poco/HashSet.h                           |   177 +
 Poco/HashStatistic.h                     |   126 +
 Poco/HashTable.h                         |   369 +
 Poco/HexBinaryDecoder.h                  |    94 +
 Poco/HexBinaryEncoder.h                  |   117 +
 Poco/ISO8859_10Encoding.h                |    48 +
 Poco/ISO8859_11Encoding.h                |    48 +
 Poco/ISO8859_13Encoding.h                |    48 +
 Poco/ISO8859_14Encoding.h                |    48 +
 Poco/ISO8859_16Encoding.h                |    48 +
 Poco/ISO8859_3Encoding.h                 |    48 +
 Poco/ISO8859_4Encoding.h                 |    48 +
 Poco/ISO8859_5Encoding.h                 |    48 +
 Poco/ISO8859_6Encoding.h                 |    48 +
 Poco/ISO8859_7Encoding.h                 |    48 +
 Poco/ISO8859_8Encoding.h                 |    48 +
 Poco/ISO8859_9Encoding.h                 |    48 +
 Poco/InflatingStream.h                   |   211 +
 Poco/Instantiator.h                      |    82 +
 Poco/JSON/Array.h                        |   566 +
 Poco/JSON/Handler.h                      |   106 +
 Poco/JSON/JSON.h                         |    62 +
 Poco/JSON/JSONException.h                |    35 +
 Poco/JSON/Object.h                       |   715 +
 Poco/JSON/ParseHandler.h                 |   169 +
 Poco/JSON/Parser.h                       |   203 +
 Poco/JSON/ParserImpl.h                   |   194 +
 Poco/JSON/PrintHandler.h                 |   139 +
 Poco/JSON/Query.h                        |   125 +
 Poco/JSON/Stringifier.h                  |    73 +
 Poco/JSON/Template.h                     |   151 +
 Poco/JSON/TemplateCache.h                |   105 +
 Poco/JSONString.h                        |    93 +
 Poco/KeyValueArgs.h                      |    73 +
 Poco/LRUCache.h                          |    56 +
 Poco/LRUStrategy.h                       |   140 +
 Poco/Latin1Encoding.h                    |    51 +
 Poco/Latin2Encoding.h                    |    54 +
 Poco/Latin9Encoding.h                    |    54 +
 Poco/LineEndingConverter.h               |   181 +
 Poco/LinearHashTable.h                   |   503 +
 Poco/ListMap.h                           |   246 +
 Poco/LocalDateTime.h                     |   388 +
 Poco/LogFile.h                           |    93 +
 Poco/LogFile_STD.h                       |    52 +
 Poco/LogFile_WIN32.h                     |    54 +
 Poco/LogFile_WIN32U.h                    |    54 +
 Poco/LogStream.h                         |   185 +
 Poco/Logger.h                            |  1318 ++
 Poco/LoggingFactory.h                    |    92 +
 Poco/LoggingRegistry.h                   |    99 +
 Poco/MD4Engine.h                         |    95 +
 Poco/MD5Engine.h                         |    95 +
 Poco/Manifest.h                          |   180 +
 Poco/MemoryPool.h                        |   115 +
 Poco/MemoryStream.h                      |   246 +
 Poco/Message.h                           |   271 +
 Poco/MetaObject.h                        |   201 +
 Poco/MetaProgramming.h                   |   144 +
 Poco/MongoDB/Array.h                     |   110 +
 Poco/MongoDB/BSONReader.h                |    84 +
 Poco/MongoDB/BSONWriter.h                |    74 +
 Poco/MongoDB/Binary.h                    |   155 +
 Poco/MongoDB/Connection.h                |   164 +
 Poco/MongoDB/Cursor.h                    |    74 +
 Poco/MongoDB/Database.h                  |   162 +
 Poco/MongoDB/DeleteRequest.h             |   113 +
 Poco/MongoDB/Document.h                  |   277 +
 Poco/MongoDB/Element.h                   |   403 +
 Poco/MongoDB/GetMoreRequest.h            |    89 +
 Poco/MongoDB/InsertRequest.h             |    97 +
 Poco/MongoDB/JavaScriptCode.h            |   105 +
 Poco/MongoDB/KillCursorsRequest.h        |    62 +
 Poco/MongoDB/Message.h                   |    73 +
 Poco/MongoDB/MessageHeader.h             |   130 +
 Poco/MongoDB/MongoDB.h                   |    64 +
 Poco/MongoDB/ObjectId.h                  |   147 +
 Poco/MongoDB/PoolableConnectionFactory.h |   128 +
 Poco/MongoDB/QueryRequest.h              |   187 +
 Poco/MongoDB/RegularExpression.h         |   129 +
 Poco/MongoDB/ReplicaSet.h                |    58 +
 Poco/MongoDB/RequestMessage.h            |    51 +
 Poco/MongoDB/ResponseMessage.h           |   108 +
 Poco/MongoDB/UpdateRequest.h             |   114 +
 Poco/Mutex.h                             |   270 +
 Poco/Mutex_POSIX.h                       |    86 +
 Poco/Mutex_VX.h                          |    80 +
 Poco/Mutex_WIN32.h                       |    85 +
 Poco/Mutex_WINCE.h                       |    50 +
 Poco/NObserver.h                         |   126 +
 Poco/NamedEvent.h                        |    96 +
 Poco/NamedEvent_Android.h                |    40 +
 Poco/NamedEvent_UNIX.h                   |    53 +
 Poco/NamedEvent_WIN32.h                  |    45 +
 Poco/NamedEvent_WIN32U.h                 |    46 +
 Poco/NamedMutex.h                        |   110 +
 Poco/NamedMutex_Android.h                |    41 +
 Poco/NamedMutex_UNIX.h                   |    57 +
 Poco/NamedMutex_WIN32.h                  |    46 +
 Poco/NamedMutex_WIN32U.h                 |    47 +
 Poco/NamedTuple.h                        |  4462 ++++
 Poco/NestedDiagnosticContext.h           |   181 +
 Poco/Net/AbstractHTTPRequestHandler.h    |   136 +
 Poco/Net/AcceptCertificateHandler.h      |    52 +
 Poco/Net/CertificateHandlerFactory.h     |    93 +
 Poco/Net/CertificateHandlerFactoryMgr.h  |    64 +
 Poco/Net/ConsoleCertificateHandler.h     |    50 +
 Poco/Net/Context.h                       |   405 +
 Poco/Net/DNS.h                           |   199 +
 Poco/Net/DatagramSocket.h                |   168 +
 Poco/Net/DatagramSocketImpl.h            |    55 +
 Poco/Net/DialogSocket.h                  |   211 +
 Poco/Net/FTPClientSession.h              |   403 +
 Poco/Net/FTPStreamFactory.h              |   120 +
 Poco/Net/FilePartSource.h                |    77 +
 Poco/Net/HTMLForm.h                      |   272 +
 Poco/Net/HTTPAuthenticationParams.h      |   103 +
 Poco/Net/HTTPBasicCredentials.h          |   123 +
 Poco/Net/HTTPBasicStreamBuf.h            |    36 +
 Poco/Net/HTTPBufferAllocator.h           |    50 +
 Poco/Net/HTTPChunkedStream.h             |   105 +
 Poco/Net/HTTPClientSession.h             |   391 +
 Poco/Net/HTTPCookie.h                    |   272 +
 Poco/Net/HTTPCredentials.h               |   206 +
 Poco/Net/HTTPDigestCredentials.h         |   186 +
 Poco/Net/HTTPFixedLengthStream.h         |   110 +
 Poco/Net/HTTPHeaderStream.h              |   102 +
 Poco/Net/HTTPIOStream.h                  |    88 +
 Poco/Net/HTTPMessage.h                   |   185 +
 Poco/Net/HTTPRequest.h                   |   200 +
 Poco/Net/HTTPRequestHandler.h            |    67 +
 Poco/Net/HTTPRequestHandlerFactory.h     |    78 +
 Poco/Net/HTTPResponse.h                  |   295 +
 Poco/Net/HTTPSClientSession.h            |   165 +
 Poco/Net/HTTPSSessionInstantiator.h      |    65 +
 Poco/Net/HTTPSStreamFactory.h            |    83 +
 Poco/Net/HTTPServer.h                    |   103 +
 Poco/Net/HTTPServerConnection.h          |    65 +
 Poco/Net/HTTPServerConnectionFactory.h   |    55 +
 Poco/Net/HTTPServerParams.h              |   154 +
 Poco/Net/HTTPServerRequest.h             |    80 +
 Poco/Net/HTTPServerRequestImpl.h         |   142 +
 Poco/Net/HTTPServerResponse.h            |   116 +
 Poco/Net/HTTPServerResponseImpl.h        |   139 +
 Poco/Net/HTTPServerSession.h             |    76 +
 Poco/Net/HTTPSession.h                   |   251 +
 Poco/Net/HTTPSessionFactory.h            |   155 +
 Poco/Net/HTTPSessionInstantiator.h       |   117 +
 Poco/Net/HTTPStream.h                    |   103 +
 Poco/Net/HTTPStreamFactory.h             |    92 +
 Poco/Net/HostEntry.h                     |   115 +
 Poco/Net/ICMPClient.h                    |    97 +
 Poco/Net/ICMPEventArgs.h                 |   163 +
 Poco/Net/ICMPPacket.h                    |    89 +
 Poco/Net/ICMPPacketImpl.h                |   141 +
 Poco/Net/ICMPSocket.h                    |    91 +
 Poco/Net/ICMPSocketImpl.h                |    94 +
 Poco/Net/ICMPv4PacketImpl.h              |   173 +
 Poco/Net/IPAddress.h                     |   450 +
 Poco/Net/IPAddressImpl.h                 |   179 +
 Poco/Net/InvalidCertificateHandler.h     |    80 +
 Poco/Net/KeyConsoleHandler.h             |    47 +
 Poco/Net/KeyFileHandler.h                |    51 +
 Poco/Net/MailMessage.h                   |   314 +
 Poco/Net/MailRecipient.h                 |   120 +
 Poco/Net/MailStream.h                    |   146 +
 Poco/Net/MediaType.h                     |   169 +
 Poco/Net/MessageHeader.h                 |   169 +
 Poco/Net/MulticastSocket.h               |   135 +
 Poco/Net/MultipartReader.h               |   160 +
 Poco/Net/MultipartWriter.h               |   109 +
 Poco/Net/NTPClient.h                     |    64 +
 Poco/Net/NTPEventArgs.h                  |    84 +
 Poco/Net/NTPPacket.h                     |   207 +
 Poco/Net/NameValueCollection.h           |   126 +
 Poco/Net/Net.h                           |   122 +
 Poco/Net/NetException.h                  |    60 +
 Poco/Net/NetSSL.h                        |    94 +
 Poco/Net/NetworkInterface.h              |   352 +
 Poco/Net/NullPartHandler.h               |    47 +
 Poco/Net/OAuth10Credentials.h            |   274 +
 Poco/Net/OAuth20Credentials.h            |   132 +
 Poco/Net/POP3ClientSession.h             |   185 +
 Poco/Net/ParallelSocketAcceptor.h        |   233 +
 Poco/Net/ParallelSocketReactor.h         |    90 +
 Poco/Net/PartHandler.h                   |    68 +
 Poco/Net/PartSource.h                    |   110 +
 Poco/Net/PartStore.h                     |   106 +
 Poco/Net/PollSet.h                       |    86 +
 Poco/Net/PrivateKeyFactory.h             |    95 +
 Poco/Net/PrivateKeyFactoryMgr.h          |    64 +
 Poco/Net/PrivateKeyPassphraseHandler.h   |    84 +
 Poco/Net/QuotedPrintableDecoder.h        |    86 +
 Poco/Net/QuotedPrintableEncoder.h        |    85 +
 Poco/Net/RawSocket.h                     |   161 +
 Poco/Net/RawSocketImpl.h                 |    56 +
 Poco/Net/RejectCertificateHandler.h      |    48 +
 Poco/Net/RemoteSyslogChannel.h           |   158 +
 Poco/Net/RemoteSyslogListener.h          |   121 +
 Poco/Net/SMTPChannel.h                   |   108 +
 Poco/Net/SMTPClientSession.h             |   234 +
 Poco/Net/SSLException.h                  |    39 +
 Poco/Net/SSLManager.h                    |   390 +
 Poco/Net/SecureSMTPClientSession.h       |    96 +
 Poco/Net/SecureServerSocket.h            |   136 +
 Poco/Net/SecureServerSocketImpl.h        |   146 +
 Poco/Net/SecureSocketImpl.h              |   263 +
 Poco/Net/SecureStreamSocket.h            |   272 +
 Poco/Net/SecureStreamSocketImpl.h        |   299 +
 Poco/Net/ServerSocket.h                  |   230 +
 Poco/Net/ServerSocketImpl.h              |    45 +
 Poco/Net/Session.h                       |    79 +
 Poco/Net/Socket.h                        |   631 +
 Poco/Net/SocketAcceptor.h                |   196 +
 Poco/Net/SocketAddress.h                 |   301 +
 Poco/Net/SocketAddressImpl.h             |   258 +
 Poco/Net/SocketConnector.h               |   212 +
 Poco/Net/SocketDefs.h                    |   378 +
 Poco/Net/SocketImpl.h                    |   500 +
 Poco/Net/SocketNotification.h            |   153 +
 Poco/Net/SocketNotifier.h                |   110 +
 Poco/Net/SocketReactor.h                 |   235 +
 Poco/Net/SocketStream.h                  |   177 +
 Poco/Net/StreamSocket.h                  |   180 +
 Poco/Net/StreamSocketImpl.h              |    59 +
 Poco/Net/StringPartSource.h              |    71 +
 Poco/Net/TCPServer.h                     |   258 +
 Poco/Net/TCPServerConnection.h           |    86 +
 Poco/Net/TCPServerConnectionFactory.h    |    89 +
 Poco/Net/TCPServerDispatcher.h           |   130 +
 Poco/Net/TCPServerParams.h               |   137 +
 Poco/Net/Utility.h                       |    52 +
 Poco/Net/VerificationErrorArgs.h         |   108 +
 Poco/Net/WebSocket.h                     |   297 +
 Poco/Net/WebSocketImpl.h                 |   142 +
 Poco/Net/X509Certificate.h               |   102 +
 Poco/Notification.h                      |    55 +
 Poco/NotificationCenter.h                |   139 +
 Poco/NotificationQueue.h                 |   155 +
 Poco/NotificationStrategy.h              |   112 +
 Poco/NullChannel.h                       |    55 +
 Poco/NullStream.h                        |    90 +
 Poco/Nullable.h                          |   323 +
 Poco/NumberFormatter.h                   |   907 +
 Poco/NumberParser.h                      |   156 +
 Poco/NumericString.h                     |   560 +
 Poco/ObjectPool.h                        |   332 +
 Poco/Observer.h                          |   124 +
 Poco/Optional.h                          |   161 +
 Poco/PBKDF2Engine.h                      |   149 +
 Poco/Path.h                              |   501 +
 Poco/Path_UNIX.h                         |    48 +
 Poco/Path_WIN32.h                        |    49 +
 Poco/Path_WIN32U.h                       |    54 +
 Poco/Path_WINCE.h                        |    54 +
 Poco/PatternFormatter.h                  |   148 +
 Poco/Pipe.h                              |   142 +
 Poco/PipeImpl.h                          |    37 +
 Poco/PipeImpl_DUMMY.h                    |    49 +
 Poco/PipeImpl_POSIX.h                    |    53 +
 Poco/PipeImpl_WIN32.h                    |    54 +
 Poco/PipeStream.h                        |   120 +
 Poco/Platform.h                          |   284 +
 Poco/Platform_POSIX.h                    |    53 +
 Poco/Platform_VX.h                       |    29 +
 Poco/Platform_WIN32.h                    |   216 +
 Poco/Poco.h                              |    24 +
 Poco/PriorityDelegate.h                  |   464 +
 Poco/PriorityEvent.h                     |    61 +
 Poco/PriorityExpire.h                    |   195 +
 Poco/PriorityNotificationQueue.h         |   158 +
 Poco/PriorityStrategy.h                  |   230 +
 Poco/Process.h                           |   266 +
 Poco/Process_UNIX.h                      |    86 +
 Poco/Process_VX.h                        |    78 +
 Poco/Process_WIN32.h                     |    83 +
 Poco/Process_WIN32U.h                    |    83 +
 Poco/Process_WINCE.h                     |    83 +
 Poco/PurgeStrategy.h                     |    97 +
 Poco/RWLock.h                            |   203 +
 Poco/RWLock_Android.h                    |    97 +
 Poco/RWLock_POSIX.h                      |    99 +
 Poco/RWLock_VX.h                         |    92 +
 Poco/RWLock_WIN32.h                      |    57 +
 Poco/RWLock_WINCE.h                      |    61 +
 Poco/Random.h                            |   165 +
 Poco/RandomStream.h                      |    73 +
 Poco/RecursiveDirectoryIterator.h        |   254 +
 Poco/RecursiveDirectoryIteratorImpl.h    |   111 +
 Poco/Redis/Array.h                       |   322 +
 Poco/Redis/AsyncReader.h                 |    98 +
 Poco/Redis/Client.h                      |   239 +
 Poco/Redis/Command.h                     |   279 +
 Poco/Redis/Error.h                       |    91 +
 Poco/Redis/Exception.h                   |    36 +
 Poco/Redis/PoolableConnectionFactory.h   |   114 +
 Poco/Redis/Redis.h                       |    62 +
 Poco/Redis/RedisEventArgs.h              |    99 +
 Poco/Redis/RedisStream.h                 |   114 +
 Poco/Redis/Type.h                        |   293 +
 Poco/RefCountedObject.h                  |    94 +
 Poco/RegularExpression.h                 |   247 +
 Poco/RotateStrategy.h                    |   165 +
 Poco/Runnable.h                          |    45 +
 Poco/RunnableAdapter.h                   |    78 +
 Poco/SAX/Attributes.h                    |   120 +
 Poco/SAX/AttributesImpl.h                |   296 +
 Poco/SAX/ContentHandler.h                |   240 +
 Poco/SAX/DTDHandler.h                    |    86 +
 Poco/SAX/DeclHandler.h                   |    91 +
 Poco/SAX/DefaultHandler.h                |    83 +
 Poco/SAX/EntityResolver.h                |    86 +
 Poco/SAX/EntityResolverImpl.h            |    78 +
 Poco/SAX/ErrorHandler.h                  |    92 +
 Poco/SAX/InputSource.h                   |   169 +
 Poco/SAX/LexicalHandler.h                |   125 +
 Poco/SAX/Locator.h                       |   103 +
 Poco/SAX/LocatorImpl.h                   |    88 +
 Poco/SAX/NamespaceSupport.h              |   195 +
 Poco/SAX/SAXException.h                  |   176 +
 Poco/SAX/SAXParser.h                     |   103 +
 Poco/SAX/WhitespaceFilter.h              |    81 +
 Poco/SAX/XMLFilter.h                     |    61 +
 Poco/SAX/XMLFilterImpl.h                 |   132 +
 Poco/SAX/XMLReader.h                     |   205 +
 Poco/SHA1Engine.h                        |    81 +
 Poco/ScopedLock.h                        |   121 +
 Poco/ScopedUnlock.h                      |    64 +
 Poco/Semaphore.h                         |   137 +
 Poco/Semaphore_POSIX.h                   |    75 +
 Poco/Semaphore_VX.h                      |    56 +
 Poco/Semaphore_WIN32.h                   |    58 +
 Poco/SevenZip/Archive.h                  |   119 +
 Poco/SevenZip/ArchiveEntry.h             |   164 +
 Poco/SevenZip/SevenZip.h                 |    62 +
 Poco/SharedLibrary.h                     |   134 +
 Poco/SharedLibrary_HPUX.h                |    51 +
 Poco/SharedLibrary_UNIX.h                |    56 +
 Poco/SharedLibrary_VX.h                  |    51 +
 Poco/SharedLibrary_WIN32.h               |    50 +
 Poco/SharedLibrary_WIN32U.h              |    50 +
 Poco/SharedMemory.h                      |   113 +
 Poco/SharedMemory_DUMMY.h                |    88 +
 Poco/SharedMemory_POSIX.h                |   107 +
 Poco/SharedMemory_WIN32.h                |   103 +
 Poco/SharedPtr.h                         |   448 +
 Poco/SignalHandler.h                     |   129 +
 Poco/SimpleFileChannel.h                 |   150 +
 Poco/SimpleHashTable.h                   |   398 +
 Poco/SingletonHolder.h                   |    77 +
 Poco/SortedDirectoryIterator.h           |    70 +
 Poco/SplitterChannel.h                   |    77 +
 Poco/Stopwatch.h                         |   108 +
 Poco/StrategyCollection.h                |   133 +
 Poco/StreamChannel.h                     |    59 +
 Poco/StreamConverter.h                   |   128 +
 Poco/StreamCopier.h                      |    85 +
 Poco/StreamTokenizer.h                   |    97 +
 Poco/StreamUtil.h                        |    92 +
 Poco/String.h                            |   706 +
 Poco/StringTokenizer.h                   |   135 +
 Poco/SynchronizedObject.h                |   131 +
 Poco/SyslogChannel.h                     |   109 +
 Poco/Task.h                              |   189 +
 Poco/TaskManager.h                       |   137 +
 Poco/TaskNotification.h                  |   170 +
 Poco/TeeStream.h                         |   132 +
 Poco/TemporaryFile.h                     |    84 +
 Poco/TextBufferIterator.h                |   145 +
 Poco/TextConverter.h                     |    93 +
 Poco/TextEncoding.h                      |   185 +
 Poco/TextIterator.h                      |   141 +
 Poco/Thread.h                            |   367 +
 Poco/ThreadLocal.h                       |   157 +
 Poco/ThreadPool.h                        |   208 +
 Poco/ThreadTarget.h                      |    87 +
 Poco/Thread_POSIX.h                      |   198 +
 Poco/Thread_VX.h                         |   169 +
 Poco/Thread_WIN32.h                      |   183 +
 Poco/Thread_WINCE.h                      |   179 +
 Poco/TimedNotificationQueue.h            |   143 +
 Poco/Timer.h                             |   229 +
 Poco/Timespan.h                          |   303 +
 Poco/Timestamp.h                         |   277 +
 Poco/Timezone.h                          |    67 +
 Poco/Token.h                             |   172 +
 Poco/Tuple.h                             |  1747 ++
 Poco/TypeList.h                          |   483 +
 Poco/Types.h                             |   201 +
 Poco/URI.h                               |   406 +
 Poco/URIStreamFactory.h                  |    97 +
 Poco/URIStreamOpener.h                   |   135 +
 Poco/UTF16Encoding.h                     |    85 +
 Poco/UTF32Encoding.h                     |    82 +
 Poco/UTF8Encoding.h                      |    61 +
 Poco/UTF8String.h                        |    83 +
 Poco/UTFString.h                         |   305 +
 Poco/UUID.h                              |   219 +
 Poco/UUIDGenerator.h                     |   104 +
 Poco/UnWindows.h                         |   142 +
 Poco/UnbufferedStreamBuf.h               |   179 +
 Poco/Unicode.h                           |   327 +
 Poco/UnicodeConverter.h                  |   141 +
 Poco/UniqueAccessExpireCache.h           |    73 +
 Poco/UniqueAccessExpireLRUCache.h        |    71 +
 Poco/UniqueAccessExpireStrategy.h        |   156 +
 Poco/UniqueExpireCache.h                 |    72 +
 Poco/UniqueExpireLRUCache.h              |    70 +
 Poco/UniqueExpireStrategy.h              |   138 +
 Poco/Util/AbstractConfiguration.h        |   381 +
 Poco/Util/Application.h                  |   545 +
 Poco/Util/ConfigurationMapper.h          |    94 +
 Poco/Util/ConfigurationView.h            |    82 +
 Poco/Util/FilesystemConfiguration.h      |    93 +
 Poco/Util/HelpFormatter.h                |   202 +
 Poco/Util/IniFileConfiguration.h         |    99 +
 Poco/Util/IntValidator.h                 |    56 +
 Poco/Util/JSONConfiguration.h            |   150 +
 Poco/Util/LayeredConfiguration.h         |   184 +
 Poco/Util/LoggingConfigurator.h          |   139 +
 Poco/Util/LoggingSubsystem.h             |    52 +
 Poco/Util/MapConfiguration.h             |    64 +
 Poco/Util/Option.h                       |   332 +
 Poco/Util/OptionCallback.h               |   109 +
 Poco/Util/OptionException.h              |    44 +
 Poco/Util/OptionProcessor.h              |   137 +
 Poco/Util/OptionSet.h                    |    88 +
 Poco/Util/PropertyFileConfiguration.h    |    99 +
 Poco/Util/RegExpValidator.h              |    54 +
 Poco/Util/ServerApplication.h            |   287 +
 Poco/Util/Subsystem.h                    |    98 +
 Poco/Util/SystemConfiguration.h          |    99 +
 Poco/Util/Timer.h                        |   169 +
 Poco/Util/TimerTask.h                    |    98 +
 Poco/Util/TimerTaskAdapter.h             |    69 +
 Poco/Util/Units.h                        |  1298 ++
 Poco/Util/Util.h                         |    62 +
 Poco/Util/Validator.h                    |    57 +
 Poco/Util/WinRegistryConfiguration.h     |    71 +
 Poco/Util/WinRegistryKey.h               |   198 +
 Poco/Util/WinService.h                   |   141 +
 Poco/Util/XMLConfiguration.h             |   209 +
 Poco/ValidArgs.h                         |    74 +
 Poco/Version.h                           |    41 +
 Poco/Void.h                              |    73 +
 Poco/Windows1250Encoding.h               |    52 +
 Poco/Windows1251Encoding.h               |    52 +
 Poco/Windows1252Encoding.h               |    51 +
 Poco/Windows1253Encoding.h               |    48 +
 Poco/Windows1254Encoding.h               |    48 +
 Poco/Windows1255Encoding.h               |    48 +
 Poco/Windows1256Encoding.h               |    48 +
 Poco/Windows1257Encoding.h               |    48 +
 Poco/Windows1258Encoding.h               |    48 +
 Poco/Windows874Encoding.h                |    48 +
 Poco/Windows932Encoding.h                |    48 +
 Poco/Windows936Encoding.h                |    48 +
 Poco/Windows949Encoding.h                |    48 +
 Poco/Windows950Encoding.h                |    48 +
 Poco/WindowsConsoleChannel.h             |   183 +
 Poco/XML/Content.h                       |    63 +
 Poco/XML/Name.h                          |   138 +
 Poco/XML/NamePool.h                      |    83 +
 Poco/XML/NamespaceStrategy.h             |   115 +
 Poco/XML/ParserEngine.h                  |   358 +
 Poco/XML/QName.h                         |   135 +
 Poco/XML/ValueTraits.h                   |   104 +
 Poco/XML/XML.h                           |    62 +
 Poco/XML/XMLException.h                  |    37 +
 Poco/XML/XMLStream.h                     |    71 +
 Poco/XML/XMLStreamParser.h               |   634 +
 Poco/XML/XMLStreamParserException.h      |    58 +
 Poco/XML/XMLString.h                     |    87 +
 Poco/XML/XMLWriter.h                     |   375 +
 Poco/XML/expat.h                         |  1085 +
 Poco/XML/expat_external.h                |   166 +
 Poco/Zip/Add.h                           |    51 +
 Poco/Zip/AutoDetectStream.h              |   101 +
 Poco/Zip/Compress.h                      |   151 +
 Poco/Zip/Decompress.h                    |    90 +
 Poco/Zip/Delete.h                        |    48 +
 Poco/Zip/Keep.h                          |    49 +
 Poco/Zip/ParseCallback.h                 |    54 +
 Poco/Zip/PartialStream.h                 |   187 +
 Poco/Zip/Rename.h                        |    49 +
 Poco/Zip/Replace.h                       |    50 +
 Poco/Zip/SkipCallback.h                  |    46 +
 Poco/Zip/Zip.h                           |    62 +
 Poco/Zip/ZipArchive.h                    |   121 +
 Poco/Zip/ZipArchiveInfo.h                |   405 +
 Poco/Zip/ZipCommon.h                     |   104 +
 Poco/Zip/ZipDataInfo.h                   |   248 +
 Poco/Zip/ZipException.h                  |    36 +
 Poco/Zip/ZipFileInfo.h                   |   519 +
 Poco/Zip/ZipLocalFileHeader.h            |   513 +
 Poco/Zip/ZipManipulator.h                |   109 +
 Poco/Zip/ZipOperation.h                  |    56 +
 Poco/Zip/ZipStream.h                     |   149 +
 Poco/Zip/ZipUtil.h                       |   126 +
 Poco/zconf.h                             |   536 +
 Poco/zlib.h                              |  1912 ++
 mosquitto.h                              |  2994 +++
 mosquitto_broker.h                       |   172 +
 mosquitto_plugin.h                       |   318 +
 mosquittopp.h                            |   146 +
 nlohmann/json.hpp                        | 22875 +++++++++++++++++++++
 openweathermap.h                         |    20 +-
 799 files changed, 169202 insertions(+), 11 deletions(-)
 create mode 100644 Poco/ASCIIEncoding.h
 create mode 100644 Poco/AbstractCache.h
 create mode 100644 Poco/AbstractDelegate.h
 create mode 100644 Poco/AbstractEvent.h
 create mode 100644 Poco/AbstractObserver.h
 create mode 100644 Poco/AbstractPriorityDelegate.h
 create mode 100644 Poco/AbstractStrategy.h
 create mode 100644 Poco/AccessExpirationDecorator.h
 create mode 100644 Poco/AccessExpireCache.h
 create mode 100644 Poco/AccessExpireLRUCache.h
 create mode 100644 Poco/AccessExpireStrategy.h
 create mode 100644 Poco/ActiveDispatcher.h
 create mode 100644 Poco/ActiveMethod.h
 create mode 100644 Poco/ActiveResult.h
 create mode 100644 Poco/ActiveRunnable.h
 create mode 100644 Poco/ActiveStarter.h
 create mode 100644 Poco/Activity.h
 create mode 100644 Poco/Alignment.h
 create mode 100644 Poco/Any.h
 create mode 100644 Poco/ArchiveStrategy.h
 create mode 100644 Poco/Array.h
 create mode 100644 Poco/Ascii.h
 create mode 100644 Poco/AsyncChannel.h
 create mode 100644 Poco/AtomicCounter.h
 create mode 100644 Poco/AutoPtr.h
 create mode 100644 Poco/AutoReleasePool.h
 create mode 100644 Poco/Base32Decoder.h
 create mode 100644 Poco/Base32Encoder.h
 create mode 100644 Poco/Base64Decoder.h
 create mode 100644 Poco/Base64Encoder.h
 create mode 100644 Poco/BasicEvent.h
 create mode 100644 Poco/BinaryReader.h
 create mode 100644 Poco/BinaryWriter.h
 create mode 100644 Poco/Buffer.h
 create mode 100644 Poco/BufferAllocator.h
 create mode 100644 Poco/BufferedBidirectionalStreamBuf.h
 create mode 100644 Poco/BufferedStreamBuf.h
 create mode 100644 Poco/Bugcheck.h
 create mode 100644 Poco/ByteOrder.h
 create mode 100644 Poco/Channel.h
 create mode 100644 Poco/Checksum.h
 create mode 100644 Poco/ClassLibrary.h
 create mode 100644 Poco/ClassLoader.h
 create mode 100644 Poco/Clock.h
 create mode 100644 Poco/Condition.h
 create mode 100644 Poco/Config.h
 create mode 100644 Poco/Configurable.h
 create mode 100644 Poco/ConsoleChannel.h
 create mode 100644 Poco/CountingStream.h
 create mode 100644 Poco/CppParser/Attributes.h
 create mode 100644 Poco/CppParser/AttributesParser.h
 create mode 100644 Poco/CppParser/BuiltIn.h
 create mode 100644 Poco/CppParser/CppParser.h
 create mode 100644 Poco/CppParser/CppToken.h
 create mode 100644 Poco/CppParser/Decl.h
 create mode 100644 Poco/CppParser/Enum.h
 create mode 100644 Poco/CppParser/EnumValue.h
 create mode 100644 Poco/CppParser/Function.h
 create mode 100644 Poco/CppParser/NameSpace.h
 create mode 100644 Poco/CppParser/Parameter.h
 create mode 100644 Poco/CppParser/Parser.h
 create mode 100644 Poco/CppParser/Struct.h
 create mode 100644 Poco/CppParser/Symbol.h
 create mode 100644 Poco/CppParser/Tokenizer.h
 create mode 100644 Poco/CppParser/TypeDef.h
 create mode 100644 Poco/CppParser/Utility.h
 create mode 100644 Poco/CppParser/Variable.h
 create mode 100644 Poco/Crypto/Cipher.h
 create mode 100644 Poco/Crypto/CipherFactory.h
 create mode 100644 Poco/Crypto/CipherImpl.h
 create mode 100644 Poco/Crypto/CipherKey.h
 create mode 100644 Poco/Crypto/CipherKeyImpl.h
 create mode 100644 Poco/Crypto/Crypto.h
 create mode 100644 Poco/Crypto/CryptoException.h
 create mode 100644 Poco/Crypto/CryptoStream.h
 create mode 100644 Poco/Crypto/CryptoTransform.h
 create mode 100644 Poco/Crypto/DigestEngine.h
 create mode 100644 Poco/Crypto/ECDSADigestEngine.h
 create mode 100644 Poco/Crypto/ECKey.h
 create mode 100644 Poco/Crypto/ECKeyImpl.h
 create mode 100644 Poco/Crypto/EVPPKey.h
 create mode 100644 Poco/Crypto/KeyPair.h
 create mode 100644 Poco/Crypto/KeyPairImpl.h
 create mode 100644 Poco/Crypto/OpenSSLInitializer.h
 create mode 100644 Poco/Crypto/PKCS12Container.h
 create mode 100644 Poco/Crypto/RSACipherImpl.h
 create mode 100644 Poco/Crypto/RSADigestEngine.h
 create mode 100644 Poco/Crypto/RSAKey.h
 create mode 100644 Poco/Crypto/RSAKeyImpl.h
 create mode 100644 Poco/Crypto/X509Certificate.h
 create mode 100644 Poco/DOM/AbstractContainerNode.h
 create mode 100644 Poco/DOM/AbstractNode.h
 create mode 100644 Poco/DOM/Attr.h
 create mode 100644 Poco/DOM/AttrMap.h
 create mode 100644 Poco/DOM/AutoPtr.h
 create mode 100644 Poco/DOM/CDATASection.h
 create mode 100644 Poco/DOM/CharacterData.h
 create mode 100644 Poco/DOM/ChildNodesList.h
 create mode 100644 Poco/DOM/Comment.h
 create mode 100644 Poco/DOM/DOMBuilder.h
 create mode 100644 Poco/DOM/DOMException.h
 create mode 100644 Poco/DOM/DOMImplementation.h
 create mode 100644 Poco/DOM/DOMObject.h
 create mode 100644 Poco/DOM/DOMParser.h
 create mode 100644 Poco/DOM/DOMSerializer.h
 create mode 100644 Poco/DOM/DOMWriter.h
 create mode 100644 Poco/DOM/DTDMap.h
 create mode 100644 Poco/DOM/Document.h
 create mode 100644 Poco/DOM/DocumentEvent.h
 create mode 100644 Poco/DOM/DocumentFragment.h
 create mode 100644 Poco/DOM/DocumentType.h
 create mode 100644 Poco/DOM/Element.h
 create mode 100644 Poco/DOM/ElementsByTagNameList.h
 create mode 100644 Poco/DOM/Entity.h
 create mode 100644 Poco/DOM/EntityReference.h
 create mode 100644 Poco/DOM/Event.h
 create mode 100644 Poco/DOM/EventDispatcher.h
 create mode 100644 Poco/DOM/EventException.h
 create mode 100644 Poco/DOM/EventListener.h
 create mode 100644 Poco/DOM/EventTarget.h
 create mode 100644 Poco/DOM/MutationEvent.h
 create mode 100644 Poco/DOM/NamedNodeMap.h
 create mode 100644 Poco/DOM/Node.h
 create mode 100644 Poco/DOM/NodeAppender.h
 create mode 100644 Poco/DOM/NodeFilter.h
 create mode 100644 Poco/DOM/NodeIterator.h
 create mode 100644 Poco/DOM/NodeList.h
 create mode 100644 Poco/DOM/Notation.h
 create mode 100644 Poco/DOM/ProcessingInstruction.h
 create mode 100644 Poco/DOM/Text.h
 create mode 100644 Poco/DOM/TreeWalker.h
 create mode 100644 Poco/Data/AbstractBinder.h
 create mode 100644 Poco/Data/AbstractBinding.h
 create mode 100644 Poco/Data/AbstractExtraction.h
 create mode 100644 Poco/Data/AbstractExtractor.h
 create mode 100644 Poco/Data/AbstractPreparation.h
 create mode 100644 Poco/Data/AbstractPreparator.h
 create mode 100644 Poco/Data/AbstractSessionImpl.h
 create mode 100644 Poco/Data/ArchiveStrategy.h
 create mode 100644 Poco/Data/AutoTransaction.h
 create mode 100644 Poco/Data/Binding.h
 create mode 100644 Poco/Data/Bulk.h
 create mode 100644 Poco/Data/BulkBinding.h
 create mode 100644 Poco/Data/BulkExtraction.h
 create mode 100644 Poco/Data/Column.h
 create mode 100644 Poco/Data/Connector.h
 create mode 100644 Poco/Data/Constants.h
 create mode 100644 Poco/Data/Data.h
 create mode 100644 Poco/Data/DataException.h
 create mode 100644 Poco/Data/Date.h
 create mode 100644 Poco/Data/DynamicDateTime.h
 create mode 100644 Poco/Data/DynamicLOB.h
 create mode 100644 Poco/Data/Extraction.h
 create mode 100644 Poco/Data/LOB.h
 create mode 100644 Poco/Data/LOBStream.h
 create mode 100644 Poco/Data/Limit.h
 create mode 100644 Poco/Data/MetaColumn.h
 create mode 100644 Poco/Data/ODBC/Binder.h
 create mode 100644 Poco/Data/ODBC/ConnectionHandle.h
 create mode 100644 Poco/Data/ODBC/Connector.h
 create mode 100644 Poco/Data/ODBC/Diagnostics.h
 create mode 100644 Poco/Data/ODBC/EnvironmentHandle.h
 create mode 100644 Poco/Data/ODBC/Error.h
 create mode 100644 Poco/Data/ODBC/Extractor.h
 create mode 100644 Poco/Data/ODBC/Handle.h
 create mode 100644 Poco/Data/ODBC/ODBC.h
 create mode 100644 Poco/Data/ODBC/ODBCException.h
 create mode 100644 Poco/Data/ODBC/ODBCMetaColumn.h
 create mode 100644 Poco/Data/ODBC/ODBCStatementImpl.h
 create mode 100644 Poco/Data/ODBC/Parameter.h
 create mode 100644 Poco/Data/ODBC/Preparator.h
 create mode 100644 Poco/Data/ODBC/SessionImpl.h
 create mode 100644 Poco/Data/ODBC/TypeInfo.h
 create mode 100644 Poco/Data/ODBC/Unicode.h
 create mode 100644 Poco/Data/ODBC/Unicode_UNIXODBC.h
 create mode 100644 Poco/Data/ODBC/Unicode_WIN32.h
 create mode 100644 Poco/Data/ODBC/Utility.h
 create mode 100644 Poco/Data/PooledSessionHolder.h
 create mode 100644 Poco/Data/PooledSessionImpl.h
 create mode 100644 Poco/Data/Position.h
 create mode 100644 Poco/Data/Preparation.h
 create mode 100644 Poco/Data/Range.h
 create mode 100644 Poco/Data/RecordSet.h
 create mode 100644 Poco/Data/Row.h
 create mode 100644 Poco/Data/RowFilter.h
 create mode 100644 Poco/Data/RowFormatter.h
 create mode 100644 Poco/Data/RowIterator.h
 create mode 100644 Poco/Data/SQLChannel.h
 create mode 100644 Poco/Data/SQLite/Binder.h
 create mode 100644 Poco/Data/SQLite/Connector.h
 create mode 100644 Poco/Data/SQLite/Extractor.h
 create mode 100644 Poco/Data/SQLite/Notifier.h
 create mode 100644 Poco/Data/SQLite/SQLite.h
 create mode 100644 Poco/Data/SQLite/SQLiteException.h
 create mode 100644 Poco/Data/SQLite/SQLiteStatementImpl.h
 create mode 100644 Poco/Data/SQLite/SessionImpl.h
 create mode 100644 Poco/Data/SQLite/Utility.h
 create mode 100644 Poco/Data/Session.h
 create mode 100644 Poco/Data/SessionFactory.h
 create mode 100644 Poco/Data/SessionImpl.h
 create mode 100644 Poco/Data/SessionPool.h
 create mode 100644 Poco/Data/SessionPoolContainer.h
 create mode 100644 Poco/Data/SimpleRowFormatter.h
 create mode 100644 Poco/Data/Statement.h
 create mode 100644 Poco/Data/StatementCreator.h
 create mode 100644 Poco/Data/StatementImpl.h
 create mode 100644 Poco/Data/Time.h
 create mode 100644 Poco/Data/Transaction.h
 create mode 100644 Poco/Data/TypeHandler.h
 create mode 100644 Poco/DateTime.h
 create mode 100644 Poco/DateTimeFormat.h
 create mode 100644 Poco/DateTimeFormatter.h
 create mode 100644 Poco/DateTimeParser.h
 create mode 100644 Poco/Debugger.h
 create mode 100644 Poco/DefaultStrategy.h
 create mode 100644 Poco/DeflatingStream.h
 create mode 100644 Poco/Delegate.h
 create mode 100644 Poco/DigestEngine.h
 create mode 100644 Poco/DigestStream.h
 create mode 100644 Poco/DirectoryIterator.h
 create mode 100644 Poco/DirectoryIteratorStrategy.h
 create mode 100644 Poco/DirectoryIterator_UNIX.h
 create mode 100644 Poco/DirectoryIterator_WIN32.h
 create mode 100644 Poco/DirectoryIterator_WIN32U.h
 create mode 100644 Poco/DirectoryWatcher.h
 create mode 100644 Poco/DoubleByteEncoding.h
 create mode 100644 Poco/Dynamic/Pair.h
 create mode 100644 Poco/Dynamic/Struct.h
 create mode 100644 Poco/Dynamic/Var.h
 create mode 100644 Poco/Dynamic/VarHolder.h
 create mode 100644 Poco/Dynamic/VarIterator.h
 create mode 100644 Poco/DynamicAny.h
 create mode 100644 Poco/DynamicAnyHolder.h
 create mode 100644 Poco/DynamicFactory.h
 create mode 100644 Poco/DynamicStruct.h
 create mode 100644 Poco/Encodings.h
 create mode 100644 Poco/Environment.h
 create mode 100644 Poco/Environment_UNIX.h
 create mode 100644 Poco/Environment_VX.h
 create mode 100644 Poco/Environment_WIN32.h
 create mode 100644 Poco/Environment_WIN32U.h
 create mode 100644 Poco/Environment_WINCE.h
 create mode 100644 Poco/Error.h
 create mode 100644 Poco/ErrorHandler.h
 create mode 100644 Poco/Event.h
 create mode 100644 Poco/EventArgs.h
 create mode 100644 Poco/EventChannel.h
 create mode 100644 Poco/EventLogChannel.h
 create mode 100644 Poco/Event_POSIX.h
 create mode 100644 Poco/Event_VX.h
 create mode 100644 Poco/Event_WIN32.h
 create mode 100644 Poco/Exception.h
 create mode 100644 Poco/ExpirationDecorator.h
 create mode 100644 Poco/Expire.h
 create mode 100644 Poco/ExpireCache.h
 create mode 100644 Poco/ExpireLRUCache.h
 create mode 100644 Poco/ExpireStrategy.h
 create mode 100644 Poco/FIFOBuffer.h
 create mode 100644 Poco/FIFOBufferStream.h
 create mode 100644 Poco/FIFOEvent.h
 create mode 100644 Poco/FIFOStrategy.h
 create mode 100644 Poco/FPEnvironment.h
 create mode 100644 Poco/FPEnvironment_C99.h
 create mode 100644 Poco/FPEnvironment_DEC.h
 create mode 100644 Poco/FPEnvironment_DUMMY.h
 create mode 100644 Poco/FPEnvironment_QNX.h
 create mode 100644 Poco/FPEnvironment_SUN.h
 create mode 100644 Poco/FPEnvironment_WIN32.h
 create mode 100644 Poco/File.h
 create mode 100644 Poco/FileChannel.h
 create mode 100644 Poco/FileStream.h
 create mode 100644 Poco/FileStreamFactory.h
 create mode 100644 Poco/FileStream_POSIX.h
 create mode 100644 Poco/FileStream_WIN32.h
 create mode 100644 Poco/File_UNIX.h
 create mode 100644 Poco/File_VX.h
 create mode 100644 Poco/File_WIN32.h
 create mode 100644 Poco/File_WIN32U.h
 create mode 100644 Poco/File_WINCE.h
 create mode 100644 Poco/Format.h
 create mode 100644 Poco/Formatter.h
 create mode 100644 Poco/FormattingChannel.h
 create mode 100644 Poco/Foundation.h
 create mode 100644 Poco/FunctionDelegate.h
 create mode 100644 Poco/FunctionPriorityDelegate.h
 create mode 100644 Poco/Glob.h
 create mode 100644 Poco/HMACEngine.h
 create mode 100644 Poco/Hash.h
 create mode 100644 Poco/HashFunction.h
 create mode 100644 Poco/HashMap.h
 create mode 100644 Poco/HashSet.h
 create mode 100644 Poco/HashStatistic.h
 create mode 100644 Poco/HashTable.h
 create mode 100644 Poco/HexBinaryDecoder.h
 create mode 100644 Poco/HexBinaryEncoder.h
 create mode 100644 Poco/ISO8859_10Encoding.h
 create mode 100644 Poco/ISO8859_11Encoding.h
 create mode 100644 Poco/ISO8859_13Encoding.h
 create mode 100644 Poco/ISO8859_14Encoding.h
 create mode 100644 Poco/ISO8859_16Encoding.h
 create mode 100644 Poco/ISO8859_3Encoding.h
 create mode 100644 Poco/ISO8859_4Encoding.h
 create mode 100644 Poco/ISO8859_5Encoding.h
 create mode 100644 Poco/ISO8859_6Encoding.h
 create mode 100644 Poco/ISO8859_7Encoding.h
 create mode 100644 Poco/ISO8859_8Encoding.h
 create mode 100644 Poco/ISO8859_9Encoding.h
 create mode 100644 Poco/InflatingStream.h
 create mode 100644 Poco/Instantiator.h
 create mode 100644 Poco/JSON/Array.h
 create mode 100644 Poco/JSON/Handler.h
 create mode 100644 Poco/JSON/JSON.h
 create mode 100644 Poco/JSON/JSONException.h
 create mode 100644 Poco/JSON/Object.h
 create mode 100644 Poco/JSON/ParseHandler.h
 create mode 100644 Poco/JSON/Parser.h
 create mode 100644 Poco/JSON/ParserImpl.h
 create mode 100644 Poco/JSON/PrintHandler.h
 create mode 100644 Poco/JSON/Query.h
 create mode 100644 Poco/JSON/Stringifier.h
 create mode 100644 Poco/JSON/Template.h
 create mode 100644 Poco/JSON/TemplateCache.h
 create mode 100644 Poco/JSONString.h
 create mode 100644 Poco/KeyValueArgs.h
 create mode 100644 Poco/LRUCache.h
 create mode 100644 Poco/LRUStrategy.h
 create mode 100644 Poco/Latin1Encoding.h
 create mode 100644 Poco/Latin2Encoding.h
 create mode 100644 Poco/Latin9Encoding.h
 create mode 100644 Poco/LineEndingConverter.h
 create mode 100644 Poco/LinearHashTable.h
 create mode 100644 Poco/ListMap.h
 create mode 100644 Poco/LocalDateTime.h
 create mode 100644 Poco/LogFile.h
 create mode 100644 Poco/LogFile_STD.h
 create mode 100644 Poco/LogFile_WIN32.h
 create mode 100644 Poco/LogFile_WIN32U.h
 create mode 100644 Poco/LogStream.h
 create mode 100644 Poco/Logger.h
 create mode 100644 Poco/LoggingFactory.h
 create mode 100644 Poco/LoggingRegistry.h
 create mode 100644 Poco/MD4Engine.h
 create mode 100644 Poco/MD5Engine.h
 create mode 100644 Poco/Manifest.h
 create mode 100644 Poco/MemoryPool.h
 create mode 100644 Poco/MemoryStream.h
 create mode 100644 Poco/Message.h
 create mode 100644 Poco/MetaObject.h
 create mode 100644 Poco/MetaProgramming.h
 create mode 100644 Poco/MongoDB/Array.h
 create mode 100644 Poco/MongoDB/BSONReader.h
 create mode 100644 Poco/MongoDB/BSONWriter.h
 create mode 100644 Poco/MongoDB/Binary.h
 create mode 100644 Poco/MongoDB/Connection.h
 create mode 100644 Poco/MongoDB/Cursor.h
 create mode 100644 Poco/MongoDB/Database.h
 create mode 100644 Poco/MongoDB/DeleteRequest.h
 create mode 100644 Poco/MongoDB/Document.h
 create mode 100644 Poco/MongoDB/Element.h
 create mode 100644 Poco/MongoDB/GetMoreRequest.h
 create mode 100644 Poco/MongoDB/InsertRequest.h
 create mode 100644 Poco/MongoDB/JavaScriptCode.h
 create mode 100644 Poco/MongoDB/KillCursorsRequest.h
 create mode 100644 Poco/MongoDB/Message.h
 create mode 100644 Poco/MongoDB/MessageHeader.h
 create mode 100644 Poco/MongoDB/MongoDB.h
 create mode 100644 Poco/MongoDB/ObjectId.h
 create mode 100644 Poco/MongoDB/PoolableConnectionFactory.h
 create mode 100644 Poco/MongoDB/QueryRequest.h
 create mode 100644 Poco/MongoDB/RegularExpression.h
 create mode 100644 Poco/MongoDB/ReplicaSet.h
 create mode 100644 Poco/MongoDB/RequestMessage.h
 create mode 100644 Poco/MongoDB/ResponseMessage.h
 create mode 100644 Poco/MongoDB/UpdateRequest.h
 create mode 100644 Poco/Mutex.h
 create mode 100644 Poco/Mutex_POSIX.h
 create mode 100644 Poco/Mutex_VX.h
 create mode 100644 Poco/Mutex_WIN32.h
 create mode 100644 Poco/Mutex_WINCE.h
 create mode 100644 Poco/NObserver.h
 create mode 100644 Poco/NamedEvent.h
 create mode 100644 Poco/NamedEvent_Android.h
 create mode 100644 Poco/NamedEvent_UNIX.h
 create mode 100644 Poco/NamedEvent_WIN32.h
 create mode 100644 Poco/NamedEvent_WIN32U.h
 create mode 100644 Poco/NamedMutex.h
 create mode 100644 Poco/NamedMutex_Android.h
 create mode 100644 Poco/NamedMutex_UNIX.h
 create mode 100644 Poco/NamedMutex_WIN32.h
 create mode 100644 Poco/NamedMutex_WIN32U.h
 create mode 100644 Poco/NamedTuple.h
 create mode 100644 Poco/NestedDiagnosticContext.h
 create mode 100644 Poco/Net/AbstractHTTPRequestHandler.h
 create mode 100644 Poco/Net/AcceptCertificateHandler.h
 create mode 100644 Poco/Net/CertificateHandlerFactory.h
 create mode 100644 Poco/Net/CertificateHandlerFactoryMgr.h
 create mode 100644 Poco/Net/ConsoleCertificateHandler.h
 create mode 100644 Poco/Net/Context.h
 create mode 100644 Poco/Net/DNS.h
 create mode 100644 Poco/Net/DatagramSocket.h
 create mode 100644 Poco/Net/DatagramSocketImpl.h
 create mode 100644 Poco/Net/DialogSocket.h
 create mode 100644 Poco/Net/FTPClientSession.h
 create mode 100644 Poco/Net/FTPStreamFactory.h
 create mode 100644 Poco/Net/FilePartSource.h
 create mode 100644 Poco/Net/HTMLForm.h
 create mode 100644 Poco/Net/HTTPAuthenticationParams.h
 create mode 100644 Poco/Net/HTTPBasicCredentials.h
 create mode 100644 Poco/Net/HTTPBasicStreamBuf.h
 create mode 100644 Poco/Net/HTTPBufferAllocator.h
 create mode 100644 Poco/Net/HTTPChunkedStream.h
 create mode 100644 Poco/Net/HTTPClientSession.h
 create mode 100644 Poco/Net/HTTPCookie.h
 create mode 100644 Poco/Net/HTTPCredentials.h
 create mode 100644 Poco/Net/HTTPDigestCredentials.h
 create mode 100644 Poco/Net/HTTPFixedLengthStream.h
 create mode 100644 Poco/Net/HTTPHeaderStream.h
 create mode 100644 Poco/Net/HTTPIOStream.h
 create mode 100644 Poco/Net/HTTPMessage.h
 create mode 100644 Poco/Net/HTTPRequest.h
 create mode 100644 Poco/Net/HTTPRequestHandler.h
 create mode 100644 Poco/Net/HTTPRequestHandlerFactory.h
 create mode 100644 Poco/Net/HTTPResponse.h
 create mode 100644 Poco/Net/HTTPSClientSession.h
 create mode 100644 Poco/Net/HTTPSSessionInstantiator.h
 create mode 100644 Poco/Net/HTTPSStreamFactory.h
 create mode 100644 Poco/Net/HTTPServer.h
 create mode 100644 Poco/Net/HTTPServerConnection.h
 create mode 100644 Poco/Net/HTTPServerConnectionFactory.h
 create mode 100644 Poco/Net/HTTPServerParams.h
 create mode 100644 Poco/Net/HTTPServerRequest.h
 create mode 100644 Poco/Net/HTTPServerRequestImpl.h
 create mode 100644 Poco/Net/HTTPServerResponse.h
 create mode 100644 Poco/Net/HTTPServerResponseImpl.h
 create mode 100644 Poco/Net/HTTPServerSession.h
 create mode 100644 Poco/Net/HTTPSession.h
 create mode 100644 Poco/Net/HTTPSessionFactory.h
 create mode 100644 Poco/Net/HTTPSessionInstantiator.h
 create mode 100644 Poco/Net/HTTPStream.h
 create mode 100644 Poco/Net/HTTPStreamFactory.h
 create mode 100644 Poco/Net/HostEntry.h
 create mode 100644 Poco/Net/ICMPClient.h
 create mode 100644 Poco/Net/ICMPEventArgs.h
 create mode 100644 Poco/Net/ICMPPacket.h
 create mode 100644 Poco/Net/ICMPPacketImpl.h
 create mode 100644 Poco/Net/ICMPSocket.h
 create mode 100644 Poco/Net/ICMPSocketImpl.h
 create mode 100644 Poco/Net/ICMPv4PacketImpl.h
 create mode 100644 Poco/Net/IPAddress.h
 create mode 100644 Poco/Net/IPAddressImpl.h
 create mode 100644 Poco/Net/InvalidCertificateHandler.h
 create mode 100644 Poco/Net/KeyConsoleHandler.h
 create mode 100644 Poco/Net/KeyFileHandler.h
 create mode 100644 Poco/Net/MailMessage.h
 create mode 100644 Poco/Net/MailRecipient.h
 create mode 100644 Poco/Net/MailStream.h
 create mode 100644 Poco/Net/MediaType.h
 create mode 100644 Poco/Net/MessageHeader.h
 create mode 100644 Poco/Net/MulticastSocket.h
 create mode 100644 Poco/Net/MultipartReader.h
 create mode 100644 Poco/Net/MultipartWriter.h
 create mode 100644 Poco/Net/NTPClient.h
 create mode 100644 Poco/Net/NTPEventArgs.h
 create mode 100644 Poco/Net/NTPPacket.h
 create mode 100644 Poco/Net/NameValueCollection.h
 create mode 100644 Poco/Net/Net.h
 create mode 100644 Poco/Net/NetException.h
 create mode 100644 Poco/Net/NetSSL.h
 create mode 100644 Poco/Net/NetworkInterface.h
 create mode 100644 Poco/Net/NullPartHandler.h
 create mode 100644 Poco/Net/OAuth10Credentials.h
 create mode 100644 Poco/Net/OAuth20Credentials.h
 create mode 100644 Poco/Net/POP3ClientSession.h
 create mode 100644 Poco/Net/ParallelSocketAcceptor.h
 create mode 100644 Poco/Net/ParallelSocketReactor.h
 create mode 100644 Poco/Net/PartHandler.h
 create mode 100644 Poco/Net/PartSource.h
 create mode 100644 Poco/Net/PartStore.h
 create mode 100644 Poco/Net/PollSet.h
 create mode 100644 Poco/Net/PrivateKeyFactory.h
 create mode 100644 Poco/Net/PrivateKeyFactoryMgr.h
 create mode 100644 Poco/Net/PrivateKeyPassphraseHandler.h
 create mode 100644 Poco/Net/QuotedPrintableDecoder.h
 create mode 100644 Poco/Net/QuotedPrintableEncoder.h
 create mode 100644 Poco/Net/RawSocket.h
 create mode 100644 Poco/Net/RawSocketImpl.h
 create mode 100644 Poco/Net/RejectCertificateHandler.h
 create mode 100644 Poco/Net/RemoteSyslogChannel.h
 create mode 100644 Poco/Net/RemoteSyslogListener.h
 create mode 100644 Poco/Net/SMTPChannel.h
 create mode 100644 Poco/Net/SMTPClientSession.h
 create mode 100644 Poco/Net/SSLException.h
 create mode 100644 Poco/Net/SSLManager.h
 create mode 100644 Poco/Net/SecureSMTPClientSession.h
 create mode 100644 Poco/Net/SecureServerSocket.h
 create mode 100644 Poco/Net/SecureServerSocketImpl.h
 create mode 100644 Poco/Net/SecureSocketImpl.h
 create mode 100644 Poco/Net/SecureStreamSocket.h
 create mode 100644 Poco/Net/SecureStreamSocketImpl.h
 create mode 100644 Poco/Net/ServerSocket.h
 create mode 100644 Poco/Net/ServerSocketImpl.h
 create mode 100644 Poco/Net/Session.h
 create mode 100644 Poco/Net/Socket.h
 create mode 100644 Poco/Net/SocketAcceptor.h
 create mode 100644 Poco/Net/SocketAddress.h
 create mode 100644 Poco/Net/SocketAddressImpl.h
 create mode 100644 Poco/Net/SocketConnector.h
 create mode 100644 Poco/Net/SocketDefs.h
 create mode 100644 Poco/Net/SocketImpl.h
 create mode 100644 Poco/Net/SocketNotification.h
 create mode 100644 Poco/Net/SocketNotifier.h
 create mode 100644 Poco/Net/SocketReactor.h
 create mode 100644 Poco/Net/SocketStream.h
 create mode 100644 Poco/Net/StreamSocket.h
 create mode 100644 Poco/Net/StreamSocketImpl.h
 create mode 100644 Poco/Net/StringPartSource.h
 create mode 100644 Poco/Net/TCPServer.h
 create mode 100644 Poco/Net/TCPServerConnection.h
 create mode 100644 Poco/Net/TCPServerConnectionFactory.h
 create mode 100644 Poco/Net/TCPServerDispatcher.h
 create mode 100644 Poco/Net/TCPServerParams.h
 create mode 100644 Poco/Net/Utility.h
 create mode 100644 Poco/Net/VerificationErrorArgs.h
 create mode 100644 Poco/Net/WebSocket.h
 create mode 100644 Poco/Net/WebSocketImpl.h
 create mode 100644 Poco/Net/X509Certificate.h
 create mode 100644 Poco/Notification.h
 create mode 100644 Poco/NotificationCenter.h
 create mode 100644 Poco/NotificationQueue.h
 create mode 100644 Poco/NotificationStrategy.h
 create mode 100644 Poco/NullChannel.h
 create mode 100644 Poco/NullStream.h
 create mode 100644 Poco/Nullable.h
 create mode 100644 Poco/NumberFormatter.h
 create mode 100644 Poco/NumberParser.h
 create mode 100644 Poco/NumericString.h
 create mode 100644 Poco/ObjectPool.h
 create mode 100644 Poco/Observer.h
 create mode 100644 Poco/Optional.h
 create mode 100644 Poco/PBKDF2Engine.h
 create mode 100644 Poco/Path.h
 create mode 100644 Poco/Path_UNIX.h
 create mode 100644 Poco/Path_WIN32.h
 create mode 100644 Poco/Path_WIN32U.h
 create mode 100644 Poco/Path_WINCE.h
 create mode 100644 Poco/PatternFormatter.h
 create mode 100644 Poco/Pipe.h
 create mode 100644 Poco/PipeImpl.h
 create mode 100644 Poco/PipeImpl_DUMMY.h
 create mode 100644 Poco/PipeImpl_POSIX.h
 create mode 100644 Poco/PipeImpl_WIN32.h
 create mode 100644 Poco/PipeStream.h
 create mode 100644 Poco/Platform.h
 create mode 100644 Poco/Platform_POSIX.h
 create mode 100644 Poco/Platform_VX.h
 create mode 100644 Poco/Platform_WIN32.h
 create mode 100644 Poco/Poco.h
 create mode 100644 Poco/PriorityDelegate.h
 create mode 100644 Poco/PriorityEvent.h
 create mode 100644 Poco/PriorityExpire.h
 create mode 100644 Poco/PriorityNotificationQueue.h
 create mode 100644 Poco/PriorityStrategy.h
 create mode 100644 Poco/Process.h
 create mode 100644 Poco/Process_UNIX.h
 create mode 100644 Poco/Process_VX.h
 create mode 100644 Poco/Process_WIN32.h
 create mode 100644 Poco/Process_WIN32U.h
 create mode 100644 Poco/Process_WINCE.h
 create mode 100644 Poco/PurgeStrategy.h
 create mode 100644 Poco/RWLock.h
 create mode 100644 Poco/RWLock_Android.h
 create mode 100644 Poco/RWLock_POSIX.h
 create mode 100644 Poco/RWLock_VX.h
 create mode 100644 Poco/RWLock_WIN32.h
 create mode 100644 Poco/RWLock_WINCE.h
 create mode 100644 Poco/Random.h
 create mode 100644 Poco/RandomStream.h
 create mode 100644 Poco/RecursiveDirectoryIterator.h
 create mode 100644 Poco/RecursiveDirectoryIteratorImpl.h
 create mode 100644 Poco/Redis/Array.h
 create mode 100644 Poco/Redis/AsyncReader.h
 create mode 100644 Poco/Redis/Client.h
 create mode 100644 Poco/Redis/Command.h
 create mode 100644 Poco/Redis/Error.h
 create mode 100644 Poco/Redis/Exception.h
 create mode 100644 Poco/Redis/PoolableConnectionFactory.h
 create mode 100644 Poco/Redis/Redis.h
 create mode 100644 Poco/Redis/RedisEventArgs.h
 create mode 100644 Poco/Redis/RedisStream.h
 create mode 100644 Poco/Redis/Type.h
 create mode 100644 Poco/RefCountedObject.h
 create mode 100644 Poco/RegularExpression.h
 create mode 100644 Poco/RotateStrategy.h
 create mode 100644 Poco/Runnable.h
 create mode 100644 Poco/RunnableAdapter.h
 create mode 100644 Poco/SAX/Attributes.h
 create mode 100644 Poco/SAX/AttributesImpl.h
 create mode 100644 Poco/SAX/ContentHandler.h
 create mode 100644 Poco/SAX/DTDHandler.h
 create mode 100644 Poco/SAX/DeclHandler.h
 create mode 100644 Poco/SAX/DefaultHandler.h
 create mode 100644 Poco/SAX/EntityResolver.h
 create mode 100644 Poco/SAX/EntityResolverImpl.h
 create mode 100644 Poco/SAX/ErrorHandler.h
 create mode 100644 Poco/SAX/InputSource.h
 create mode 100644 Poco/SAX/LexicalHandler.h
 create mode 100644 Poco/SAX/Locator.h
 create mode 100644 Poco/SAX/LocatorImpl.h
 create mode 100644 Poco/SAX/NamespaceSupport.h
 create mode 100644 Poco/SAX/SAXException.h
 create mode 100644 Poco/SAX/SAXParser.h
 create mode 100644 Poco/SAX/WhitespaceFilter.h
 create mode 100644 Poco/SAX/XMLFilter.h
 create mode 100644 Poco/SAX/XMLFilterImpl.h
 create mode 100644 Poco/SAX/XMLReader.h
 create mode 100644 Poco/SHA1Engine.h
 create mode 100644 Poco/ScopedLock.h
 create mode 100644 Poco/ScopedUnlock.h
 create mode 100644 Poco/Semaphore.h
 create mode 100644 Poco/Semaphore_POSIX.h
 create mode 100644 Poco/Semaphore_VX.h
 create mode 100644 Poco/Semaphore_WIN32.h
 create mode 100644 Poco/SevenZip/Archive.h
 create mode 100644 Poco/SevenZip/ArchiveEntry.h
 create mode 100644 Poco/SevenZip/SevenZip.h
 create mode 100644 Poco/SharedLibrary.h
 create mode 100644 Poco/SharedLibrary_HPUX.h
 create mode 100644 Poco/SharedLibrary_UNIX.h
 create mode 100644 Poco/SharedLibrary_VX.h
 create mode 100644 Poco/SharedLibrary_WIN32.h
 create mode 100644 Poco/SharedLibrary_WIN32U.h
 create mode 100644 Poco/SharedMemory.h
 create mode 100644 Poco/SharedMemory_DUMMY.h
 create mode 100644 Poco/SharedMemory_POSIX.h
 create mode 100644 Poco/SharedMemory_WIN32.h
 create mode 100644 Poco/SharedPtr.h
 create mode 100644 Poco/SignalHandler.h
 create mode 100644 Poco/SimpleFileChannel.h
 create mode 100644 Poco/SimpleHashTable.h
 create mode 100644 Poco/SingletonHolder.h
 create mode 100644 Poco/SortedDirectoryIterator.h
 create mode 100644 Poco/SplitterChannel.h
 create mode 100644 Poco/Stopwatch.h
 create mode 100644 Poco/StrategyCollection.h
 create mode 100644 Poco/StreamChannel.h
 create mode 100644 Poco/StreamConverter.h
 create mode 100644 Poco/StreamCopier.h
 create mode 100644 Poco/StreamTokenizer.h
 create mode 100644 Poco/StreamUtil.h
 create mode 100644 Poco/String.h
 create mode 100644 Poco/StringTokenizer.h
 create mode 100644 Poco/SynchronizedObject.h
 create mode 100644 Poco/SyslogChannel.h
 create mode 100644 Poco/Task.h
 create mode 100644 Poco/TaskManager.h
 create mode 100644 Poco/TaskNotification.h
 create mode 100644 Poco/TeeStream.h
 create mode 100644 Poco/TemporaryFile.h
 create mode 100644 Poco/TextBufferIterator.h
 create mode 100644 Poco/TextConverter.h
 create mode 100644 Poco/TextEncoding.h
 create mode 100644 Poco/TextIterator.h
 create mode 100644 Poco/Thread.h
 create mode 100644 Poco/ThreadLocal.h
 create mode 100644 Poco/ThreadPool.h
 create mode 100644 Poco/ThreadTarget.h
 create mode 100644 Poco/Thread_POSIX.h
 create mode 100644 Poco/Thread_VX.h
 create mode 100644 Poco/Thread_WIN32.h
 create mode 100644 Poco/Thread_WINCE.h
 create mode 100644 Poco/TimedNotificationQueue.h
 create mode 100644 Poco/Timer.h
 create mode 100644 Poco/Timespan.h
 create mode 100644 Poco/Timestamp.h
 create mode 100644 Poco/Timezone.h
 create mode 100644 Poco/Token.h
 create mode 100644 Poco/Tuple.h
 create mode 100644 Poco/TypeList.h
 create mode 100644 Poco/Types.h
 create mode 100644 Poco/URI.h
 create mode 100644 Poco/URIStreamFactory.h
 create mode 100644 Poco/URIStreamOpener.h
 create mode 100644 Poco/UTF16Encoding.h
 create mode 100644 Poco/UTF32Encoding.h
 create mode 100644 Poco/UTF8Encoding.h
 create mode 100644 Poco/UTF8String.h
 create mode 100644 Poco/UTFString.h
 create mode 100644 Poco/UUID.h
 create mode 100644 Poco/UUIDGenerator.h
 create mode 100644 Poco/UnWindows.h
 create mode 100644 Poco/UnbufferedStreamBuf.h
 create mode 100644 Poco/Unicode.h
 create mode 100644 Poco/UnicodeConverter.h
 create mode 100644 Poco/UniqueAccessExpireCache.h
 create mode 100644 Poco/UniqueAccessExpireLRUCache.h
 create mode 100644 Poco/UniqueAccessExpireStrategy.h
 create mode 100644 Poco/UniqueExpireCache.h
 create mode 100644 Poco/UniqueExpireLRUCache.h
 create mode 100644 Poco/UniqueExpireStrategy.h
 create mode 100644 Poco/Util/AbstractConfiguration.h
 create mode 100644 Poco/Util/Application.h
 create mode 100644 Poco/Util/ConfigurationMapper.h
 create mode 100644 Poco/Util/ConfigurationView.h
 create mode 100644 Poco/Util/FilesystemConfiguration.h
 create mode 100644 Poco/Util/HelpFormatter.h
 create mode 100644 Poco/Util/IniFileConfiguration.h
 create mode 100644 Poco/Util/IntValidator.h
 create mode 100644 Poco/Util/JSONConfiguration.h
 create mode 100644 Poco/Util/LayeredConfiguration.h
 create mode 100644 Poco/Util/LoggingConfigurator.h
 create mode 100644 Poco/Util/LoggingSubsystem.h
 create mode 100644 Poco/Util/MapConfiguration.h
 create mode 100644 Poco/Util/Option.h
 create mode 100644 Poco/Util/OptionCallback.h
 create mode 100644 Poco/Util/OptionException.h
 create mode 100644 Poco/Util/OptionProcessor.h
 create mode 100644 Poco/Util/OptionSet.h
 create mode 100644 Poco/Util/PropertyFileConfiguration.h
 create mode 100644 Poco/Util/RegExpValidator.h
 create mode 100644 Poco/Util/ServerApplication.h
 create mode 100644 Poco/Util/Subsystem.h
 create mode 100644 Poco/Util/SystemConfiguration.h
 create mode 100644 Poco/Util/Timer.h
 create mode 100644 Poco/Util/TimerTask.h
 create mode 100644 Poco/Util/TimerTaskAdapter.h
 create mode 100644 Poco/Util/Units.h
 create mode 100644 Poco/Util/Util.h
 create mode 100644 Poco/Util/Validator.h
 create mode 100644 Poco/Util/WinRegistryConfiguration.h
 create mode 100644 Poco/Util/WinRegistryKey.h
 create mode 100644 Poco/Util/WinService.h
 create mode 100644 Poco/Util/XMLConfiguration.h
 create mode 100644 Poco/ValidArgs.h
 create mode 100644 Poco/Version.h
 create mode 100644 Poco/Void.h
 create mode 100644 Poco/Windows1250Encoding.h
 create mode 100644 Poco/Windows1251Encoding.h
 create mode 100644 Poco/Windows1252Encoding.h
 create mode 100644 Poco/Windows1253Encoding.h
 create mode 100644 Poco/Windows1254Encoding.h
 create mode 100644 Poco/Windows1255Encoding.h
 create mode 100644 Poco/Windows1256Encoding.h
 create mode 100644 Poco/Windows1257Encoding.h
 create mode 100644 Poco/Windows1258Encoding.h
 create mode 100644 Poco/Windows874Encoding.h
 create mode 100644 Poco/Windows932Encoding.h
 create mode 100644 Poco/Windows936Encoding.h
 create mode 100644 Poco/Windows949Encoding.h
 create mode 100644 Poco/Windows950Encoding.h
 create mode 100644 Poco/WindowsConsoleChannel.h
 create mode 100644 Poco/XML/Content.h
 create mode 100644 Poco/XML/Name.h
 create mode 100644 Poco/XML/NamePool.h
 create mode 100644 Poco/XML/NamespaceStrategy.h
 create mode 100644 Poco/XML/ParserEngine.h
 create mode 100644 Poco/XML/QName.h
 create mode 100644 Poco/XML/ValueTraits.h
 create mode 100644 Poco/XML/XML.h
 create mode 100644 Poco/XML/XMLException.h
 create mode 100644 Poco/XML/XMLStream.h
 create mode 100644 Poco/XML/XMLStreamParser.h
 create mode 100644 Poco/XML/XMLStreamParserException.h
 create mode 100644 Poco/XML/XMLString.h
 create mode 100644 Poco/XML/XMLWriter.h
 create mode 100644 Poco/XML/expat.h
 create mode 100644 Poco/XML/expat_external.h
 create mode 100644 Poco/Zip/Add.h
 create mode 100644 Poco/Zip/AutoDetectStream.h
 create mode 100644 Poco/Zip/Compress.h
 create mode 100644 Poco/Zip/Decompress.h
 create mode 100644 Poco/Zip/Delete.h
 create mode 100644 Poco/Zip/Keep.h
 create mode 100644 Poco/Zip/ParseCallback.h
 create mode 100644 Poco/Zip/PartialStream.h
 create mode 100644 Poco/Zip/Rename.h
 create mode 100644 Poco/Zip/Replace.h
 create mode 100644 Poco/Zip/SkipCallback.h
 create mode 100644 Poco/Zip/Zip.h
 create mode 100644 Poco/Zip/ZipArchive.h
 create mode 100644 Poco/Zip/ZipArchiveInfo.h
 create mode 100644 Poco/Zip/ZipCommon.h
 create mode 100644 Poco/Zip/ZipDataInfo.h
 create mode 100644 Poco/Zip/ZipException.h
 create mode 100644 Poco/Zip/ZipFileInfo.h
 create mode 100644 Poco/Zip/ZipLocalFileHeader.h
 create mode 100644 Poco/Zip/ZipManipulator.h
 create mode 100644 Poco/Zip/ZipOperation.h
 create mode 100644 Poco/Zip/ZipStream.h
 create mode 100644 Poco/Zip/ZipUtil.h
 create mode 100644 Poco/zconf.h
 create mode 100644 Poco/zlib.h
 create mode 100644 mosquitto.h
 create mode 100644 mosquitto_broker.h
 create mode 100644 mosquitto_plugin.h
 create mode 100644 mosquittopp.h
 create mode 100644 nlohmann/json.hpp

diff --git a/.gitignore b/.gitignore
index 7f142c5..1f64d1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
 /Debug
 /x64/Release
 /Release
+/x64/Debug
diff --git a/MqttClient.h b/MqttClient.h
index 4b6ccaf..e1099dd 100644
--- a/MqttClient.h
+++ b/MqttClient.h
@@ -2,7 +2,7 @@
 #include <iostream>
 #include <cstring>
 #include <cstdio>
-#include <mosquittopp.h>
+#include "mosquittopp.h"
 #include "dbSqlite.h"
 #include "structs.h"
 
diff --git a/Poco/ASCIIEncoding.h b/Poco/ASCIIEncoding.h
new file mode 100644
index 0000000..e47f615
--- /dev/null
+++ b/Poco/ASCIIEncoding.h
@@ -0,0 +1,51 @@
+//
+// ASCIIEncoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  ASCIIEncoding
+//
+// Definition of the ASCIIEncoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ASCIIEncoding_INCLUDED
+#define Foundation_ASCIIEncoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API ASCIIEncoding: public TextEncoding
+	/// 7-bit ASCII text encoding.
+{
+public:
+	ASCIIEncoding();
+	~ASCIIEncoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ASCIIEncoding_INCLUDED
diff --git a/Poco/AbstractCache.h b/Poco/AbstractCache.h
new file mode 100644
index 0000000..37cfc25
--- /dev/null
+++ b/Poco/AbstractCache.h
@@ -0,0 +1,366 @@
+//
+// AbstractCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  AbstractCache
+//
+// Definition of the AbstractCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AbstractCache_INCLUDED
+#define Foundation_AbstractCache_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h" 
+#include "Poco/Mutex.h"
+#include "Poco/Exception.h"
+#include "Poco/FIFOEvent.h"
+#include "Poco/EventArgs.h"
+#include "Poco/Delegate.h"
+#include "Poco/SharedPtr.h"
+#include <map>
+#include <set>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+template <class TKey, class TValue, class TStrategy, class TMutex = FastMutex, class TEventMutex = FastMutex> 
+class AbstractCache
+	/// An AbstractCache is the interface of all caches. 
+{
+public:
+	FIFOEvent<const KeyValueArgs<TKey, TValue >, TEventMutex > Add;
+	FIFOEvent<const KeyValueArgs<TKey, TValue >, TEventMutex > Update;
+	FIFOEvent<const TKey, TEventMutex>                         Remove;
+	FIFOEvent<const TKey, TEventMutex>                         Get;
+	FIFOEvent<const EventArgs, TEventMutex>                    Clear;
+
+	typedef std::map<TKey, SharedPtr<TValue > > DataHolder;
+	typedef typename DataHolder::iterator       Iterator;
+	typedef typename DataHolder::const_iterator ConstIterator;
+	typedef std::set<TKey>                      KeySet;
+
+	AbstractCache()
+	{
+		initialize();
+	}
+
+	AbstractCache(const TStrategy& strat): _strategy(strat)
+	{
+		initialize();
+	}
+
+	virtual ~AbstractCache()
+	{
+		try
+		{
+			uninitialize();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	void add(const TKey& key, const TValue& val)
+		/// Adds the key value pair to the cache.
+		/// If for the key already an entry exists, it will be overwritten.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doAdd(key, val);
+	}
+
+	void update(const TKey& key, const TValue& val)
+		/// Adds the key value pair to the cache. Note that adding a NULL SharedPtr will fail!
+		/// If for the key already an entry exists, it will be overwritten.
+		/// The difference to add is that no remove or add events are thrown in this case, 
+		/// just a simply silent update is performed
+		/// If the key doesnot exist the behavior is equal to add, ie. an add event is thrown
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doUpdate(key, val);
+	}
+
+	void add(const TKey& key, SharedPtr<TValue > val)
+		/// Adds the key value pair to the cache. Note that adding a NULL SharedPtr will fail!
+		/// If for the key already an entry exists, it will be overwritten, ie. first a remove event
+		/// is thrown, then a add event
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doAdd(key, val);
+	}
+
+	void update(const TKey& key, SharedPtr<TValue > val)
+		/// Adds the key value pair to the cache. Note that adding a NULL SharedPtr will fail!
+		/// If for the key already an entry exists, it will be overwritten.
+		/// The difference to add is that no remove or add events are thrown in this case, 
+		/// just an Update is thrown
+		/// If the key doesnot exist the behavior is equal to add, ie. an add event is thrown
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doUpdate(key, val);
+	}
+
+	void remove(const TKey& key)
+		/// Removes an entry from the cache. If the entry is not found,
+		/// the remove is ignored.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		Iterator it = _data.find(key);
+		doRemove(it);
+	}
+
+	bool has(const TKey& key) const
+		/// Returns true if the cache contains a value for the key.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return doHas(key);
+	}
+
+	SharedPtr<TValue> get(const TKey& key)
+		/// Returns a SharedPtr of the value. The SharedPointer will remain valid
+		/// even when cache replacement removes the element.
+		/// If for the key no value exists, an empty SharedPtr is returned.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return doGet (key);
+	}
+
+	void clear()
+		/// Removes all elements from the cache.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doClear();
+	}
+
+	std::size_t size()
+		/// Returns the number of cached elements
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doReplace();
+		return _data.size();
+	}
+
+	void forceReplace()
+		/// Forces cache replacement. Note that Poco's cache strategy use for efficiency reason no background thread
+		/// which periodically triggers cache replacement. Cache Replacement is only started when the cache is modified
+		/// from outside, i.e. add is called, or when a user tries to access an cache element via get.
+		/// In some cases, i.e. expire based caching where for a long time no access to the cache happens,
+		/// it might be desirable to be able to trigger cache replacement manually.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doReplace();
+	}
+
+	std::set<TKey> getAllKeys()
+		/// Returns a copy of all keys stored in the cache
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		doReplace();
+		ConstIterator it = _data.begin();
+		ConstIterator itEnd = _data.end();
+		std::set<TKey> result;
+		for (; it != itEnd; ++it)
+			result.insert(it->first);
+
+		return result;
+	}
+
+protected:
+	mutable FIFOEvent<ValidArgs<TKey> > IsValid;
+	mutable FIFOEvent<KeySet>           Replace;
+
+	void initialize()
+		/// Sets up event registration.
+	{
+		Add		+= Delegate<TStrategy, const KeyValueArgs<TKey, TValue> >(&_strategy, &TStrategy::onAdd);
+		Update	+= Delegate<TStrategy, const KeyValueArgs<TKey, TValue> >(&_strategy, &TStrategy::onUpdate);
+		Remove	+= Delegate<TStrategy, const TKey>(&_strategy, &TStrategy::onRemove);
+		Get		+= Delegate<TStrategy, const TKey>(&_strategy, &TStrategy::onGet);
+		Clear	+= Delegate<TStrategy, const EventArgs>(&_strategy, &TStrategy::onClear);
+		IsValid	+= Delegate<TStrategy, ValidArgs<TKey> >(&_strategy, &TStrategy::onIsValid);
+		Replace	+= Delegate<TStrategy, KeySet>(&_strategy, &TStrategy::onReplace);
+	}
+
+	void uninitialize()
+		/// Reverts event registration.
+	{
+		Add		-= Delegate<TStrategy, const KeyValueArgs<TKey, TValue> >(&_strategy, &TStrategy::onAdd );
+		Update	-= Delegate<TStrategy, const KeyValueArgs<TKey, TValue> >(&_strategy, &TStrategy::onUpdate);
+		Remove	-= Delegate<TStrategy, const TKey>(&_strategy, &TStrategy::onRemove);
+		Get		-= Delegate<TStrategy, const TKey>(&_strategy, &TStrategy::onGet);
+		Clear	-= Delegate<TStrategy, const EventArgs>(&_strategy, &TStrategy::onClear);
+		IsValid	-= Delegate<TStrategy, ValidArgs<TKey> >(&_strategy, &TStrategy::onIsValid);
+		Replace	-= Delegate<TStrategy, KeySet>(&_strategy, &TStrategy::onReplace);
+	}
+
+	void doAdd(const TKey& key, const TValue& val)
+		/// Adds the key value pair to the cache.
+		/// If for the key already an entry exists, it will be overwritten.
+	{
+		Iterator it = _data.find(key);
+		doRemove(it);
+
+		KeyValueArgs<TKey, TValue> args(key, val);
+		Add.notify(this, args);
+		_data.insert(std::make_pair(key, SharedPtr<TValue>(new TValue(val))));
+		
+		doReplace();
+	}
+
+	void doAdd(const TKey& key, SharedPtr<TValue>& val)
+		/// Adds the key value pair to the cache.
+		/// If for the key already an entry exists, it will be overwritten.
+	{
+		Iterator it = _data.find(key);
+		doRemove(it);
+
+		KeyValueArgs<TKey, TValue> args(key, *val);
+		Add.notify(this, args);
+		_data.insert(std::make_pair(key, val));
+		
+		doReplace();
+	}
+
+	void doUpdate(const TKey& key, const TValue& val)
+		/// Adds the key value pair to the cache.
+		/// If for the key already an entry exists, it will be overwritten.
+	{
+		KeyValueArgs<TKey, TValue> args(key, val);
+		Iterator it = _data.find(key);
+		if (it == _data.end())
+		{
+			Add.notify(this, args);
+			_data.insert(std::make_pair(key, SharedPtr<TValue>(new TValue(val))));
+		}
+		else
+		{
+			Update.notify(this, args);
+			it->second = SharedPtr<TValue>(new TValue(val));
+		}
+		
+		doReplace();
+	}
+
+	void doUpdate(const TKey& key, SharedPtr<TValue>& val)
+		/// Adds the key value pair to the cache.
+		/// If for the key already an entry exists, it will be overwritten.
+	{
+		KeyValueArgs<TKey, TValue> args(key, *val);
+		Iterator it = _data.find(key);
+		if (it == _data.end())
+		{
+			Add.notify(this, args);
+			_data.insert(std::make_pair(key, val));
+		}
+		else
+		{
+			Update.notify(this, args);
+			it->second = val;
+		}
+		
+		doReplace();
+	}
+
+	void doRemove(Iterator it) 
+		/// Removes an entry from the cache. If the entry is not found
+		/// the remove is ignored.
+	{
+		if (it != _data.end())
+		{
+			Remove.notify(this, it->first);
+			_data.erase(it);
+		}
+	}
+
+	bool doHas(const TKey& key) const
+		/// Returns true if the cache contains a value for the key
+	{
+		// ask the strategy if the key is valid
+		ConstIterator it = _data.find(key);
+		bool result = false;
+
+		if (it != _data.end())
+		{
+			ValidArgs<TKey> args(key);
+			IsValid.notify(this, args);
+			result = args.isValid();
+		}
+
+		return result;
+	}
+
+	SharedPtr<TValue> doGet(const TKey& key) 
+		/// Returns a SharedPtr of the cache entry, returns 0 if for
+		/// the key no value was found
+	{
+		Iterator it = _data.find(key);
+		SharedPtr<TValue> result;
+
+		if (it != _data.end())
+		{	
+			// inform all strategies that a read-access to an element happens
+			Get.notify(this, key);
+			// ask all strategies if the key is valid
+			ValidArgs<TKey> args(key);
+			IsValid.notify(this, args);
+
+			if (!args.isValid())
+			{
+				doRemove(it);
+			}
+			else
+			{
+				result = it->second;
+			}
+		}
+
+		return result;
+	}
+
+	void doClear()
+	{
+		static EventArgs _emptyArgs;
+		Clear.notify(this, _emptyArgs);
+		_data.clear();
+	}
+
+	void doReplace()
+	{
+		std::set<TKey> delMe;
+		Replace.notify(this, delMe);
+		// delMe contains the to be removed elements
+		typename std::set<TKey>::const_iterator it    = delMe.begin();
+		typename std::set<TKey>::const_iterator endIt = delMe.end();
+
+		for (; it != endIt; ++it)
+		{
+			Iterator itH = _data.find(*it);
+			doRemove(itH);
+		}
+	}
+
+	TStrategy          _strategy;
+	mutable DataHolder _data;
+	mutable TMutex  _mutex;
+
+private:
+	AbstractCache(const AbstractCache& aCache);
+	AbstractCache& operator = (const AbstractCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AbstractCache_INCLUDED
diff --git a/Poco/AbstractDelegate.h b/Poco/AbstractDelegate.h
new file mode 100644
index 0000000..9dea69a
--- /dev/null
+++ b/Poco/AbstractDelegate.h
@@ -0,0 +1,110 @@
+//
+// AbstractDelegate.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  AbstractDelegate
+//
+// Implementation of the AbstractDelegate template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AbstractDelegate_INCLUDED
+#define Foundation_AbstractDelegate_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class TArgs> 
+class AbstractDelegate
+	/// Base class for Delegate and Expire.
+{
+public:
+	AbstractDelegate()
+	{
+	}
+
+	AbstractDelegate(const AbstractDelegate& /*del*/)
+	{
+	}
+
+	virtual ~AbstractDelegate() 
+	{
+	}
+
+	virtual bool notify(const void* sender, TArgs& arguments) = 0;
+		/// Invokes the delegate's callback function.
+		/// Returns true if successful, or false if the delegate
+		/// has been disabled or has expired.
+
+	virtual bool equals(const AbstractDelegate& other) const = 0;
+		/// Compares the AbstractDelegate with the other one for equality.
+
+	virtual AbstractDelegate* clone() const = 0;
+		/// Returns a deep copy of the AbstractDelegate.
+
+	virtual void disable() = 0;
+		/// Disables the delegate, which is done prior to removal.
+		
+	virtual const AbstractDelegate* unwrap() const
+		/// Returns the unwrapped delegate. Must be overridden by decorators
+		/// like Expire.
+	{
+		return this;
+	}
+};
+
+
+template <> 
+class AbstractDelegate<void>
+	/// Base class for Delegate and Expire.
+{
+public:
+	AbstractDelegate()
+	{
+	}
+
+	AbstractDelegate(const AbstractDelegate&)
+	{
+	}
+
+	virtual ~AbstractDelegate() 
+	{
+	}
+
+	virtual bool notify(const void* sender) = 0;
+		/// Invokes the delegate's callback function.
+		/// Returns true if successful, or false if the delegate
+		/// has been disabled or has expired.
+
+	virtual bool equals(const AbstractDelegate& other) const = 0;
+		/// Compares the AbstractDelegate with the other one for equality.
+
+	virtual AbstractDelegate* clone() const = 0;
+		/// Returns a deep copy of the AbstractDelegate.
+
+	virtual void disable() = 0;
+		/// Disables the delegate, which is done prior to removal.
+		
+	virtual const AbstractDelegate* unwrap() const
+		/// Returns the unwrapped delegate. Must be overridden by decorators
+		/// like Expire.
+	{
+		return this;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AbstractDelegate_INCLUDED
diff --git a/Poco/AbstractEvent.h b/Poco/AbstractEvent.h
new file mode 100644
index 0000000..917092a
--- /dev/null
+++ b/Poco/AbstractEvent.h
@@ -0,0 +1,558 @@
+//
+// AbstractEvent.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  AbstractEvent
+//
+// Definition of the AbstractEvent class.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AbstractFoundation_INCLUDED
+#define Foundation_AbstractFoundation_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/SingletonHolder.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/ActiveResult.h"
+#include "Poco/ActiveMethod.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class TArgs, class TStrategy, class TDelegate, class TMutex = FastMutex>
+class AbstractEvent
+	/// An AbstractEvent is the base class of all events.
+	/// It works similar to the way C# handles notifications (aka events in C#).
+	///
+	/// Events can be used to send information to a set of delegates
+	/// which are registered with the event. The type of the data is specified with
+	/// the template parameter TArgs. The TStrategy parameter must be a subclass
+	/// of NotificationStrategy. The parameter TDelegate can either be a subclass of AbstractDelegate
+	/// or of AbstractPriorityDelegate.
+	///
+	/// Note that AbstractEvent should never be used directly. One ought to use
+	/// one of its subclasses which set the TStrategy and TDelegate template parameters
+	/// to fixed values. For most use-cases the BasicEvent template will be sufficient:
+	///
+	///     #include "Poco/BasicEvent.h"
+	///     #include "Poco/Delegate.h"
+	///
+	/// Note that as of release 1.4.2, the behavior of BasicEvent equals that of FIFOEvent,
+	/// so the FIFOEvent class is no longer necessary and provided for backwards compatibility
+	/// only.
+	///
+	/// BasicEvent works with a standard delegate. They allow one object to register
+	/// one or more delegates with an event. In contrast, a PriorityDelegate comes with an attached priority value
+	/// and allows one object to register for one priority value one or more delegates. Note that PriorityDelegates
+	/// only work with PriorityEvents:
+	///
+	///     #include "Poco/PriorityEvent.h"
+	///     #include "Poco/PriorityDelegate.h"
+	///
+	/// Use events by adding them as public members to the object which is throwing notifications:
+	///
+	///     class MyData
+	///     {
+	///     public:
+	///         Poco::BasicEvent<int> dataChanged;
+	///
+	///         MyData();
+	///         ...
+	///         void setData(int i);
+	///         ...
+	///     private:
+	///         int _data;
+	///     };
+	///
+	/// Firing the event is done either by calling the event's notify() or notifyAsync() method:
+	///
+	///     void MyData::setData(int i)
+	///     {
+	///         this->_data = i;
+	///         dataChanged.notify(this, this->_data);
+	///     }
+	///
+	/// Alternatively, instead of notify(), operator () can be used.
+	///
+	///     void MyData::setData(int i)
+	///     {
+	///         this->_data = i;
+	///         dataChanged(this, this->_data);
+	///     }
+	///
+	/// Note that operator (), notify() and notifyAsync() do not catch exceptions, i.e. in case a
+	/// delegate throws an exception, notifying is immediately aborted and the exception is propagated
+	/// back to the caller.
+	///
+	/// Delegates can register methods at the event. In the case of a BasicEvent
+	/// the Delegate template is used, in case of an PriorityEvent a PriorityDelegate is used.
+	/// Mixing of delegates, e.g. using a PriorityDelegate with a BasicEvent is not allowed and
+	/// can lead to compile-time and/or run-time errors. The standalone delegate() functions
+	/// can be used to construct Delegate objects.
+	///
+	/// Events require the observers to have one of the following method signatures:
+	///
+	///     void onEvent(const void* pSender, TArgs& args);
+	///     void onEvent(TArgs& args);
+	///     static void onEvent(const void* pSender, TArgs& args);
+	///     static void onEvent(void* pSender, TArgs& args);
+	///     static void onEvent(TArgs& args);
+	///
+	/// For performance reasons arguments are always sent by reference. This also allows observers
+	/// to modify the event argument. To prevent that, use <[const TArg]> as template
+	/// parameter. A non-conformant method signature leads to compile errors.
+	///
+	/// Assuming that the observer meets the method signature requirement, it can register
+	/// this method with the += operator:
+	///
+	///     class MyController
+	///     {
+	///     protected:
+	///         MyData _data;
+	///
+	///         void onDataChanged(void* pSender, int& data);
+	///         ...
+	///     };
+	///
+	///     MyController::MyController()
+	///     {
+	///         _data.dataChanged += delegate(this, &MyController::onDataChanged);
+	///     }
+	///
+	/// In some cases it might be desirable to work with automatically expiring registrations. Simply add
+	/// to delegate as 3rd parameter a expireValue (in milliseconds):
+	///
+	///     _data.dataChanged += delegate(this, &MyController::onDataChanged, 1000);
+	///
+	/// This will add a delegate to the event which will automatically be removed in 1000 millisecs.
+	///
+	/// Unregistering happens via the -= operator. Forgetting to unregister a method will lead to
+	/// segmentation faults later, when one tries to send a notify to a no longer existing object.
+	///
+	///     MyController::~MyController()
+	///     {
+	///         _data.dataChanged -= delegate(this, &MyController::onDataChanged);
+	///     }
+	///
+	/// Working with PriorityDelegate's as similar to working with BasicEvent.
+	/// Instead of delegate(), the priorityDelegate() function must be used
+	/// to create the PriorityDelegate.
+{
+public:
+	typedef TDelegate* DelegateHandle;
+	typedef TArgs Args;
+
+	AbstractEvent():
+		_executeAsync(this, &AbstractEvent::executeAsyncImpl),
+		_enabled(true)
+	{
+	}
+
+	AbstractEvent(const TStrategy& strat):
+		_executeAsync(this, &AbstractEvent::executeAsyncImpl),
+		_strategy(strat),
+		_enabled(true)
+	{
+	}
+
+	virtual ~AbstractEvent()
+	{
+	}
+
+	void operator += (const TDelegate& aDelegate)
+		/// Adds a delegate to the event.
+		///
+		/// Exact behavior is determined by the TStrategy.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.add(aDelegate);
+	}
+
+	void operator -= (const TDelegate& aDelegate)
+		/// Removes a delegate from the event.
+		///
+		/// If the delegate is not found, this function does nothing.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.remove(aDelegate);
+	}
+
+	DelegateHandle add(const TDelegate& aDelegate)
+		/// Adds a delegate to the event.
+		///
+		/// Exact behavior is determined by the TStrategy.
+		///
+		/// Returns a DelegateHandle which can be used in call to
+		/// remove() to remove the delegate.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return _strategy.add(aDelegate);
+	}
+
+	void remove(DelegateHandle delegateHandle)
+		/// Removes a delegate from the event using a DelegateHandle
+		/// returned by add().
+		///
+		/// If the delegate is not found, this function does nothing.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.remove(delegateHandle);
+	}
+
+	void operator () (const void* pSender, TArgs& args)
+		/// Shortcut for notify(pSender, args);
+	{
+		notify(pSender, args);
+	}
+
+	void operator () (TArgs& args)
+		/// Shortcut for notify(args).
+	{
+		notify(0, args);
+	}
+
+	void notify(const void* pSender, TArgs& args)
+		/// Sends a notification to all registered delegates. The order is
+		/// determined by the TStrategy. This method is blocking. While executing,
+		/// the list of delegates may be modified. These changes don't
+		/// influence the current active notifications but are activated with
+		/// the next notify. If a delegate is removed during a notify(), the
+		/// delegate will no longer be invoked (unless it has already been
+		/// invoked prior to removal). If one of the delegates throws an exception,
+		/// the notify method is immediately aborted and the exception is propagated
+		/// to the caller.
+	{
+		Poco::ScopedLockWithUnlock<TMutex> lock(_mutex);
+
+		if (!_enabled) return;
+
+		// thread-safeness:
+		// copy should be faster and safer than blocking until
+		// execution ends
+		TStrategy strategy(_strategy);
+		lock.unlock();
+		strategy.notify(pSender, args);
+	}
+
+	bool hasDelegates() const {
+		return !empty();
+	}
+
+	ActiveResult<TArgs> notifyAsync(const void* pSender, const TArgs& args)
+		/// Sends a notification to all registered delegates. The order is
+		/// determined by the TStrategy. This method is not blocking and will
+		/// immediately return. The delegates are invoked in a seperate thread.
+		/// Call activeResult.wait() to wait until the notification has ended.
+		/// While executing, other objects can change the delegate list. These changes don't
+		/// influence the current active notifications but are activated with
+		/// the next notify. If a delegate is removed during a notify(), the
+		/// delegate will no longer be invoked (unless it has already been
+		/// invoked prior to removal). If one of the delegates throws an exception,
+		/// the execution is aborted and the exception is propagated to the caller.
+	{
+		NotifyAsyncParams params(pSender, args);
+		{
+			typename TMutex::ScopedLock lock(_mutex);
+
+			// thread-safeness:
+			// copy should be faster and safer than blocking until
+			// execution ends
+			// make a copy of the strategy here to guarantee that
+			// between notifyAsync and the execution of the method no changes can occur
+
+			params.ptrStrat = SharedPtr<TStrategy>(new TStrategy(_strategy));
+			params.enabled  = _enabled;
+		}
+		ActiveResult<TArgs> result = _executeAsync(params);
+		return result;
+	}
+
+	void enable()
+		/// Enables the event.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_enabled = true;
+	}
+
+	void disable()
+		/// Disables the event. notify and notifyAsnyc will be ignored,
+		/// but adding/removing delegates is still allowed.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_enabled = false;
+	}
+
+	bool isEnabled() const
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return _enabled;
+	}
+
+	void clear()
+		/// Removes all delegates.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.clear();
+	}
+
+	bool empty() const
+		/// Checks if any delegates are registered at the delegate.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return _strategy.empty();
+	}
+
+protected:
+	struct NotifyAsyncParams
+	{
+		SharedPtr<TStrategy> ptrStrat;
+		const void* pSender;
+		TArgs       args;
+		bool        enabled;
+
+		NotifyAsyncParams(const void* pSend, const TArgs& a):ptrStrat(), pSender(pSend), args(a), enabled(true)
+			/// Default constructor reduces the need for TArgs to have an empty constructor, only copy constructor is needed.
+		{
+		}
+	};
+
+	ActiveMethod<TArgs, NotifyAsyncParams, AbstractEvent> _executeAsync;
+
+	TArgs executeAsyncImpl(const NotifyAsyncParams& par)
+	{
+		if (!par.enabled)
+		{
+			return par.args;
+		}
+
+		NotifyAsyncParams params = par;
+		TArgs retArgs(params.args);
+		params.ptrStrat->notify(params.pSender, retArgs);
+		return retArgs;
+	}
+
+	TStrategy _strategy; /// The strategy used to notify observers.
+	bool      _enabled;  /// Stores if an event is enabled. Notfies on disabled events have no effect
+	                     /// but it is possible to change the observers.
+	mutable TMutex _mutex;
+
+private:
+	AbstractEvent(const AbstractEvent& other);
+	AbstractEvent& operator = (const AbstractEvent& other);
+};
+
+
+template <class TStrategy, class TDelegate, class TMutex>
+class AbstractEvent<void, TStrategy, TDelegate, TMutex>
+{
+public:
+	typedef TDelegate* DelegateHandle;
+
+	AbstractEvent():
+		_executeAsync(this, &AbstractEvent::executeAsyncImpl),
+		_enabled(true)
+	{
+	}
+
+	AbstractEvent(const TStrategy& strat):
+		_executeAsync(this, &AbstractEvent::executeAsyncImpl),
+		_strategy(strat),
+		_enabled(true)
+	{
+	}
+
+	virtual ~AbstractEvent()
+	{
+	}
+
+	void operator += (const TDelegate& aDelegate)
+		/// Adds a delegate to the event.
+		///
+		/// Exact behavior is determined by the TStrategy.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.add(aDelegate);
+	}
+
+	void operator -= (const TDelegate& aDelegate)
+		/// Removes a delegate from the event.
+		///
+		/// If the delegate is not found, this function does nothing.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.remove(aDelegate);
+	}
+
+	DelegateHandle add(const TDelegate& aDelegate)
+		/// Adds a delegate to the event.
+		///
+		/// Exact behavior is determined by the TStrategy.
+		///
+		/// Returns a DelegateHandle which can be used in call to
+		/// remove() to remove the delegate.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return _strategy.add(aDelegate);
+	}
+
+	void remove(DelegateHandle delegateHandle)
+		/// Removes a delegate from the event using a DelegateHandle
+		/// returned by add().
+		///
+		/// If the delegate is not found, this function does nothing.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.remove(delegateHandle);
+	}
+
+	void operator () (const void* pSender)
+		/// Shortcut for notify(pSender, args);
+	{
+		notify(pSender);
+	}
+
+	void operator () ()
+		/// Shortcut for notify(args).
+	{
+		notify(0);
+	}
+
+	void notify(const void* pSender)
+		/// Sends a notification to all registered delegates. The order is
+		/// determined by the TStrategy. This method is blocking. While executing,
+		/// the list of delegates may be modified. These changes don't
+		/// influence the current active notifications but are activated with
+		/// the next notify. If a delegate is removed during a notify(), the
+		/// delegate will no longer be invoked (unless it has already been
+		/// invoked prior to removal). If one of the delegates throws an exception,
+		/// the notify method is immediately aborted and the exception is propagated
+		/// to the caller.
+	{
+		Poco::ScopedLockWithUnlock<TMutex> lock(_mutex);
+
+		if (!_enabled) return;
+
+		// thread-safeness:
+		// copy should be faster and safer than blocking until
+		// execution ends
+		TStrategy strategy(_strategy);
+		lock.unlock();
+		strategy.notify(pSender);
+	}
+
+	ActiveResult<void> notifyAsync(const void* pSender)
+		/// Sends a notification to all registered delegates. The order is
+		/// determined by the TStrategy. This method is not blocking and will
+		/// immediately return. The delegates are invoked in a seperate thread.
+		/// Call activeResult.wait() to wait until the notification has ended.
+		/// While executing, other objects can change the delegate list. These changes don't
+		/// influence the current active notifications but are activated with
+		/// the next notify. If a delegate is removed during a notify(), the
+		/// delegate will no longer be invoked (unless it has already been
+		/// invoked prior to removal). If one of the delegates throws an exception,
+		/// the execution is aborted and the exception is propagated to the caller.
+	{
+		NotifyAsyncParams params(pSender);
+		{
+			typename TMutex::ScopedLock lock(_mutex);
+
+			// thread-safeness:
+			// copy should be faster and safer than blocking until
+			// execution ends
+			// make a copy of the strategy here to guarantee that
+			// between notifyAsync and the execution of the method no changes can occur
+
+			params.ptrStrat = SharedPtr<TStrategy>(new TStrategy(_strategy));
+			params.enabled  = _enabled;
+		}
+		ActiveResult<void> result = _executeAsync(params);
+		return result;
+	}
+
+	void enable()
+		/// Enables the event.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_enabled = true;
+	}
+
+	void disable()
+		/// Disables the event. notify and notifyAsnyc will be ignored,
+		/// but adding/removing delegates is still allowed.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_enabled = false;
+	}
+
+	bool isEnabled() const
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return _enabled;
+	}
+
+	void clear()
+		/// Removes all delegates.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		_strategy.clear();
+	}
+
+	bool empty() const
+		/// Checks if any delegates are registered at the delegate.
+	{
+		typename TMutex::ScopedLock lock(_mutex);
+		return _strategy.empty();
+	}
+
+protected:
+	struct NotifyAsyncParams
+	{
+		SharedPtr<TStrategy> ptrStrat;
+		const void* pSender;
+		bool        enabled;
+
+		NotifyAsyncParams(const void* pSend):ptrStrat(), pSender(pSend), enabled(true)
+			/// Default constructor reduces the need for TArgs to have an empty constructor, only copy constructor is needed.
+		{
+		}
+	};
+
+	ActiveMethod<void, NotifyAsyncParams, AbstractEvent> _executeAsync;
+
+	void executeAsyncImpl(const NotifyAsyncParams& par)
+	{
+		if (!par.enabled)
+		{
+			return;
+		}
+
+		NotifyAsyncParams params = par;
+		params.ptrStrat->notify(params.pSender);
+		return;
+	}
+
+	TStrategy _strategy; /// The strategy used to notify observers.
+	bool      _enabled;  /// Stores if an event is enabled. Notfies on disabled events have no effect
+	                     /// but it is possible to change the observers.
+	mutable TMutex _mutex;
+
+private:
+	AbstractEvent(const AbstractEvent& other);
+	AbstractEvent& operator = (const AbstractEvent& other);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AbstractFoundation_INCLUDED
diff --git a/Poco/AbstractObserver.h b/Poco/AbstractObserver.h
new file mode 100644
index 0000000..baa40a6
--- /dev/null
+++ b/Poco/AbstractObserver.h
@@ -0,0 +1,50 @@
+//
+// AbstractObserver.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  NotificationCenter
+//
+// Definition of the AbstractObserver class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AbstractObserver_INCLUDED
+#define Foundation_AbstractObserver_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Notification.h"
+
+
+namespace Poco {
+
+
+class Foundation_API AbstractObserver
+	/// The base class for all instantiations of
+	/// the Observer and NObserver template classes.
+{
+public:
+	AbstractObserver();
+	AbstractObserver(const AbstractObserver& observer);
+	virtual ~AbstractObserver();
+	
+	AbstractObserver& operator = (const AbstractObserver& observer);
+
+	virtual void notify(Notification* pNf) const = 0;
+	virtual bool equals(const AbstractObserver& observer) const = 0;
+	virtual bool accepts(Notification* pNf) const = 0;
+	virtual AbstractObserver* clone() const = 0;
+	virtual void disable() = 0;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AbstractObserver_INCLUDED
diff --git a/Poco/AbstractPriorityDelegate.h b/Poco/AbstractPriorityDelegate.h
new file mode 100644
index 0000000..c27bc0c
--- /dev/null
+++ b/Poco/AbstractPriorityDelegate.h
@@ -0,0 +1,63 @@
+//
+// AbstractPriorityDelegate.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  AbstractPriorityDelegate
+//
+// Implementation of the AbstractPriorityDelegate template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AbstractPriorityDelegate_INCLUDED
+#define Foundation_AbstractPriorityDelegate_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractDelegate.h"
+
+
+namespace Poco {
+
+
+template <class TArgs> 
+class AbstractPriorityDelegate: public AbstractDelegate<TArgs>
+	/// Base class for PriorityDelegate and PriorityExpire.
+	///
+	/// Extends AbstractDelegate with a priority value.
+{
+public:
+	AbstractPriorityDelegate(int prio):
+		_priority(prio)
+	{
+	}
+
+	AbstractPriorityDelegate(const AbstractPriorityDelegate& del):
+		AbstractDelegate<TArgs>(del),
+		_priority(del._priority)
+	{
+	}
+
+	virtual ~AbstractPriorityDelegate() 
+	{
+	}
+
+	int priority() const
+	{
+		return _priority;
+	}
+
+protected:
+	int _priority;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AbstractPriorityDelegate_INCLUDED
diff --git a/Poco/AbstractStrategy.h b/Poco/AbstractStrategy.h
new file mode 100644
index 0000000..8d0ac25
--- /dev/null
+++ b/Poco/AbstractStrategy.h
@@ -0,0 +1,77 @@
+//
+// AbstractStrategy.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  AbstractCache
+//
+// Definition of the AbstractStrategy class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AbstractStrategy_INCLUDED
+#define Foundation_AbstractStrategy_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/EventArgs.h"
+#include <set>
+
+
+namespace Poco {
+
+
+template <class TKey, class TValue> 
+class AbstractStrategy
+	/// An AbstractStrategy is the interface for all strategies. 
+{
+public:
+	AbstractStrategy()
+	{
+	}
+
+	virtual ~AbstractStrategy()
+	{
+	}
+
+	virtual void onUpdate(const void* pSender, const KeyValueArgs <TKey, TValue>& args)
+		/// Updates an existing entry.
+	{
+		onRemove(pSender,args.key());
+		onAdd(pSender, args);
+	}
+	
+	virtual void onAdd(const void* pSender, const KeyValueArgs <TKey, TValue>& key) = 0;
+		/// Adds the key to the strategy.
+		/// If for the key already an entry exists, an exception will be thrown.
+
+	virtual void onRemove(const void* pSender, const TKey& key) = 0;
+		/// Removes an entry from the strategy. If the entry is not found
+		/// the remove is ignored.
+
+	virtual void onGet(const void* pSender, const TKey& key) = 0;
+		/// Informs the strategy that a read-access happens to an element.
+
+	virtual void onClear(const void* pSender, const EventArgs& args) = 0;
+		/// Removes all elements from the cache.
+
+	virtual void onIsValid(const void* pSender, ValidArgs<TKey>& key) = 0;
+		/// Used to query if a key is still valid (i.e. cached).
+
+	virtual void onReplace(const void* pSender, std::set<TKey>& elemsToRemove) = 0;
+		/// Used by the Strategy to indicate which elements should be removed from
+		/// the cache. Note that onReplace does not change the current list of keys.
+		/// The cache object is reponsible to remove the elements.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AbstractStrategy_INCLUDED
diff --git a/Poco/AccessExpirationDecorator.h b/Poco/AccessExpirationDecorator.h
new file mode 100644
index 0000000..9978185
--- /dev/null
+++ b/Poco/AccessExpirationDecorator.h
@@ -0,0 +1,83 @@
+//
+// AccessExpirationDecorator.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  AccessExpirationDecorator
+//
+// Implementation of the AccessExpirationDecorator template.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AccessExpirationDecorator_INCLUDED
+#define Foundation_AccessExpirationDecorator_INCLUDED
+
+
+#include "Poco/Timestamp.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+
+
+template <typename TArgs>
+class AccessExpirationDecorator
+	/// AccessExpirationDecorator adds an expiration method to values so that they can be used
+	/// with the UniqueAccessExpireCache
+{
+public:
+	AccessExpirationDecorator():
+		_value(),
+		_span()
+	{
+	}
+
+	AccessExpirationDecorator(const TArgs& p, const Poco::Timespan::TimeDiff& diffInMs):
+			/// Creates an element that will expire in diff milliseconds
+		_value(p),
+		_span(diffInMs*1000)
+	{
+	}
+
+	AccessExpirationDecorator(const TArgs& p, const Poco::Timespan& timeSpan):
+		/// Creates an element that will expire after the given timeSpan
+		_value(p),
+		_span(timeSpan)
+	{
+	}
+
+
+	~AccessExpirationDecorator()
+	{
+	}
+	
+	const Poco::Timespan& getTimeout() const
+	{
+		return _span;
+	}
+
+	const TArgs& value() const
+	{
+		return _value;
+	}
+
+	TArgs& value()
+	{
+		return _value;
+	}
+
+private:
+	TArgs     _value;
+	Timespan  _span;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AccessExpirationDecorator_INCLUDED
diff --git a/Poco/AccessExpireCache.h b/Poco/AccessExpireCache.h
new file mode 100644
index 0000000..bb5c571
--- /dev/null
+++ b/Poco/AccessExpireCache.h
@@ -0,0 +1,63 @@
+//
+// AccessExpireCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  AccessExpireCache
+//
+// Definition of the AccessExpireCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AccessExpireCache_INCLUDED
+#define Foundation_AccessExpireCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/AccessExpireStrategy.h"
+
+
+namespace Poco {
+
+
+template <
+	class TKey, 
+	class TValue, 
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+> 
+class AccessExpireCache: public AbstractCache<TKey, TValue, AccessExpireStrategy<TKey, TValue>, TMutex, TEventMutex>
+	/// An AccessExpireCache caches entries for a fixed time period (per default 10 minutes).
+	/// Entries expire when they are not accessed with get() during this time period. Each access resets
+	/// the start time for expiration.
+	/// Be careful when using an AccessExpireCache. A cache is often used
+	/// like cache.has(x) followed by cache.get x). Note that it could happen
+	/// that the "has" call works, then the current execution thread gets descheduled, time passes,
+	/// the entry gets invalid, thus leading to an empty SharedPtr being returned 
+	/// when "get" is invoked.
+{
+public:
+	AccessExpireCache(Timestamp::TimeDiff expire = 600000): 
+		AbstractCache<TKey, TValue, AccessExpireStrategy<TKey, TValue>, TMutex, TEventMutex>(AccessExpireStrategy<TKey, TValue>(expire))
+	{
+	}
+
+	~AccessExpireCache()
+	{
+	}
+
+private:
+	AccessExpireCache(const AccessExpireCache& aCache);
+	AccessExpireCache& operator = (const AccessExpireCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AccessExpireCache_INCLUDED
diff --git a/Poco/AccessExpireLRUCache.h b/Poco/AccessExpireLRUCache.h
new file mode 100644
index 0000000..278cbbc
--- /dev/null
+++ b/Poco/AccessExpireLRUCache.h
@@ -0,0 +1,62 @@
+//
+// AccessExpireLRUCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  AccessExpireLRUCache
+//
+// Definition of the AccessExpireLRUCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AccessExpireLRUCache_INCLUDED
+#define Foundation_AccessExpireLRUCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/StrategyCollection.h"
+#include "Poco/AccessExpireStrategy.h"
+#include "Poco/LRUStrategy.h"
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+>
+class AccessExpireLRUCache: public AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>
+	/// An AccessExpireLRUCache combines LRU caching and time based expire caching.
+	/// It cache entries for a fixed time period (per default 10 minutes)
+	/// but also limits the size of the cache (per default: 1024).
+{
+public:
+	AccessExpireLRUCache(long cacheSize = 1024, Timestamp::TimeDiff expire = 600000): 
+		AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex >(StrategyCollection<TKey, TValue>())
+	{
+		this->_strategy.pushBack(new LRUStrategy<TKey, TValue>(cacheSize));
+		this->_strategy.pushBack(new AccessExpireStrategy<TKey, TValue>(expire));
+	}
+
+	~AccessExpireLRUCache()
+	{
+	}
+
+private:
+	AccessExpireLRUCache(const AccessExpireLRUCache& aCache);
+	AccessExpireLRUCache& operator = (const AccessExpireLRUCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AccessExpireLRUCache_INCLUDED
diff --git a/Poco/AccessExpireStrategy.h b/Poco/AccessExpireStrategy.h
new file mode 100644
index 0000000..3bfa45c
--- /dev/null
+++ b/Poco/AccessExpireStrategy.h
@@ -0,0 +1,74 @@
+//
+// AccessExpireStrategy.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  AccessExpireStrategy
+//
+// Definition of the AccessExpireStrategy class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AccessExpireStrategy_INCLUDED
+#define Foundation_AccessExpireStrategy_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/ExpireStrategy.h"
+#include "Poco/Bugcheck.h"
+#include "Poco/Timestamp.h"
+#include "Poco/EventArgs.h"
+#include <set>
+#include <map>
+
+
+namespace Poco {
+
+
+template <
+	class TKey,
+	class TValue
+>
+class AccessExpireStrategy: public ExpireStrategy<TKey, TValue>
+	/// An AccessExpireStrategy implements time and access based expiration of cache entries
+{
+public:
+	AccessExpireStrategy(Timestamp::TimeDiff expireTimeInMilliSec): ExpireStrategy<TKey, TValue>(expireTimeInMilliSec)
+		/// Create an expire strategy. Note that the smallest allowed caching time is 25ms.
+		/// Anything lower than that is not useful with current operating systems.
+	{
+	}
+
+	~AccessExpireStrategy()
+	{
+	}
+
+	void onGet(const void*, const TKey& key)
+	{
+		// get triggers an update to the expiration time
+		typename ExpireStrategy<TKey, TValue>::Iterator it = this->_keys.find(key);
+		if (it != this->_keys.end())
+		{
+			if (!it->second->first.isElapsed(this->_expireTime)) // don't extend if already expired
+			{
+				this->_keyIndex.erase(it->second);
+				Timestamp now;
+				typename ExpireStrategy<TKey, TValue>::IndexIterator itIdx =
+					this->_keyIndex.insert(typename ExpireStrategy<TKey, TValue>::TimeIndex::value_type(now, key));
+				it->second = itIdx;
+			}
+		}
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AccessExpireStrategy_INCLUDED
diff --git a/Poco/ActiveDispatcher.h b/Poco/ActiveDispatcher.h
new file mode 100644
index 0000000..7550a2d
--- /dev/null
+++ b/Poco/ActiveDispatcher.h
@@ -0,0 +1,116 @@
+//
+// ActiveDispatcher.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ActiveObjects
+//
+// Definition of the ActiveDispatcher class.
+//
+// Copyright (c) 2006-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ActiveDispatcher_INCLUDED
+#define Foundation_ActiveDispatcher_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/Thread.h"
+#include "Poco/ActiveStarter.h"
+#include "Poco/ActiveRunnable.h"
+#include "Poco/NotificationQueue.h"
+
+
+namespace Poco {
+
+
+class Foundation_API ActiveDispatcher: protected Runnable
+	/// This class is used to implement an active object
+	/// with strictly serialized method execution.
+	///
+	/// An active object, which is an ordinary object
+	/// containing ActiveMethod members, executes all
+	/// active methods in their own thread. 
+	/// This behavior does not fit the "classic"
+	/// definition of an active object, which serializes
+	/// the execution of active methods (in other words,
+	/// only one active method can be running at any given
+	/// time).
+	///
+	/// Using this class as a base class, the serializing
+	/// behavior for active objects can be implemented.
+	/// 
+	/// The following example shows how this is done:
+	///
+	///     class ActiveObject: public ActiveDispatcher
+	///     {
+	///     public:
+	///         ActiveObject():
+	///             exampleActiveMethod(this, &ActiveObject::exampleActiveMethodImpl)
+	///         {
+	///         }
+	///
+	///         ActiveMethod<std::string, std::string, ActiveObject, ActiveStarter<ActiveDispatcher> > exampleActiveMethod;
+	///
+	///     protected:
+	///         std::string exampleActiveMethodImpl(const std::string& arg)
+	///         {
+	///             ...
+	///         }
+	///     };
+	///
+	/// The only things different from the example in
+	/// ActiveMethod is that the ActiveObject in this case
+	/// inherits from ActiveDispatcher, and that the ActiveMethod
+	/// template for exampleActiveMethod has an additional parameter,
+	/// specifying the specialized ActiveStarter for ActiveDispatcher.
+{
+public:
+	ActiveDispatcher();
+		/// Creates the ActiveDispatcher.
+
+	ActiveDispatcher(Thread::Priority prio);
+		/// Creates the ActiveDispatcher and sets
+		/// the priority of its thread.
+
+	virtual ~ActiveDispatcher();
+		/// Destroys the ActiveDispatcher.
+
+	void start(ActiveRunnableBase::Ptr pRunnable);
+		/// Adds the Runnable to the dispatch queue.
+
+	void cancel();
+		/// Cancels all queued methods.
+		
+protected:
+	void run();
+	void stop();
+
+private:
+	Thread            _thread;
+	NotificationQueue _queue;
+};
+
+
+template <>
+class ActiveStarter<ActiveDispatcher>
+	/// A specialization of ActiveStarter
+	/// for ActiveDispatcher.
+{
+public:
+	static void start(ActiveDispatcher* pOwner, ActiveRunnableBase::Ptr pRunnable)
+	{
+		pOwner->start(pRunnable);
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ActiveDispatcher_INCLUDED
diff --git a/Poco/ActiveMethod.h b/Poco/ActiveMethod.h
new file mode 100644
index 0000000..cefd8f7
--- /dev/null
+++ b/Poco/ActiveMethod.h
@@ -0,0 +1,218 @@
+//
+// ActiveMethod.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ActiveObjects
+//
+// Definition of the ActiveMethod class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ActiveMethod_INCLUDED
+#define Foundation_ActiveMethod_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/ActiveResult.h"
+#include "Poco/ActiveRunnable.h"
+#include "Poco/ActiveStarter.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+
+
+template <class ResultType, class ArgType, class OwnerType, class StarterType = ActiveStarter<OwnerType> >
+class ActiveMethod
+	/// An active method is a method that, when called, executes
+	/// in its own thread. ActiveMethod's take exactly one
+	/// argument and can return a value. To pass more than one
+	/// argument to the method, use a struct.
+	/// The following example shows how to add an ActiveMethod
+	/// to a class:
+	///
+	///     class ActiveObject
+	///     {
+	///     public:
+	///         ActiveObject():
+	///             exampleActiveMethod(this, &ActiveObject::exampleActiveMethodImpl)
+	///         {
+	///         }
+	///
+	///         ActiveMethod<std::string, std::string, ActiveObject> exampleActiveMethod;
+	///
+	///     protected:
+	///         std::string exampleActiveMethodImpl(const std::string& arg)
+	///         {
+	///             ...
+	///         }
+	///     };
+	///
+	/// And following is an example that shows how to invoke an ActiveMethod.
+	///
+	///     ActiveObject myActiveObject;
+	///     ActiveResult<std::string> result = myActiveObject.exampleActiveMethod("foo");
+	///     ...
+	///     result.wait();
+	///     std::cout << result.data() << std::endl;
+	///
+	/// The way an ActiveMethod is started can be changed by passing a StarterType
+	/// template argument with a corresponding class. The default ActiveStarter
+	/// starts the method in its own thread, obtained from a thread pool.
+	///
+	/// For an alternative implementation of StarterType, see ActiveDispatcher.
+	///
+	/// For methods that do not require an argument or a return value, the Void
+	/// class can be used.
+{
+public:
+	typedef ResultType (OwnerType::*Callback)(const ArgType&);
+	typedef ActiveResult<ResultType> ActiveResultType;
+	typedef ActiveRunnable<ResultType, ArgType, OwnerType> ActiveRunnableType;
+
+	ActiveMethod(OwnerType* pOwner, Callback method):
+		_pOwner(pOwner),
+		_method(method)
+		/// Creates an ActiveMethod object.
+	{
+		poco_check_ptr (pOwner);
+	}
+	
+	ActiveResultType operator () (const ArgType& arg)
+		/// Invokes the ActiveMethod.
+	{
+		ActiveResultType result(new ActiveResultHolder<ResultType>());
+		ActiveRunnableBase::Ptr pRunnable(new ActiveRunnableType(_pOwner, _method, arg, result));
+		StarterType::start(_pOwner, pRunnable);
+		return result;
+	}
+		
+	ActiveMethod(const ActiveMethod& other):
+		_pOwner(other._pOwner),
+		_method(other._method)
+	{
+	}
+
+	ActiveMethod& operator = (const ActiveMethod& other)
+	{
+		ActiveMethod tmp(other);
+		swap(tmp);
+		return *this;
+	}
+
+	void swap(ActiveMethod& other)
+	{
+		std::swap(_pOwner, other._pOwner);
+		std::swap(_method, other._method);
+	}
+
+private:
+	ActiveMethod();
+
+	OwnerType* _pOwner;
+	Callback   _method;
+};
+
+
+
+template <class ResultType, class OwnerType, class StarterType>
+class ActiveMethod <ResultType, void, OwnerType, StarterType>
+	/// An active method is a method that, when called, executes
+	/// in its own thread. ActiveMethod's take exactly one
+	/// argument and can return a value. To pass more than one
+	/// argument to the method, use a struct.
+	/// The following example shows how to add an ActiveMethod
+	/// to a class:
+	///
+	///     class ActiveObject
+	///     {
+	///     public:
+	///         ActiveObject():
+	///             exampleActiveMethod(this, &ActiveObject::exampleActiveMethodImpl)
+	///         {
+	///         }
+	///
+	///         ActiveMethod<std::string, std::string, ActiveObject> exampleActiveMethod;
+	///
+	///     protected:
+	///         std::string exampleActiveMethodImpl(const std::string& arg)
+	///         {
+	///             ...
+	///         }
+	///     };
+	///
+	/// And following is an example that shows how to invoke an ActiveMethod.
+	///
+	///     ActiveObject myActiveObject;
+	///     ActiveResult<std::string> result = myActiveObject.exampleActiveMethod("foo");
+	///     ...
+	///     result.wait();
+	///     std::cout << result.data() << std::endl;
+	///
+	/// The way an ActiveMethod is started can be changed by passing a StarterType
+	/// template argument with a corresponding class. The default ActiveStarter
+	/// starts the method in its own thread, obtained from a thread pool.
+	///
+	/// For an alternative implementation of StarterType, see ActiveDispatcher.
+	///
+	/// For methods that do not require an argument or a return value, simply use void.
+{
+public:
+	typedef ResultType (OwnerType::*Callback)(void);
+	typedef ActiveResult<ResultType> ActiveResultType;
+	typedef ActiveRunnable<ResultType, void, OwnerType> ActiveRunnableType;
+
+	ActiveMethod(OwnerType* pOwner, Callback method):
+		_pOwner(pOwner),
+		_method(method)
+		/// Creates an ActiveMethod object.
+	{
+		poco_check_ptr (pOwner);
+	}
+	
+	ActiveResultType operator () (void)
+		/// Invokes the ActiveMethod.
+	{
+		ActiveResultType result(new ActiveResultHolder<ResultType>());
+		ActiveRunnableBase::Ptr pRunnable(new ActiveRunnableType(_pOwner, _method, result));
+		StarterType::start(_pOwner, pRunnable);
+		return result;
+	}
+		
+	ActiveMethod(const ActiveMethod& other):
+		_pOwner(other._pOwner),
+		_method(other._method)
+	{
+	}
+
+	ActiveMethod& operator = (const ActiveMethod& other)
+	{
+		ActiveMethod tmp(other);
+		swap(tmp);
+		return *this;
+	}
+
+	void swap(ActiveMethod& other)
+	{
+		std::swap(_pOwner, other._pOwner);
+		std::swap(_method, other._method);
+	}
+
+private:
+	ActiveMethod();
+
+	OwnerType* _pOwner;
+	Callback   _method;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ActiveMethod_INCLUDED
diff --git a/Poco/ActiveResult.h b/Poco/ActiveResult.h
new file mode 100644
index 0000000..4cdc0ed
--- /dev/null
+++ b/Poco/ActiveResult.h
@@ -0,0 +1,495 @@
+//
+// ActiveResult.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ActiveObjects
+//
+// Definition of the ActiveResult class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ActiveResult_INCLUDED
+#define Foundation_ActiveResult_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Exception.h"
+#include <algorithm>
+
+
+namespace Poco {
+
+
+template <class ResultType>
+class ActiveResultHolder: public RefCountedObject
+	/// This class holds the result of an asynchronous method
+	/// invocation. It is used to pass the result from the
+	/// execution thread back to the invocation thread. 
+	/// The class uses reference counting for memory management.
+	/// Do not use this class directly, use ActiveResult instead.
+{
+public:
+	ActiveResultHolder():
+		_pData(0),
+		_pExc(0),
+		_event(false)
+		/// Creates an ActiveResultHolder.
+	{
+	}
+		
+	ResultType& data()
+		/// Returns a reference to the actual result.
+	{
+		poco_check_ptr(_pData);
+		return *_pData;
+	}
+	
+	void data(ResultType* pData)
+	{
+		delete _pData;
+		_pData = pData;
+	}
+	
+	void wait()
+		/// Pauses the caller until the result becomes available.
+	{
+		_event.wait();
+	}
+	
+	bool tryWait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Returns true if the result became
+		/// available, false otherwise.
+	{
+		return _event.tryWait(milliseconds);
+	}
+	
+	void wait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Throws a TimeoutException if the
+		/// result did not became available.
+	{
+		_event.wait(milliseconds);
+	}
+	
+	void notify()
+		/// Notifies the invoking thread that the result became available.
+	{
+		_event.set();
+	}
+	
+	bool failed() const
+		/// Returns true if the active method failed (and threw an exception).
+		/// Information about the exception can be obtained by calling error().
+	{
+		return _pExc != 0;
+	}
+	
+	std::string error() const
+		/// If the active method threw an exception, a textual representation
+		/// of the exception is returned. An empty string is returned if the
+		/// active method completed successfully.
+	{
+		if (_pExc)
+			return _pExc->message();
+		else
+			return std::string();
+	}
+	
+	Exception* exception() const
+		/// If the active method threw an exception, a clone of the exception
+		/// object is returned, otherwise null.
+	{
+		return _pExc;
+	}
+	
+	void error(const Exception& exc)
+		/// Sets the exception.
+	{
+		delete _pExc;
+		_pExc = exc.clone();
+	}
+	
+	void error(const std::string& msg)
+		/// Sets the exception.
+	{
+		delete _pExc;
+		_pExc = new UnhandledException(msg);
+	}
+
+protected:
+	~ActiveResultHolder()
+	{
+		delete _pData;
+		delete _pExc;
+	}
+
+private:
+	ResultType* _pData;
+	Exception*  _pExc;
+	Event       _event;
+};
+
+
+
+template <>
+class ActiveResultHolder<void>: public RefCountedObject
+{
+public:
+	ActiveResultHolder():
+		_pExc(0),
+		_event(false)
+		/// Creates an ActiveResultHolder.
+	{
+	}
+	
+	void wait()
+		/// Pauses the caller until the result becomes available.
+	{
+		_event.wait();
+	}
+	
+	bool tryWait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Returns true if the result became
+		/// available, false otherwise.
+	{
+		return _event.tryWait(milliseconds);
+	}
+	
+	void wait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Throws a TimeoutException if the
+		/// result did not became available.
+	{
+		_event.wait(milliseconds);
+	}
+	
+	void notify()
+		/// Notifies the invoking thread that the result became available.
+	{
+		_event.set();
+	}
+	
+	bool failed() const
+		/// Returns true if the active method failed (and threw an exception).
+		/// Information about the exception can be obtained by calling error().
+	{
+		return _pExc != 0;
+	}
+	
+	std::string error() const
+		/// If the active method threw an exception, a textual representation
+		/// of the exception is returned. An empty string is returned if the
+		/// active method completed successfully.
+	{
+		if (_pExc)
+			return _pExc->message();
+		else
+			return std::string();
+	}
+	
+	Exception* exception() const
+		/// If the active method threw an exception, a clone of the exception
+		/// object is returned, otherwise null.
+	{
+		return _pExc;
+	}
+	
+	void error(const Exception& exc)
+		/// Sets the exception.
+	{
+		delete _pExc;
+		_pExc = exc.clone();
+	}
+	
+	void error(const std::string& msg)
+		/// Sets the exception.
+	{
+		delete _pExc;
+		_pExc = new UnhandledException(msg);
+	}
+
+protected:
+	~ActiveResultHolder()
+	{
+		delete _pExc;
+	}
+
+private:
+	Exception*  _pExc;
+	Event       _event;
+};
+
+
+template <class RT>
+class ActiveResult
+	/// This class holds the result of an asynchronous method
+	/// invocation (see class ActiveMethod). It is used to pass the 
+	/// result from the execution thread back to the invocation thread. 
+{
+public:
+	typedef RT ResultType;
+	typedef ActiveResultHolder<ResultType> ActiveResultHolderType;
+
+	ActiveResult(ActiveResultHolderType* pHolder):
+		_pHolder(pHolder)
+		/// Creates the active result. For internal use only.
+	{
+		poco_check_ptr (pHolder);
+	}
+	
+	ActiveResult(const ActiveResult& result)
+		/// Copy constructor.
+	{
+		_pHolder = result._pHolder;
+		_pHolder->duplicate();
+	}
+	
+	~ActiveResult()
+		/// Destroys the result.
+	{
+		_pHolder->release();
+	}
+	
+	ActiveResult& operator = (const ActiveResult& result)
+		/// Assignment operator.
+	{
+		ActiveResult tmp(result);
+		swap(tmp);
+		return *this;
+	}
+	
+	void swap(ActiveResult& result)
+	{
+		using std::swap;
+		swap(_pHolder, result._pHolder);
+	}
+	
+	ResultType& data() const
+		/// Returns a reference to the result data.
+	{
+		return _pHolder->data();
+	}
+	
+	void data(ResultType* pValue)
+	{
+		_pHolder->data(pValue);
+	}
+	
+	void wait()
+		/// Pauses the caller until the result becomes available.
+	{
+		_pHolder->wait();
+	}
+	
+	bool tryWait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Returns true if the result became
+		/// available, false otherwise.
+	{
+		return _pHolder->tryWait(milliseconds);
+	}
+	
+	void wait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Throws a TimeoutException if the
+		/// result did not became available.
+	{
+		_pHolder->wait(milliseconds);
+	}
+	
+	bool available() const
+		/// Returns true if a result is available.
+	{
+		return _pHolder->tryWait(0);
+	}
+	
+	bool failed() const
+		/// Returns true if the active method failed (and threw an exception).
+		/// Information about the exception can be obtained by calling error().
+	{
+		return _pHolder->failed();
+	}
+	
+	std::string error() const
+		/// If the active method threw an exception, a textual representation
+		/// of the exception is returned. An empty string is returned if the
+		/// active method completed successfully.
+	{
+		return _pHolder->error();
+	}
+
+	Exception* exception() const
+		/// If the active method threw an exception, a clone of the exception
+		/// object is returned, otherwise null.
+	{
+		return _pHolder->exception();
+	}
+
+	void notify()
+		/// Notifies the invoking thread that the result became available.
+		/// For internal use only.
+	{
+		_pHolder->notify();
+	}
+	
+	ResultType& data()
+		/// Returns a non-const reference to the result data. For internal
+		/// use only.
+	{
+		return _pHolder->data();
+	}
+	
+	void error(const std::string& msg)
+		/// Sets the failed flag and the exception message.
+	{
+		_pHolder->error(msg);
+	}
+
+	void error(const Exception& exc)
+		/// Sets the failed flag and the exception message.
+	{
+		_pHolder->error(exc);
+	}
+	
+private:
+	ActiveResult();
+
+	ActiveResultHolderType* _pHolder;
+};
+
+
+
+template <>
+class ActiveResult<void>
+	/// This class holds the result of an asynchronous method
+	/// invocation (see class ActiveMethod). It is used to pass the 
+	/// result from the execution thread back to the invocation thread. 
+{
+public:
+	typedef ActiveResultHolder<void> ActiveResultHolderType;
+
+	ActiveResult(ActiveResultHolderType* pHolder):
+		_pHolder(pHolder)
+		/// Creates the active result. For internal use only.
+	{
+		poco_check_ptr (pHolder);
+	}
+	
+	ActiveResult(const ActiveResult& result)
+		/// Copy constructor.
+	{
+		_pHolder = result._pHolder;
+		_pHolder->duplicate();
+	}
+	
+	~ActiveResult()
+		/// Destroys the result.
+	{
+		_pHolder->release();
+	}
+	
+	ActiveResult& operator = (const ActiveResult& result)
+		/// Assignment operator.
+	{
+		ActiveResult tmp(result);
+		swap(tmp);
+		return *this;
+	}
+	
+	void swap(ActiveResult& result)
+	{
+		using std::swap;
+		swap(_pHolder, result._pHolder);
+	}
+	
+	void wait()
+		/// Pauses the caller until the result becomes available.
+	{
+		_pHolder->wait();
+	}
+	
+	bool tryWait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Returns true if the result became
+		/// available, false otherwise.
+	{
+		return _pHolder->tryWait(milliseconds);
+	}
+	
+	void wait(long milliseconds)
+		/// Waits up to the specified interval for the result to
+		/// become available. Throws a TimeoutException if the
+		/// result did not became available.
+	{
+		_pHolder->wait(milliseconds);
+	}
+	
+	bool available() const
+		/// Returns true if a result is available.
+	{
+		return _pHolder->tryWait(0);
+	}
+	
+	bool failed() const
+		/// Returns true if the active method failed (and threw an exception).
+		/// Information about the exception can be obtained by calling error().
+	{
+		return _pHolder->failed();
+	}
+	
+	std::string error() const
+		/// If the active method threw an exception, a textual representation
+		/// of the exception is returned. An empty string is returned if the
+		/// active method completed successfully.
+	{
+		return _pHolder->error();
+	}
+
+	Exception* exception() const
+		/// If the active method threw an exception, a clone of the exception
+		/// object is returned, otherwise null.
+	{
+		return _pHolder->exception();
+	}
+
+	void notify()
+		/// Notifies the invoking thread that the result became available.
+		/// For internal use only.
+	{
+		_pHolder->notify();
+	}
+	
+	void error(const std::string& msg)
+		/// Sets the failed flag and the exception message.
+	{
+		_pHolder->error(msg);
+	}
+
+	void error(const Exception& exc)
+		/// Sets the failed flag and the exception message.
+	{
+		_pHolder->error(exc);
+	}
+	
+private:
+	ActiveResult();
+
+	ActiveResultHolderType* _pHolder;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ActiveResult_INCLUDED
diff --git a/Poco/ActiveRunnable.h b/Poco/ActiveRunnable.h
new file mode 100644
index 0000000..95317b0
--- /dev/null
+++ b/Poco/ActiveRunnable.h
@@ -0,0 +1,231 @@
+//
+// ActiveRunnable.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ActiveObjects
+//
+// Definition of the ActiveRunnable class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ActiveRunnable_INCLUDED
+#define Foundation_ActiveRunnable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/ActiveResult.h"
+#include "Poco/Runnable.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+
+
+class ActiveRunnableBase: public Runnable, public RefCountedObject
+	/// The base class for all ActiveRunnable instantiations.
+{
+public:
+	typedef AutoPtr<ActiveRunnableBase> Ptr;
+};
+
+
+template <class ResultType, class ArgType, class OwnerType>
+class ActiveRunnable: public ActiveRunnableBase
+	/// This class is used by ActiveMethod.
+	/// See the ActiveMethod class for more information.
+{
+public:
+	typedef ResultType (OwnerType::*Callback)(const ArgType&);
+	typedef ActiveResult<ResultType> ActiveResultType;
+
+	ActiveRunnable(OwnerType* pOwner, Callback method, const ArgType& arg, const ActiveResultType& result):
+		_pOwner(pOwner),
+		_method(method),
+		_arg(arg),
+		_result(result)
+	{
+		poco_check_ptr (pOwner);
+	}
+
+	void run()
+	{
+		ActiveRunnableBase::Ptr guard(this, false); // ensure automatic release when done
+		try
+		{
+			_result.data(new ResultType((_pOwner->*_method)(_arg)));
+		}
+		catch (Exception& e)
+		{
+			_result.error(e);
+		}
+		catch (std::exception& e)
+		{
+			_result.error(e.what());
+		}
+		catch (...)
+		{
+			_result.error("unknown exception");
+		}
+		_result.notify();
+	}
+
+private:
+	OwnerType* _pOwner;
+	Callback   _method;
+	ArgType    _arg;
+	ActiveResultType _result;
+};
+
+
+template <class ArgType, class OwnerType>
+class ActiveRunnable<void, ArgType, OwnerType>: public ActiveRunnableBase
+	/// This class is used by ActiveMethod.
+	/// See the ActiveMethod class for more information.
+{
+public:
+	typedef void (OwnerType::*Callback)(const ArgType&);
+	typedef ActiveResult<void> ActiveResultType;
+
+	ActiveRunnable(OwnerType* pOwner, Callback method, const ArgType& arg, const ActiveResultType& result):
+		_pOwner(pOwner),
+		_method(method),
+		_arg(arg),
+		_result(result)
+	{
+		poco_check_ptr (pOwner);
+	}
+
+	void run()
+	{
+		ActiveRunnableBase::Ptr guard(this, false); // ensure automatic release when done
+		try
+		{
+			(_pOwner->*_method)(_arg);
+		}
+		catch (Exception& e)
+		{
+			_result.error(e);
+		}
+		catch (std::exception& e)
+		{
+			_result.error(e.what());
+		}
+		catch (...)
+		{
+			_result.error("unknown exception");
+		}
+		_result.notify();
+	}
+
+private:
+	OwnerType* _pOwner;
+	Callback   _method;
+	ArgType    _arg;
+	ActiveResultType _result;
+};
+
+
+template <class ResultType, class OwnerType>
+class ActiveRunnable<ResultType, void, OwnerType>: public ActiveRunnableBase
+	/// This class is used by ActiveMethod.
+	/// See the ActiveMethod class for more information.
+{
+public:
+	typedef ResultType (OwnerType::*Callback)();
+	typedef ActiveResult<ResultType> ActiveResultType;
+
+	ActiveRunnable(OwnerType* pOwner, Callback method, const ActiveResultType& result):
+		_pOwner(pOwner),
+		_method(method),
+		_result(result)
+	{
+		poco_check_ptr (pOwner);
+	}
+
+	void run()
+	{
+		ActiveRunnableBase::Ptr guard(this, false); // ensure automatic release when done
+		try
+		{
+			_result.data(new ResultType((_pOwner->*_method)()));
+		}
+		catch (Exception& e)
+		{
+			_result.error(e);
+		}
+		catch (std::exception& e)
+		{
+			_result.error(e.what());
+		}
+		catch (...)
+		{
+			_result.error("unknown exception");
+		}
+		_result.notify();
+	}
+
+private:
+	OwnerType* _pOwner;
+	Callback   _method;
+	ActiveResultType _result;
+};
+
+
+template <class OwnerType>
+class ActiveRunnable<void, void, OwnerType>: public ActiveRunnableBase
+	/// This class is used by ActiveMethod.
+	/// See the ActiveMethod class for more information.
+{
+public:
+	typedef void (OwnerType::*Callback)();
+	typedef ActiveResult<void> ActiveResultType;
+
+	ActiveRunnable(OwnerType* pOwner, Callback method, const ActiveResultType& result):
+		_pOwner(pOwner),
+		_method(method),
+		_result(result)
+	{
+		poco_check_ptr (pOwner);
+	}
+
+	void run()
+	{
+		ActiveRunnableBase::Ptr guard(this, false); // ensure automatic release when done
+		try
+		{
+			(_pOwner->*_method)();
+		}
+		catch (Exception& e)
+		{
+			_result.error(e);
+		}
+		catch (std::exception& e)
+		{
+			_result.error(e.what());
+		}
+		catch (...)
+		{
+			_result.error("unknown exception");
+		}
+		_result.notify();
+	}
+
+private:
+	OwnerType* _pOwner;
+	Callback   _method;
+	ActiveResultType _result;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ActiveRunnable_INCLUDED
diff --git a/Poco/ActiveStarter.h b/Poco/ActiveStarter.h
new file mode 100644
index 0000000..b79a31e
--- /dev/null
+++ b/Poco/ActiveStarter.h
@@ -0,0 +1,48 @@
+//
+// ActiveStarter.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ActiveObjects
+//
+// Definition of the ActiveStarter class.
+//
+// Copyright (c) 2006-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ActiveStarter_INCLUDED
+#define Foundation_ActiveStarter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/ThreadPool.h"
+#include "Poco/ActiveRunnable.h"
+
+
+namespace Poco {
+
+
+template <class OwnerType>
+class ActiveStarter
+	/// The default implementation of the StarterType 
+	/// policy for ActiveMethod. It starts the method
+	/// in its own thread, obtained from the default
+	/// thread pool.
+{
+public:
+	static void start(OwnerType* /*pOwner*/, ActiveRunnableBase::Ptr pRunnable)
+	{
+		ThreadPool::defaultPool().start(*pRunnable);
+		pRunnable->duplicate(); // The runnable will release itself.
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ActiveStarter_INCLUDED
diff --git a/Poco/Activity.h b/Poco/Activity.h
new file mode 100644
index 0000000..a7297f1
--- /dev/null
+++ b/Poco/Activity.h
@@ -0,0 +1,208 @@
+//
+// Activity.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ActiveObjects
+//
+// Definition of the Activity template class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Activity_INCLUDED
+#define Foundation_Activity_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RunnableAdapter.h"
+#include "Poco/ThreadPool.h"
+#include "Poco/Event.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class C>
+class Activity: public Runnable
+	/// This template class helps to implement active objects.
+	/// An active object uses threads to decouple method
+	/// execution from method invocation, or to perform tasks
+	/// autonomously, without intervention of a caller.
+	///
+	/// An activity is a (typically longer running) method
+	/// that executes within its own task. Activities can
+	/// be started automatically (upon object construction)
+	/// or manually at a later time. Activities can also
+	/// be stopped at any time. However, to make stopping
+	/// an activity work, the method implementing the
+	/// activity has to check periodically whether it
+	/// has been requested to stop, and if so, return. 
+	/// Activities are stopped before the object they belong to is
+	/// destroyed. Methods implementing activities cannot have arguments
+	/// or return values. 
+	///
+	/// Activity objects are used as follows:
+	///
+	///     class ActiveObject
+	///     {
+	///     public:
+	///         ActiveObject(): 
+	///             _activity(this, &ActiveObject::runActivity)
+	///         {
+	///             ...
+	///         }
+	///   
+	///         ...
+	///  
+	///     protected:
+	///         void runActivity()
+	///         {
+	///             while (!_activity.isStopped())
+	///             {
+	///                 ...
+	///             }
+	///         }
+	///
+	///     private:
+	///         Activity<ActiveObject> _activity;
+	///     };
+{
+public:
+	typedef RunnableAdapter<C> RunnableAdapterType;
+	typedef typename RunnableAdapterType::Callback Callback;
+
+	Activity(C* pOwner, Callback method):
+		_pOwner(pOwner),
+		_runnable(*pOwner, method),
+		_stopped(true),
+		_running(false),
+		_done(false)
+		/// Creates the activity. Call start() to
+		/// start it.
+	{
+		poco_check_ptr (pOwner);
+	}
+	
+	~Activity()
+		/// Stops and destroys the activity.
+	{
+		try
+		{
+			stop();
+			wait();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+	
+	void start()
+		/// Starts the activity by acquiring a
+		/// thread for it from the default thread pool.
+	{
+		start(ThreadPool::defaultPool());
+	}
+
+	void start(ThreadPool& pool)
+	{
+		FastMutex::ScopedLock lock(_mutex);
+		
+		if (!_running)
+		{
+			_done.reset();
+			_stopped = false;
+			_running = true;
+			try
+			{
+				pool.start(*this);
+			}
+			catch (...)
+			{
+				_running = false;
+				throw;
+			}
+		}
+	}
+	
+	void stop()
+		/// Requests to stop the activity.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		_stopped = true;
+	}
+	
+	void wait()
+		/// Waits for the activity to complete.
+	{
+		if (_running)
+		{
+			_done.wait();
+		}
+	}
+
+	void wait(long milliseconds)
+		/// Waits the given interval for the activity to complete.
+		/// An TimeoutException is thrown if the activity does not
+		/// complete within the given interval.
+	{
+		if (_running)
+		{
+			_done.wait(milliseconds);
+		}
+	}
+	
+	bool isStopped() const
+		/// Returns true if the activity has been requested to stop.
+	{
+		return _stopped;
+	}
+	
+	bool isRunning() const
+		/// Returns true if the activity is running.
+	{
+		return _running;
+	}
+
+protected:
+	void run()
+	{
+		try
+		{
+			_runnable.run();
+		}
+		catch (...)
+		{
+			_running = false;
+			_done.set();
+			throw;
+		}
+		_running = false;
+		_done.set();
+	}
+	
+private:
+	Activity();
+	Activity(const Activity&);
+	Activity& operator = (const Activity&);
+
+	C*                  _pOwner;
+	RunnableAdapterType _runnable;
+	volatile bool       _stopped;
+	volatile bool       _running;
+	Event               _done;
+	FastMutex           _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Activity_INCLUDED
diff --git a/Poco/Alignment.h b/Poco/Alignment.h
new file mode 100644
index 0000000..d655a3d
--- /dev/null
+++ b/Poco/Alignment.h
@@ -0,0 +1,246 @@
+//
+// Alignment.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Alignment
+//
+// Definition of the Alignment class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+// Adapted for POCO from LLVM Compiler Infrastructure code:
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source License
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AlignOf function that computes alignments for
+// arbitrary types.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef Foundation_AlignOf_INCLUDED
+#define Foundation_AlignOf_INCLUDED
+
+
+#include <cstddef>
+
+
+#ifdef POCO_ENABLE_CPP11
+
+
+	#include <type_traits>
+	#define POCO_HAVE_ALIGNMENT
+
+
+#else
+
+
+	namespace Poco {
+
+
+	template <typename T>
+	struct AlignmentCalcImpl
+	{
+		char x;
+		T t;
+	private:
+		AlignmentCalcImpl() {} // Never instantiate.
+	};
+
+
+	template <typename T>
+	struct AlignOf
+		/// A templated class that contains an enum value representing
+		/// the alignment of the template argument.  For example,
+		/// AlignOf<int>::Alignment represents the alignment of type "int".  The
+		/// alignment calculated is the minimum alignment, and not necessarily
+		/// the "desired" alignment returned by GCC's __alignof__ (for example).  Note
+		/// that because the alignment is an enum value, it can be used as a
+		/// compile-time constant (e.g., for template instantiation).
+	{
+		enum
+		{
+			Alignment = static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T))
+		};
+
+		enum { Alignment_GreaterEqual_2Bytes  = Alignment >= 2  ? 1 : 0 };
+		enum { Alignment_GreaterEqual_4Bytes  = Alignment >= 4  ? 1 : 0 };
+		enum { Alignment_GreaterEqual_8Bytes  = Alignment >= 8  ? 1 : 0 };
+		enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 };
+	
+		enum { Alignment_LessEqual_2Bytes  = Alignment <= 2  ? 1 : 0 };
+		enum { Alignment_LessEqual_4Bytes  = Alignment <= 4  ? 1 : 0 };
+		enum { Alignment_LessEqual_8Bytes  = Alignment <= 8  ? 1 : 0 };
+		enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
+
+	};
+
+
+	template <typename T>
+	inline unsigned alignOf()
+		/// A templated function that returns the minimum alignment of
+		/// of a type.  This provides no extra functionality beyond the AlignOf
+		/// class besides some cosmetic cleanliness.  Example usage:
+		/// alignOf<int>() returns the alignment of an int.
+	{
+		return AlignOf<T>::Alignment;
+	}
+
+
+	template <std::size_t Alignment> struct AlignedCharArrayImpl;
+		/// Helper for building an aligned character array type.
+		///
+		/// This template is used to explicitly build up a collection of aligned
+		/// character types. We have to build these up using a macro and explicit
+		/// specialization to cope with old versions of MSVC and GCC where only an
+		/// integer literal can be used to specify an alignment constraint. Once built
+		/// up here, we can then begin to indirect between these using normal C++
+		/// template parameters.
+
+
+	// MSVC requires special handling here.
+	#ifndef _MSC_VER
+
+		#ifdef POCO_COMPILER_CLANG
+
+			#if __has_feature(cxx_alignas)
+				#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+					template <> struct AlignedCharArrayImpl<x> \
+					{ \
+						char aligned alignas(x); \
+					}
+				#define POCO_HAVE_ALIGNMENT
+			#endif
+
+		#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES)
+
+			#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+				template <> struct AlignedCharArrayImpl<x> \
+				{ \
+					char aligned __attribute__((aligned(x))); \
+				}
+				#define POCO_HAVE_ALIGNMENT
+
+		#endif
+	
+		#ifdef POCO_HAVE_ALIGNMENT
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
+
+			#undef POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+		#endif // POCO_HAVE_ALIGNMENT
+
+	#else // _MSC_VER
+
+		// We provide special variations of this template for the most common
+		// alignments because __declspec(align(...)) doesn't actually work when it is
+		// a member of a by-value function argument in MSVC, even if the alignment
+		// request is something reasonably like 8-byte or 16-byte.
+		template <> struct AlignedCharArrayImpl<1> { char aligned; };
+		template <> struct AlignedCharArrayImpl<2> { short aligned; };
+		template <> struct AlignedCharArrayImpl<4> { int aligned; };
+		template <> struct AlignedCharArrayImpl<8> { double aligned; };
+
+		#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
+			template <> struct AlignedCharArrayImpl<x> { \
+				__declspec(align(x)) char aligned; \
+			}
+
+		POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
+		POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
+		POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
+		POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
+		
+		#if (_MSC_VER > 1600)  // MSVC 2010 complains on alignment  larger than 128
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
+			POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
+		#endif  // _MSC_VER > 1600
+		
+		// Any larger and MSVC complains.
+		#undef POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
+
+		#define POCO_HAVE_ALIGNMENT
+	#endif // _MSC_VER
+
+	// POCO_HAVE_ALIGNMENT will be defined on the pre-C++11 platforms/compilers where
+	// it can be reliably determined and used. Uncomment the line below to explicitly
+	// disable use of alignment even for those platforms. 
+	// #undef POCO_HAVE_ALIGNMENT
+
+
+	#ifdef POCO_HAVE_ALIGNMENT
+
+		template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char>
+		union AlignedCharArrayUnion
+			/// This union template exposes a suitably aligned and sized character
+			/// array member which can hold elements of any of up to four types.
+			///
+			/// These types may be arrays, structs, or any other types. The goal is to
+			/// produce a union type containing a character array which, when used, forms
+			/// storage suitable to placement new any of these types over. Support for more
+			/// than four types can be added at the cost of more boiler plate.
+		{
+		private:
+			class AlignerImpl
+			{
+				T1 t1;
+				T2 t2;
+				T3 t3;
+				T4 t4;
+		
+				AlignerImpl(); // Never defined or instantiated.
+			};
+	
+			union SizerImpl
+			{
+				char arr1[sizeof(T1)];
+				char arr2[sizeof(T2)];
+				char arr3[sizeof(T3)];
+				char arr4[sizeof(T4)];
+			};
+	
+		public:
+			char buffer[sizeof(SizerImpl)];
+				/// The character array buffer for use by clients.
+				///
+				/// No other member of this union should be referenced. They exist purely to
+				/// constrain the layout of this character array.
+	
+		private:
+			Poco::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment> _nonceMember;
+
+		};
+
+	#endif // POCO_HAVE_ALIGNMENT
+
+	} // namespace Poco
+
+
+#endif // POCO_ENABLE_CPP11
+
+
+#endif // Foundation_AlignOf_INCLUDED
diff --git a/Poco/Any.h b/Poco/Any.h
new file mode 100644
index 0000000..30f5b76
--- /dev/null
+++ b/Poco/Any.h
@@ -0,0 +1,599 @@
+//
+// Any.h
+//
+// Library: Foundation
+// Package: Core
+// 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
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Any_INCLUDED
+#define Foundation_Any_INCLUDED
+
+
+#include "Poco/Exception.h"
+#include "Poco/MetaProgramming.h"
+#include <algorithm>
+#include <typeinfo>
+#include <cstring>
+
+
+namespace Poco {
+
+
+class Any;
+
+
+namespace Dynamic {
+
+class Var;
+class VarHolder;
+template <class> class VarHolderImpl;
+
+}
+
+#ifndef POCO_NO_SOO
+
+#ifndef POCO_ENABLE_CPP11
+	// C++11 needed for std::aligned_storage
+	#error "Any SOO can only be enabled with C++11 support"
+#endif
+
+template <typename PlaceholderT, unsigned int SizeV = POCO_SMALL_OBJECT_SIZE>
+union Placeholder
+	/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
+	/// object optimization, when enabled).
+	/// 
+	/// If Holder<Type> 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:
+	struct Size
+	{
+		static const unsigned int value = SizeV;
+	};
+
+	Placeholder ()
+	{
+		erase();
+	}
+
+	void erase()
+	{
+		std::memset(holder, 0, sizeof(Placeholder));
+	}
+
+	bool isLocal() const
+	{
+		return holder[SizeV] != 0;
+	}
+
+	void setLocal(bool local) const
+	{
+		holder[SizeV] = local ? 1 : 0;
+	}
+
+	PlaceholderT* content() const
+	{
+		if (isLocal())
+			return reinterpret_cast<PlaceholderT*>(holder);
+		else
+			return pHolder;
+	}
+
+// MSVC71,80 won't extend friendship to nested class (Any::Holder)
+#if !defined(POCO_MSVC_VERSION) || (defined(POCO_MSVC_VERSION) && (POCO_MSVC_VERSION > 80))
+private:
+#endif
+	typedef typename std::aligned_storage<SizeV + 1>::type AlignerType;
+	
+	PlaceholderT* pHolder;
+	mutable char  holder [SizeV + 1];
+	AlignerType   aligner;
+
+	friend class Any;
+	friend class Dynamic::Var;
+	friend class Dynamic::VarHolder;
+	template <class> friend class Dynamic::VarHolderImpl;
+};
+
+
+#else // !POCO_NO_SOO
+
+
+template <typename PlaceholderT>
+union Placeholder
+	/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
+	/// object optimization, when enabled).
+	/// 
+	/// If Holder<Type> 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:
+
+	Placeholder ()
+	{
+	}
+
+	PlaceholderT* content() const
+	{
+		return pHolder;
+	}
+
+// MSVC71,80 won't extend friendship to nested class (Any::Holder)
+#if !defined(POCO_MSVC_VERSION) || (defined(POCO_MSVC_VERSION) && (POCO_MSVC_VERSION > 80))
+private:
+#endif
+	
+	PlaceholderT*         pHolder;
+
+	friend class Any;
+	friend class Dynamic::Var;
+	friend class Dynamic::VarHolder;
+	template <class> friend class Dynamic::VarHolderImpl;
+};
+
+
+#endif // POCO_NO_SOO
+
+
+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.
+	///
+	/// 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.
+{
+public:
+
+#ifndef POCO_NO_SOO
+
+	Any()
+		/// Creates an empty any type.
+	{
+	}
+
+	template<typename ValueType>
+	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.
+	{
+		if ((this != &other) && !other.empty())
+			construct(other);
+	}
+
+	~Any()
+		/// Destructor. If Any is locally held, calls ValueHolder destructor;
+		/// otherwise, deletes the placeholder from the heap.
+	{
+		if (!empty())
+		{
+			if (_valueHolder.isLocal())
+				destruct();
+			else
+				delete content();
+		}
+	}
+
+	Any& swap(Any& other)
+		/// Swaps the content of the two Anys.
+		/// 
+		/// When small object optimizaton is enabled, swap only
+		/// has no-throw guarantee when both (*this and other)
+		/// objects are allocated on the heap.
+	{
+		if (this == &other) return *this;
+
+		if (!_valueHolder.isLocal() && !other._valueHolder.isLocal())
+		{
+			std::swap(_valueHolder.pHolder, other._valueHolder.pHolder);
+		}
+		else
+		{
+			Any tmp(*this);
+			try
+			{
+				if (_valueHolder.isLocal()) destruct();
+				construct(other);
+				other = tmp;
+			}
+			catch (...)
+			{
+				construct(tmp);
+				throw;
+			}
+		}
+
+		return *this;
+	}
+
+	template<typename ValueType>
+	Any& operator = (const ValueType& rhs)
+		/// Assignment operator for all types != Any.
+		///
+		/// Example: 
+		///   Any a = 13; 
+		///   Any a = string("12345");
+	{
+		construct(rhs);
+		return *this;
+	}
+	
+	Any& operator = (const Any& rhs)
+		/// Assignment operator for Any.
+	{
+		if ((this != &rhs) && !rhs.empty())
+			construct(rhs);
+		else if ((this != &rhs) && rhs.empty())
+			_valueHolder.erase();
+
+		return *this;
+	}
+	
+	bool empty() const
+		/// Returns true if the Any is empty.
+	{
+		char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
+		return 0 == std::memcmp(_valueHolder.holder, buf, POCO_SMALL_OBJECT_SIZE);
+	}
+	
+	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 ValueHolder
+	{
+	public:
+	
+		virtual ~ValueHolder()
+		{
+		}
+
+		virtual const std::type_info & type() const = 0;
+		virtual void clone(Placeholder<ValueHolder>*) const = 0;
+	};
+
+	template<typename ValueType>
+	class Holder : public ValueHolder
+	{
+	public:
+		Holder(const ValueType & value) : _held(value)
+		{
+		}
+
+		virtual const std::type_info & type() const
+		{
+			return typeid(ValueType);
+		}
+
+		virtual void clone(Placeholder<ValueHolder>* pPlaceholder) const
+		{
+			if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
+			{
+				new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
+				pPlaceholder->setLocal(true);
+			}
+			else
+			{
+				pPlaceholder->pHolder = new Holder(_held);
+				pPlaceholder->setLocal(false);
+			}
+		}
+
+		ValueType _held;
+
+	private:
+		Holder & operator = (const Holder &);
+	};
+
+	ValueHolder* content() const
+	{
+		return _valueHolder.content();
+	}
+
+	template<typename ValueType>
+	void construct(const ValueType& value)
+	{
+		if (sizeof(Holder<ValueType>) <= Placeholder<ValueType>::Size::value)
+		{
+			new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
+			_valueHolder.setLocal(true);
+		}
+		else
+		{
+			_valueHolder.pHolder = new Holder<ValueType>(value);
+			_valueHolder.setLocal(false);
+		}
+	}
+
+	void construct(const Any& other)
+	{
+		if (!other.empty())
+			other.content()->clone(&_valueHolder);
+		else
+			_valueHolder.erase();
+	}
+	
+	void destruct()
+	{
+		content()->~ValueHolder();
+	}
+
+	Placeholder<ValueHolder> _valueHolder;
+
+
+#else // if POCO_NO_SOO
+
+
+	Any(): _pHolder(0)
+		/// Creates an empty any type.
+	{
+	}
+
+	template <typename ValueType>
+	Any(const ValueType& value):
+		_pHolder(new Holder<ValueType>(value))
+		/// Creates an any which stores the init parameter inside.
+		///
+		/// Example: 
+		///	 Any a(13); 
+		///	 Any a(string("12345"));
+	{
+	}
+
+	Any(const Any& other):
+		_pHolder(other._pHolder ? other._pHolder->clone() : 0)
+		/// Copy constructor, works with both empty and initialized Any values.
+	{
+	}
+
+	~Any()
+	{
+		delete _pHolder;
+	}
+
+	Any& swap(Any& rhs)
+		/// Swaps the content of the two Anys.
+	{
+		std::swap(_pHolder, rhs._pHolder);
+		return *this;
+	}
+
+	template <typename ValueType>
+	Any& operator = (const ValueType& rhs)
+		/// Assignment operator for all types != Any.
+		///
+		/// Example: 
+		///   Any a = 13; 
+		///   Any a = string("12345");
+	{
+		Any(rhs).swap(*this);
+		return *this;
+	}
+
+	Any& operator = (const Any& rhs)
+		/// Assignment operator for Any.
+	{
+		Any(rhs).swap(*this);
+		return *this;
+	}
+
+	bool empty() const
+		/// Returns true if the Any is empty.
+	{
+		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 recommended to always query an Any for its type info before
+		/// trying to extract data via an AnyCast/RefAnyCast.
+	{
+		return _pHolder ? _pHolder->type() : typeid(void);
+	}
+
+private:
+	class ValueHolder
+	{
+	public:
+		virtual ~ValueHolder()
+		{
+		}
+
+		virtual const std::type_info& type() const = 0;
+		virtual ValueHolder* clone() const = 0;
+	};
+
+	template <typename ValueType>
+	class Holder: public ValueHolder
+	{
+	public: 
+		Holder(const ValueType& value):
+			_held(value)
+		{
+		}
+
+		virtual const std::type_info& type() const
+		{
+			return typeid(ValueType);
+		}
+
+		virtual ValueHolder* clone() const
+		{
+			return new Holder(_held);
+		}
+
+		ValueType _held;
+
+	private:
+		Holder & operator=(const Holder &);
+	};
+
+	ValueHolder* content() const
+	{
+		return _pHolder;
+	}
+
+private:
+	ValueHolder* _pHolder;
+
+#endif // POCO_NO_SOO
+
+	template <typename ValueType>
+	friend ValueType* AnyCast(Any*);
+
+	template <typename ValueType>
+	friend ValueType* UnsafeAnyCast(Any*);
+
+};
+
+
+template <typename ValueType>
+ValueType* AnyCast(Any* operand)
+	/// AnyCast operator used to extract the ValueType from an Any*. Will return a pointer
+	/// to the stored value. 
+	///
+	/// Example Usage: 
+	///	 MyType* pTmp = AnyCast<MyType*>(pAny).
+	/// Will return NULL if the cast fails, i.e. types don't match.
+{
+	return operand && operand->type() == typeid(ValueType)
+				? &static_cast<Any::Holder<ValueType>*>(operand->content())->_held
+				: 0;
+}
+
+
+template <typename ValueType>
+const ValueType* AnyCast(const Any* operand)
+	/// AnyCast operator used to extract a const ValueType pointer from an const Any*. Will return a const pointer
+	/// to the stored value. 
+	///
+	/// Example Usage:
+	///	 const MyType* pTmp = AnyCast<MyType*>(pAny).
+	/// Will return NULL if the cast fails, i.e. types don't match.
+{
+	return AnyCast<ValueType>(const_cast<Any*>(operand));
+}
+
+
+template <typename ValueType>
+ValueType AnyCast(Any& operand)
+	/// AnyCast operator used to extract a copy of the ValueType from an Any&.
+	///
+	/// Example Usage: 
+	///	 MyType tmp = AnyCast<MyType>(anAny).
+	/// Will throw a BadCastException if the cast fails.
+	/// Dont use an AnyCast in combination with references, i.e. MyType& tmp = ... or const MyType& tmp = ...
+	/// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
+	/// these cases.
+{
+	typedef typename TypeWrapper<ValueType>::TYPE NonRef;
+
+	NonRef* result = AnyCast<NonRef>(&operand);
+	if (!result) throw BadCastException("Failed to convert between Any types");
+	return *result;
+}
+
+
+template <typename ValueType>
+ValueType AnyCast(const Any& operand)
+	/// AnyCast operator used to extract a copy of the ValueType from an const Any&.
+	///
+	/// Example Usage: 
+	///	 MyType tmp = AnyCast<MyType>(anAny).
+	/// Will throw a BadCastException if the cast fails.
+	/// Dont use an AnyCast in combination with references, i.e. MyType& tmp = ... or const MyType& = ...
+	/// Some compilers will accept this code although a copy is returned. Use the RefAnyCast in
+	/// these cases.
+{
+	typedef typename TypeWrapper<ValueType>::TYPE NonRef;
+
+	return AnyCast<NonRef&>(const_cast<Any&>(operand));
+}
+
+
+template <typename ValueType>
+const ValueType& RefAnyCast(const Any & operand)
+	/// AnyCast operator used to return a const reference to the internal data. 
+	///
+	/// Example Usage: 
+	///	 const MyType& tmp = RefAnyCast<MyType>(anAny);
+{
+	ValueType* result = AnyCast<ValueType>(const_cast<Any*>(&operand));
+	if (!result) throw BadCastException("RefAnyCast: Failed to convert between const Any types");
+	return *result;
+}
+
+
+template <typename ValueType>
+ValueType& RefAnyCast(Any& operand)
+	/// AnyCast operator used to return a reference to the internal data.
+	///
+	/// Example Usage: 
+	///	 MyType& tmp = RefAnyCast<MyType>(anAny);
+{
+	ValueType* result = AnyCast<ValueType>(&operand);
+	if (!result) throw BadCastException("RefAnyCast: Failed to convert between Any types");
+	return *result;
+}
+
+
+template <typename ValueType>
+ValueType* UnsafeAnyCast(Any* operand)
+	/// The "unsafe" versions of AnyCast are not part of the
+	/// public interface and may be removed at any time. They are
+	/// required where we know what type is stored in the any and can't
+	/// use typeid() comparison, e.g., when our types may travel across
+	/// different shared libraries.
+{
+	return &static_cast<Any::Holder<ValueType>*>(operand->content())->_held;
+}
+
+
+template <typename ValueType>
+const ValueType* UnsafeAnyCast(const Any* operand)
+	/// The "unsafe" versions of AnyCast are not part of the
+	/// public interface and may be removed at any time. They are
+	/// required where we know what type is stored in the any and can't
+	/// use typeid() comparison, e.g., when our types may travel across
+	/// different shared libraries.
+{
+	return AnyCast<ValueType>(const_cast<Any*>(operand));
+}
+
+
+} // namespace Poco
+
+
+#endif
diff --git a/Poco/ArchiveStrategy.h b/Poco/ArchiveStrategy.h
new file mode 100644
index 0000000..e04605f
--- /dev/null
+++ b/Poco/ArchiveStrategy.h
@@ -0,0 +1,146 @@
+//
+// ArchiveStrategy.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  FileChannel
+//
+// Definition of the ArchiveStrategy class and subclasses.
+//
+// Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ArchiveStrategy_INCLUDED
+#define Foundation_ArchiveStrategy_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/LogFile.h"
+#include "Poco/File.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/NumberFormatter.h"
+
+
+namespace Poco {
+
+
+class ArchiveCompressor;
+
+
+class Foundation_API ArchiveStrategy
+	/// The ArchiveStrategy is used by FileChannel 
+	/// to rename a rotated log file for archiving.
+	///
+	/// Archived files can be automatically compressed,
+	/// using the gzip file format.
+{
+public:
+	ArchiveStrategy();
+	virtual ~ArchiveStrategy();
+
+	virtual LogFile* archive(LogFile* pFile) = 0;
+		/// Renames the given log file for archiving
+		/// and creates and returns a new log file.
+		/// The given LogFile object is deleted.
+
+	void compress(bool flag = true);
+		/// Enables or disables compression of archived files.	
+
+protected:
+	void moveFile(const std::string& oldName, const std::string& newName);
+	bool exists(const std::string& name);
+	
+private:
+	ArchiveStrategy(const ArchiveStrategy&);
+	ArchiveStrategy& operator = (const ArchiveStrategy&);
+	
+	bool _compress;
+	ArchiveCompressor* _pCompressor;
+};
+
+
+class Foundation_API ArchiveByNumberStrategy: public ArchiveStrategy
+	/// A monotonic increasing number is appended to the
+	/// log file name. The most recent archived file
+	/// always has the number zero.
+{
+public:
+	ArchiveByNumberStrategy();
+	~ArchiveByNumberStrategy();
+	LogFile* archive(LogFile* pFile);
+};
+
+
+template <class DT>
+class ArchiveByTimestampStrategy: public ArchiveStrategy
+	/// A timestamp (YYYYMMDDhhmmssiii) is appended to archived
+	/// log files.
+{
+public:
+	ArchiveByTimestampStrategy()
+	{
+	}
+	
+	~ArchiveByTimestampStrategy()
+	{
+	}
+	
+	LogFile* archive(LogFile* pFile)
+		/// Archives the file by appending the current timestamp to the
+		/// file name. If the new file name exists, additionally a monotonic
+		/// increasing number is appended to the log file name.
+	{
+		std::string path = pFile->path();
+		delete pFile;
+		std::string archPath = path;
+		archPath.append(".");
+		DateTimeFormatter::append(archPath, DT().timestamp(), "%Y%m%d%H%M%S%i");
+		
+		if (exists(archPath)) archiveByNumber(archPath);
+		else moveFile(path, archPath);
+
+		return new LogFile(path);
+	}
+
+private:
+	void archiveByNumber(const std::string& basePath)
+		/// A monotonic increasing number is appended to the
+		/// log file name. The most recent archived file
+		/// always has the number zero.
+	{
+		int n = -1;
+		std::string path;
+		do
+		{
+			path = basePath;
+			path.append(".");
+			NumberFormatter::append(path, ++n);
+		}
+		while (exists(path));
+		
+		while (n >= 0)
+		{
+			std::string oldPath = basePath;
+			if (n > 0)
+			{
+				oldPath.append(".");
+				NumberFormatter::append(oldPath, n - 1);
+			}
+			std::string newPath = basePath;
+			newPath.append(".");
+			NumberFormatter::append(newPath, n);
+			moveFile(oldPath, newPath);
+			--n;
+		}
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ArchiveStrategy_INCLUDED
diff --git a/Poco/Array.h b/Poco/Array.h
new file mode 100644
index 0000000..76e5fae
--- /dev/null
+++ b/Poco/Array.h
@@ -0,0 +1,249 @@
+//
+// Array.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Array
+//
+// Definition of the Array class
+//
+// Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+// ------------------------------------------------------------------------------
+// (C) Copyright Nicolai M. Josuttis 2001.
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+// ------------------------------------------------------------------------------
+
+
+#ifndef Foundation_Array_INCLUDED
+#define Foundation_Array_INCLUDED
+
+#include "Poco/Exception.h"
+#include "Poco/Bugcheck.h"
+#include <algorithm>
+
+namespace Poco {
+
+template<class T, std::size_t N>
+class Array 
+	/// STL container like C-style array replacement class. 
+	/// 
+	/// This implementation is based on the idea of Nicolai Josuttis.
+	/// His original implementation can be found at http://www.josuttis.com/cppcode/array.html . 
+{
+
+public:
+
+	typedef T				value_type;
+	typedef T*				iterator;
+	typedef const T*		const_iterator;
+	typedef T&				reference;
+	typedef const T&		const_reference;
+	typedef std::size_t		size_type;
+	typedef std::ptrdiff_t  difference_type;
+
+	iterator begin()
+	{
+		return elems;
+	}
+
+	const_iterator begin() const
+	{
+		return elems;
+	}
+
+	iterator end()
+	{ 
+		return elems+N;
+	}
+
+	const_iterator end() const
+	{
+		return elems+N;
+	}
+
+	typedef std::reverse_iterator<iterator>			reverse_iterator;
+	typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
+
+	reverse_iterator rbegin()
+	{
+		return reverse_iterator(end());
+	}
+
+	const_reverse_iterator rbegin() const
+	{
+		return const_reverse_iterator(end());
+	}
+
+	reverse_iterator rend()
+	{ 
+		return reverse_iterator(begin());
+	}
+
+	const_reverse_iterator rend() const
+	{
+		return const_reverse_iterator(begin());
+	}
+
+	reference operator[](size_type i) 
+		/// Element access without range check. If the index is not small than the given size, the behavior is undefined.
+	{ 
+		poco_assert( i < N && "out of range" ); 
+		return elems[i];
+	}
+
+	const_reference operator[](size_type i) const 
+		/// Element access without range check. If the index is not small than the given size, the behavior is undefined.
+	{	 
+		poco_assert( i < N && "out of range" ); 
+		return elems[i]; 
+	}
+
+	reference at(size_type i)
+		/// Element access with range check. Throws Poco::InvalidArgumentException if the index is over range.
+	{ 
+		if(i>=size())
+			throw Poco::InvalidArgumentException("Array::at() range check failed: index is over range");
+		return elems[i]; 
+	}
+
+	const_reference at(size_type i) const
+		/// Element access with range check. Throws Poco::InvalidArgumentException if the index is over range.
+	{
+		if(i>=size())
+			throw Poco::InvalidArgumentException("Array::at() range check failed: index is over range");
+		return elems[i]; 
+	}
+
+	reference front() 
+	{ 
+		return elems[0]; 
+	}
+
+	const_reference front() const 
+	{
+		return elems[0];
+	}
+
+	reference back() 
+	{ 
+		return elems[N-1]; 
+	}
+
+	const_reference back() const 
+	{ 
+		return elems[N-1]; 
+	}
+
+	static size_type size()
+	{
+		return N; 
+	}
+
+	static bool empty()
+	{ 
+		return false; 
+	}
+
+	static size_type max_size()
+	{ 
+		return N; 
+	}
+
+	enum { static_size = N };
+
+	void swap (Array<T,N>& y) {
+		std::swap_ranges(begin(),end(),y.begin());
+	}
+
+	const T* data() const
+		/// Direct access to data (read-only)
+	{ 
+		return elems; 
+	}
+
+	T* data()
+	{ 
+		return elems;
+	}
+
+	T* c_array(){ 
+		/// Use array as C array (direct read/write access to data)
+		return elems;
+	}
+
+	template <typename Other>
+	Array<T,N>& operator= (const Array<Other,N>& rhs)
+		/// Assignment with type conversion 
+	{
+		std::copy(rhs.begin(),rhs.end(), begin());
+		return *this;
+	}
+
+	void assign (const T& value)
+		/// Assign one value to all elements
+	{
+		std::fill_n(begin(),size(),value);
+	}
+
+public:
+
+	T elems[N];	
+		/// Fixed-size array of elements of type T, public specifier used to make this class a aggregate.
+
+};
+
+// comparisons
+template<class T, std::size_t N>
+bool operator== (const Array<T,N>& x, const Array<T,N>& y) 
+{
+	return std::equal(x.begin(), x.end(), y.begin());
+}
+
+template<class T, std::size_t N>
+bool operator< (const Array<T,N>& x, const Array<T,N>& y) 
+{
+	return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template<class T, std::size_t N>
+bool operator!= (const Array<T,N>& x, const Array<T,N>& y) 
+{
+	return !(x==y);
+}
+
+template<class T, std::size_t N>
+bool operator> (const Array<T,N>& x, const Array<T,N>& y) 
+{
+	return y<x;
+}
+
+template<class T, std::size_t N>
+bool operator<= (const Array<T,N>& x, const Array<T,N>& y) 
+{
+	return !(y<x);
+}
+
+template<class T, std::size_t N>
+bool operator>= (const Array<T,N>& x, const Array<T,N>& y) 
+{
+	return !(x<y);
+}
+
+template<class T, std::size_t N>
+inline void swap (Array<T,N>& x, Array<T,N>& y) 
+	/// global swap()
+{
+	x.swap(y);
+}
+
+}// namespace Poco
+
+#endif // Foundation_Array_INCLUDED
+
diff --git a/Poco/Ascii.h b/Poco/Ascii.h
new file mode 100644
index 0000000..5dd741d
--- /dev/null
+++ b/Poco/Ascii.h
@@ -0,0 +1,220 @@
+//
+// Ascii.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Ascii
+//
+// Definition of the Ascii class.
+//
+// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Ascii_INCLUDED
+#define Foundation_Ascii_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Ascii
+	/// This class contains enumerations and static
+	/// utility functions for dealing with ASCII characters
+	/// and their properties.
+	///
+	/// The classification functions will also work if
+	/// non-ASCII character codes are passed to them,
+	/// but classification will only check for
+	/// ASCII characters.
+	///
+	/// This allows the classification methods to be used
+	/// on the single bytes of a UTF-8 string, without
+	/// causing assertions or inconsistent results (depending
+	/// upon the current locale) on bytes outside the ASCII range,
+	/// as may be produced by Ascii::isSpace(), etc.
+{
+public:
+	enum CharacterProperties
+		/// ASCII character properties.
+	{
+		ACP_CONTROL  = 0x0001,
+		ACP_SPACE    = 0x0002,
+		ACP_PUNCT    = 0x0004,
+		ACP_DIGIT    = 0x0008,
+		ACP_HEXDIGIT = 0x0010,
+		ACP_ALPHA    = 0x0020,
+		ACP_LOWER    = 0x0040,
+		ACP_UPPER    = 0x0080,
+		ACP_GRAPH    = 0x0100,
+		ACP_PRINT    = 0x0200
+	};
+	
+	static int properties(int ch);
+		/// Return the ASCII character properties for the
+		/// character with the given ASCII value.
+		///
+		/// If the character is outside the ASCII range
+		/// (0 .. 127), 0 is returned.
+
+	static bool hasSomeProperties(int ch, int properties);
+		/// Returns true if the given character is
+		/// within the ASCII range and has at least one of 
+		/// the given properties.
+
+	static bool hasProperties(int ch, int properties);
+		/// Returns true if the given character is
+		/// within the ASCII range and has all of 
+		/// the given properties.
+
+	static bool isAscii(int ch);
+		/// Returns true iff the given character code is within
+		/// the ASCII range (0 .. 127).
+		
+	static bool isSpace(int ch);
+		/// Returns true iff the given character is a whitespace.
+		
+	static bool isDigit(int ch);
+		/// Returns true iff the given character is a digit.
+
+	static bool isHexDigit(int ch);
+		/// Returns true iff the given character is a hexadecimal digit.
+		
+	static bool isPunct(int ch);
+		/// Returns true iff the given character is a punctuation character.
+		
+	static bool isAlpha(int ch);
+		/// Returns true iff the given character is an alphabetic character.	
+
+	static bool isAlphaNumeric(int ch);
+		/// Returns true iff the given character is an alphabetic character.	
+		
+	static bool isLower(int ch);
+		/// Returns true iff the given character is a lowercase alphabetic
+		/// character.
+		
+	static bool isUpper(int ch);
+		/// Returns true iff the given character is an uppercase alphabetic
+		/// character.
+		
+	static int toLower(int ch);
+		/// If the given character is an uppercase character,
+		/// return its lowercase counterpart, otherwise return
+		/// the character.
+
+	static int toUpper(int ch);
+		/// If the given character is a lowercase character,
+		/// return its uppercase counterpart, otherwise return
+		/// the character.
+		
+private:
+	static const int CHARACTER_PROPERTIES[128];
+};
+
+
+//
+// inlines
+//
+inline int Ascii::properties(int ch)
+{
+	if (isAscii(ch)) 
+		return CHARACTER_PROPERTIES[ch];
+	else
+		return 0;
+}
+
+
+inline bool Ascii::isAscii(int ch)
+{
+	return (static_cast<UInt32>(ch) & 0xFFFFFF80) == 0;
+}
+
+
+inline bool Ascii::hasProperties(int ch, int props)
+{
+	return (properties(ch) & props) == props;
+}
+
+
+inline bool Ascii::hasSomeProperties(int ch, int props)
+{
+	return (properties(ch) & props) != 0;
+}
+
+
+inline bool Ascii::isSpace(int ch)
+{
+	return hasProperties(ch, ACP_SPACE);
+}
+
+
+inline bool Ascii::isDigit(int ch)
+{
+	return hasProperties(ch, ACP_DIGIT);
+}
+
+
+inline bool Ascii::isHexDigit(int ch)
+{
+	return hasProperties(ch, ACP_HEXDIGIT);
+}
+
+
+inline bool Ascii::isPunct(int ch)
+{
+	return hasProperties(ch, ACP_PUNCT);
+}
+
+
+inline bool Ascii::isAlpha(int ch)
+{
+	return hasProperties(ch, ACP_ALPHA);
+}
+
+
+inline bool Ascii::isAlphaNumeric(int ch)
+{
+	return hasSomeProperties(ch, ACP_ALPHA | ACP_DIGIT);
+}
+
+
+inline bool Ascii::isLower(int ch)
+{
+	return hasProperties(ch, ACP_LOWER);
+}
+
+
+inline bool Ascii::isUpper(int ch)
+{
+	return hasProperties(ch, ACP_UPPER);
+}
+
+
+inline int Ascii::toLower(int ch)
+{
+	if (isUpper(ch))
+		return ch + 32;
+	else
+		return ch;
+}
+
+
+inline int Ascii::toUpper(int ch)
+{
+	if (isLower(ch))
+		return ch - 32;
+	else
+		return ch;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Ascii_INCLUDED
diff --git a/Poco/AsyncChannel.h b/Poco/AsyncChannel.h
new file mode 100644
index 0000000..9756edc
--- /dev/null
+++ b/Poco/AsyncChannel.h
@@ -0,0 +1,100 @@
+//
+// AsyncChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  AsyncChannel
+//
+// Definition of the AsyncChannel class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AsyncChannel_INCLUDED
+#define Foundation_AsyncChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Thread.h"
+#include "Poco/Mutex.h"
+#include "Poco/Runnable.h"
+#include "Poco/NotificationQueue.h"
+
+
+namespace Poco {
+
+
+class Foundation_API AsyncChannel: public Channel, public Runnable
+	/// A channel uses a separate thread for logging.
+	///
+	/// Using this channel can help to improve the performance of
+	/// applications that produce huge amounts of log messages or
+	/// that write log messages to multiple channels simultaneously.
+	///
+	/// All log messages are put into a queue and this queue is
+	/// then processed by a separate thread.
+{
+public:
+	AsyncChannel(Channel* pChannel = 0, Thread::Priority prio = Thread::PRIO_NORMAL);
+		/// Creates the AsyncChannel and connects it to
+		/// the given channel.
+
+	void setChannel(Channel* pChannel);
+		/// Connects the AsyncChannel to the given target channel.
+		/// All messages will be forwarded to this channel.
+		
+	Channel* getChannel() const;
+		/// Returns the target channel.
+
+	void open();
+		/// Opens the channel and creates the 
+		/// background logging thread.
+		
+	void close();
+		/// Closes the channel and stops the background
+		/// logging thread.
+
+	void log(const Message& msg);
+		/// Queues the message for processing by the
+		/// background thread.
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets or changes a configuration property.
+		///
+		/// The "channel" property allows setting the target 
+		/// channel via the LoggingRegistry.
+		/// The "channel" property is set-only.
+		///
+		/// The "priority" property allows setting the thread
+		/// priority. The following values are supported:
+		///    * lowest
+		///    * low
+		///    * normal (default)
+		///    * high
+		///    * highest
+		///
+		/// The "priority" property is set-only.
+
+protected:
+	~AsyncChannel();
+	void run();
+	void setPriority(const std::string& value);
+		
+private:
+	Channel*  _pChannel;
+	Thread    _thread;
+	FastMutex _threadMutex;
+	FastMutex _channelMutex;
+	NotificationQueue _queue;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AsyncChannel_INCLUDED
diff --git a/Poco/AtomicCounter.h b/Poco/AtomicCounter.h
new file mode 100644
index 0000000..4c7c788
--- /dev/null
+++ b/Poco/AtomicCounter.h
@@ -0,0 +1,417 @@
+//
+// AtomicCounter.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  AtomicCounter
+//
+// Definition of the AtomicCounter class.
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AtomicCounter_INCLUDED
+#define Foundation_AtomicCounter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#if POCO_OS == POCO_OS_WINDOWS_NT
+	#include "Poco/UnWindows.h"
+#elif POCO_OS == POCO_OS_MAC_OS_X
+	#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 || __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 || __TV_OS_VERSION_MAX_ALLOWED >= 100000 || __WATCH_OS_VERSION_MAX_ALLOWED >= 30000
+		#if __cplusplus >= 201103L
+			#ifndef POCO_HAVE_STD_ATOMICS
+				#define POCO_HAVE_STD_ATOMICS
+			#endif
+		#else
+			#include <libkern/OSAtomic.h>
+		#endif
+	#else
+		#include <libkern/OSAtomic.h>
+	#endif
+#elif ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2) || __GNUC__ > 4) && (defined(__x86_64__) || defined(__i386__))
+	#if !defined(POCO_HAVE_GCC_ATOMICS) && !defined(POCO_NO_GCC_ATOMICS)
+		#define POCO_HAVE_GCC_ATOMICS
+	#endif
+#elif ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) || __GNUC__ > 4)
+	#if !defined(POCO_HAVE_GCC_ATOMICS) && !defined(POCO_NO_GCC_ATOMICS)
+		#define POCO_HAVE_GCC_ATOMICS
+	#endif
+#endif // POCO_OS
+#include "Poco/Mutex.h"
+#ifdef POCO_HAVE_STD_ATOMICS
+#include <atomic>
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API AtomicCounter
+	/// This class implements a simple counter, which
+	/// provides atomic operations that are safe to
+	/// use in a multithreaded environment.
+	///
+	/// Typical usage of AtomicCounter is for implementing
+	/// reference counting and similar things.
+	///
+	/// On some platforms, the implementation of AtomicCounter
+	/// is based on atomic primitives specific to the platform
+	/// (such as InterlockedIncrement, etc. on Windows), and
+	/// thus very efficient. On platforms that do not support
+	/// atomic primitives, operations are guarded by a FastMutex.
+	///
+	/// The following platforms currently have atomic
+	/// primitives:
+	///   - Windows
+	///   - Mac OS X
+	///   - GCC 4.1+ (Intel platforms only)
+{
+public:
+	typedef int ValueType; /// The underlying integer type.
+	
+	AtomicCounter();
+		/// Creates a new AtomicCounter and initializes it to zero.
+		
+	explicit AtomicCounter(ValueType initialValue);
+		/// Creates a new AtomicCounter and initializes it with
+		/// the given value.
+	
+	AtomicCounter(const AtomicCounter& counter);
+		/// Creates the counter by copying another one.
+	
+	~AtomicCounter();
+		/// Destroys the AtomicCounter.
+
+	AtomicCounter& operator = (const AtomicCounter& counter);
+		/// Assigns the value of another AtomicCounter.
+		
+	AtomicCounter& operator = (ValueType value);
+		/// Assigns a value to the counter.
+
+	operator ValueType () const;
+		/// Returns the value of the counter.
+		
+	ValueType value() const;
+		/// Returns the value of the counter.
+		
+	ValueType operator ++ (); // prefix
+		/// Increments the counter and returns the result.
+		
+	ValueType operator ++ (int); // postfix
+		/// Increments the counter and returns the previous value.
+		
+	ValueType operator -- (); // prefix
+		/// Decrements the counter and returns the result.
+		
+	ValueType operator -- (int); // postfix
+		/// Decrements the counter and returns the previous value.
+		
+	bool operator ! () const;
+		/// Returns true if the counter is zero, false otherwise.
+
+private:
+#if defined(POCO_HAVE_STD_ATOMICS)
+	typedef std::atomic<int> ImplType;
+#elif POCO_OS == POCO_OS_WINDOWS_NT
+	typedef volatile LONG ImplType;
+#elif POCO_OS == POCO_OS_MAC_OS_X
+	typedef int32_t ImplType;
+#elif defined(POCO_HAVE_GCC_ATOMICS)
+	typedef int ImplType;
+#else // generic implementation based on FastMutex
+	struct ImplType
+	{
+		mutable FastMutex mutex;
+		volatile int      value;
+	};
+#endif // POCO_OS
+
+	ImplType _counter;
+};
+
+
+//
+// inlines
+//
+
+
+#if defined(POCO_HAVE_STD_ATOMICS)
+//
+// C++11 atomics
+//
+inline AtomicCounter::operator AtomicCounter::ValueType () const
+{
+	return _counter.load();
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::value() const
+{
+	return _counter.load();
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
+{
+	return ++_counter;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
+{
+	return _counter++;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
+{
+	return --_counter;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
+{
+	return _counter--;
+}
+
+	
+inline bool AtomicCounter::operator ! () const
+{
+	return _counter.load() == 0;
+}
+
+
+#elif POCO_OS == POCO_OS_WINDOWS_NT
+//
+// Windows
+//
+inline AtomicCounter::operator AtomicCounter::ValueType () const
+{
+	return _counter;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::value() const
+{
+	return _counter;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
+{
+	return InterlockedIncrement(&_counter);
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
+{
+	ValueType result = InterlockedIncrement(&_counter);
+	return --result;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
+{
+	return InterlockedDecrement(&_counter);
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
+{
+	ValueType result = InterlockedDecrement(&_counter);
+	return ++result;
+}
+
+	
+inline bool AtomicCounter::operator ! () const
+{
+	return _counter == 0;
+}
+
+
+#elif POCO_OS == POCO_OS_MAC_OS_X
+//
+// Mac OS X
+//
+inline AtomicCounter::operator AtomicCounter::ValueType () const
+{
+	return _counter;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::value() const
+{
+	return _counter;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
+{
+	return OSAtomicIncrement32(&_counter);
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
+{
+	ValueType result = OSAtomicIncrement32(&_counter);
+	return --result;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
+{
+	return OSAtomicDecrement32(&_counter);
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
+{
+	ValueType result = OSAtomicDecrement32(&_counter);
+	return ++result;
+}
+
+	
+inline bool AtomicCounter::operator ! () const
+{
+	return _counter == 0;
+}
+
+#elif defined(POCO_HAVE_GCC_ATOMICS)
+//
+// GCC 4.1+ atomic builtins.
+//
+inline AtomicCounter::operator AtomicCounter::ValueType () const
+{
+	return _counter;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::value() const
+{
+	return _counter;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
+{
+	return __sync_add_and_fetch(&_counter, 1);
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
+{
+	return __sync_fetch_and_add(&_counter, 1);
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
+{
+	return __sync_sub_and_fetch(&_counter, 1);
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
+{
+	return __sync_fetch_and_sub(&_counter, 1);
+}
+
+	
+inline bool AtomicCounter::operator ! () const
+{
+	return _counter == 0;
+}
+
+
+#else
+//
+// Generic implementation based on FastMutex
+//
+inline AtomicCounter::operator AtomicCounter::ValueType () const
+{
+	ValueType result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = _counter.value;
+	}
+	return result;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::value() const
+{
+	ValueType result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = _counter.value;
+	}
+	return result;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator ++ () // prefix
+{
+	ValueType result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = ++_counter.value;
+	}
+	return result;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator ++ (int) // postfix
+{
+	ValueType result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = _counter.value++;
+	}
+	return result;
+}
+
+
+inline AtomicCounter::ValueType AtomicCounter::operator -- () // prefix
+{
+	ValueType result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = --_counter.value;
+	}
+	return result;
+}
+
+	
+inline AtomicCounter::ValueType AtomicCounter::operator -- (int) // postfix
+{
+	ValueType result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = _counter.value--;
+	}
+	return result;
+}
+
+	
+inline bool AtomicCounter::operator ! () const
+{
+	bool result;
+	{
+		FastMutex::ScopedLock lock(_counter.mutex);
+		result = _counter.value == 0;
+	}
+	return result;
+}
+
+
+#endif // POCO_OS
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AtomicCounter_INCLUDED
diff --git a/Poco/AutoPtr.h b/Poco/AutoPtr.h
new file mode 100644
index 0000000..c323571
--- /dev/null
+++ b/Poco/AutoPtr.h
@@ -0,0 +1,386 @@
+//
+// AutoPtr.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  AutoPtr
+//
+// Definition of the AutoPtr template class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AutoPtr_INCLUDED
+#define Foundation_AutoPtr_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <algorithm>
+
+
+namespace Poco {
+
+
+template <class C>
+class AutoPtr
+	/// AutoPtr is a "smart" pointer for classes implementing
+	/// reference counting based garbage collection.
+	/// To be usable with the AutoPtr template, a class must
+	/// implement the following behaviour:
+	/// A class must maintain a reference count.
+	/// The constructors of the object initialize the reference
+	/// count to one.
+	/// The class must implement a public duplicate() method:
+	///     void duplicate();
+	/// that increments the reference count by one.
+	/// The class must implement a public release() method:
+	///     void release()
+	/// that decrements the reference count by one, and,
+	/// if the reference count reaches zero, deletes the
+	/// object.
+	///
+	/// AutoPtr works in the following way:
+	/// If an AutoPtr is assigned an ordinary pointer to
+	/// an object (via the constructor or the assignment operator),
+	/// it takes ownership of the object and the object's reference 
+	/// count remains unchanged.
+	/// If the AutoPtr is assigned another AutoPtr, the
+	/// object's reference count is incremented by one by
+	/// calling duplicate() on its object.
+	/// The destructor of AutoPtr calls release() on its
+	/// object.
+	/// AutoPtr supports dereferencing with both the ->
+	/// and the * operator. An attempt to dereference a null
+	/// AutoPtr results in a NullPointerException being thrown.
+	/// AutoPtr also implements all relational operators.
+	/// Note that AutoPtr allows casting of its encapsulated data types.
+{
+public:
+	AutoPtr(): _ptr(0)
+	{
+	}
+
+	AutoPtr(C* ptr): _ptr(ptr)
+	{
+	}
+
+	AutoPtr(C* ptr, bool shared): _ptr(ptr)
+	{
+		if (shared && _ptr) _ptr->duplicate();
+	}
+
+	AutoPtr(const AutoPtr& ptr): _ptr(ptr._ptr)
+	{
+		if (_ptr) _ptr->duplicate();
+	}
+
+	template <class Other> 
+	AutoPtr(const AutoPtr<Other>& ptr): _ptr(const_cast<Other*>(ptr.get()))
+	{
+		if (_ptr) _ptr->duplicate();
+	}
+
+	~AutoPtr()
+	{
+		if (_ptr) _ptr->release();
+	}
+	
+	AutoPtr& assign(C* ptr)
+	{
+		if (_ptr != ptr)
+		{
+			if (_ptr) _ptr->release();
+			_ptr = ptr;
+		}
+		return *this;
+	}
+
+	AutoPtr& assign(C* ptr, bool shared)
+	{
+		if (_ptr != ptr)
+		{
+			if (_ptr) _ptr->release();
+			_ptr = ptr;
+			if (shared && _ptr) _ptr->duplicate();
+		}
+		return *this;
+	}
+	
+	AutoPtr& assign(const AutoPtr& ptr)
+	{
+		if (&ptr != this)
+		{
+			if (_ptr) _ptr->release();
+			_ptr = ptr._ptr;
+			if (_ptr) _ptr->duplicate();
+		}
+		return *this;
+	}
+	
+	template <class Other> 
+	AutoPtr& assign(const AutoPtr<Other>& ptr)
+	{
+		if (ptr.get() != _ptr)
+		{
+			if (_ptr) _ptr->release();
+			_ptr = const_cast<Other*>(ptr.get());
+			if (_ptr) _ptr->duplicate();
+		}
+		return *this;
+	}
+
+	void reset()
+	{
+		if (_ptr)
+		{
+			_ptr->release();
+			_ptr = 0;
+		}
+	}
+
+	void reset(C* ptr)
+	{
+		assign(ptr);
+	}
+
+	void reset(C* ptr, bool shared)
+	{
+		assign(ptr, shared);
+	}
+
+	void reset(const AutoPtr& ptr)
+	{
+		assign(ptr);
+	}
+
+	template <class Other>
+	void reset(const AutoPtr<Other>& ptr)
+	{
+		assign<Other>(ptr);
+	}
+
+	AutoPtr& operator = (C* ptr)
+	{
+		return assign(ptr);
+	}
+
+	AutoPtr& operator = (const AutoPtr& ptr)
+	{
+		return assign(ptr);
+	}
+	
+	template <class Other> 
+	AutoPtr& operator = (const AutoPtr<Other>& ptr)
+	{
+		return assign<Other>(ptr);
+	}
+
+	void swap(AutoPtr& ptr)
+	{
+		std::swap(_ptr, ptr._ptr);
+	}
+	
+	template <class Other> 
+	AutoPtr<Other> cast() const
+		/// Casts the AutoPtr via a dynamic cast to the given type.
+		/// Returns an AutoPtr containing NULL if the cast fails.
+		/// Example: (assume class Sub: public Super)
+		///    AutoPtr<Super> super(new Sub());
+		///    AutoPtr<Sub> sub = super.cast<Sub>();
+		///    poco_assert (sub.get());
+	{
+		Other* pOther = dynamic_cast<Other*>(_ptr);
+		return AutoPtr<Other>(pOther, true);
+	}
+
+	template <class Other> 
+	AutoPtr<Other> unsafeCast() const
+		/// Casts the AutoPtr via a static cast to the given type.
+		/// Example: (assume class Sub: public Super)
+		///    AutoPtr<Super> super(new Sub());
+		///    AutoPtr<Sub> sub = super.unsafeCast<Sub>();
+		///    poco_assert (sub.get());
+	{
+		Other* pOther = static_cast<Other*>(_ptr);
+		return AutoPtr<Other>(pOther, true);
+	}
+
+	C* operator -> ()
+	{
+		if (_ptr)
+			return _ptr;
+		else
+			throw NullPointerException();
+	}
+
+	const C* operator -> () const
+	{
+		if (_ptr)
+			return _ptr;
+		else
+			throw NullPointerException();
+	}
+
+	C& operator * ()
+	{
+		if (_ptr)
+			return *_ptr;
+		else
+			throw NullPointerException();
+	}
+
+	const C& operator * () const
+	{
+		if (_ptr)
+			return *_ptr;
+		else
+			throw NullPointerException();
+	}
+
+	C* get()
+	{
+		return _ptr;
+	}
+
+	const C* get() const
+	{
+		return _ptr;
+	}
+
+	operator C* ()
+	{
+		return _ptr;
+	}
+	
+	operator const C* () const
+	{
+		return _ptr;
+	}
+	
+	bool operator ! () const
+	{
+		return _ptr == 0;
+	}
+
+	bool isNull() const
+	{
+		return _ptr == 0;
+	}
+	
+	C* duplicate()
+	{
+		if (_ptr) _ptr->duplicate();
+		return _ptr;
+	}
+
+	bool operator == (const AutoPtr& ptr) const
+	{
+		return _ptr == ptr._ptr;
+	}
+
+	bool operator == (const C* ptr) const
+	{
+		return _ptr == ptr;
+	}
+
+	bool operator == (C* ptr) const
+	{
+		return _ptr == ptr;
+	}
+
+	bool operator != (const AutoPtr& ptr) const
+	{
+		return _ptr != ptr._ptr;
+	}
+
+	bool operator != (const C* ptr) const
+	{
+		return _ptr != ptr;
+	}
+
+	bool operator != (C* ptr) const
+	{
+		return _ptr != ptr;
+	}
+
+	bool operator < (const AutoPtr& ptr) const
+	{
+		return _ptr < ptr._ptr;
+	}
+
+	bool operator < (const C* ptr) const
+	{
+		return _ptr < ptr;
+	}
+
+	bool operator < (C* ptr) const
+	{
+		return _ptr < ptr;
+	}
+
+	bool operator <= (const AutoPtr& ptr) const
+	{
+		return _ptr <= ptr._ptr;
+	}
+
+	bool operator <= (const C* ptr) const
+	{
+		return _ptr <= ptr;
+	}
+
+	bool operator <= (C* ptr) const
+	{
+		return _ptr <= ptr;
+	}
+
+	bool operator > (const AutoPtr& ptr) const
+	{
+		return _ptr > ptr._ptr;
+	}
+
+	bool operator > (const C* ptr) const
+	{
+		return _ptr > ptr;
+	}
+
+	bool operator > (C* ptr) const
+	{
+		return _ptr > ptr;
+	}
+
+	bool operator >= (const AutoPtr& ptr) const
+	{
+		return _ptr >= ptr._ptr;
+	}
+
+	bool operator >= (const C* ptr) const
+	{
+		return _ptr >= ptr;
+	}
+
+	bool operator >= (C* ptr) const
+	{
+		return _ptr >= ptr;
+	}
+
+private:
+	C* _ptr;
+};
+
+
+template <class C>
+inline void swap(AutoPtr<C>& p1, AutoPtr<C>& p2)
+{
+	p1.swap(p2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AutoPtr_INCLUDED
diff --git a/Poco/AutoReleasePool.h b/Poco/AutoReleasePool.h
new file mode 100644
index 0000000..0b13956
--- /dev/null
+++ b/Poco/AutoReleasePool.h
@@ -0,0 +1,86 @@
+//
+// AutoReleasePool.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  AutoReleasePool
+//
+// Definition of the AutoReleasePool class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_AutoReleasePool_INCLUDED
+#define Foundation_AutoReleasePool_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <list>
+
+
+namespace Poco {
+
+
+template <class C>
+class AutoReleasePool
+	/// An AutoReleasePool implements simple garbage collection for 
+	/// reference-counted objects.
+	/// It temporarily takes ownwership of reference-counted objects that 
+	/// nobody else wants to take ownership of and releases them 
+	/// at a later, appropriate point in time.
+	///
+	/// Note: The correct way to add an object hold by an AutoPtr<> to
+	/// an AutoReleasePool is by invoking the AutoPtr's duplicate()
+	/// method. Example:
+	///    AutoReleasePool<C> arp;
+	///    AutoPtr<C> ptr = new C;
+	///    ...
+	///    arp.add(ptr.duplicate());
+{
+public:
+	AutoReleasePool()
+		/// Creates the AutoReleasePool.
+	{
+	}
+	
+	~AutoReleasePool()
+		/// Destroys the AutoReleasePool and releases
+		/// all objects it currently holds.
+	{
+		release();
+	}
+	
+	void add(C* pObject)
+		/// Adds the given object to the AutoReleasePool.
+		/// The object's reference count is not modified
+	{
+		if (pObject)
+			_list.push_back(pObject);
+	}
+	
+	void release()
+		/// Releases all objects the AutoReleasePool currently holds
+		/// by calling each object's release() method.
+	{
+		while (!_list.empty())
+		{
+			_list.front()->release();
+			_list.pop_front();
+		}
+	}
+	
+private:
+	typedef std::list<C*> ObjectList;
+	
+	ObjectList _list;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_AutoReleasePool_INCLUDED
diff --git a/Poco/Base32Decoder.h b/Poco/Base32Decoder.h
new file mode 100644
index 0000000..54367c5
--- /dev/null
+++ b/Poco/Base32Decoder.h
@@ -0,0 +1,104 @@
+//
+// Base32Decoder.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  Base32
+//
+// Definition of class Base32Decoder.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Base32Decoder_INCLUDED
+#define Foundation_Base32Decoder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class Foundation_API Base32DecoderBuf: public UnbufferedStreamBuf
+	/// This streambuf base32-decodes all data read
+	/// from the istream connected to it.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	Base32DecoderBuf(std::istream& istr);
+	~Base32DecoderBuf();
+	
+private:
+	int readFromDevice();
+	int readOne();
+
+	unsigned char   _group[8];
+	int             _groupLength;
+	int             _groupIndex;
+	std::streambuf& _buf;
+	
+	static unsigned char IN_ENCODING[256];
+	static bool          IN_ENCODING_INIT;
+	
+private:
+	Base32DecoderBuf(const Base32DecoderBuf&);
+	Base32DecoderBuf& operator = (const Base32DecoderBuf&);
+};
+
+
+class Foundation_API Base32DecoderIOS: public virtual std::ios
+	/// The base class for Base32Decoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	Base32DecoderIOS(std::istream& istr);
+	~Base32DecoderIOS();
+	Base32DecoderBuf* rdbuf();
+
+protected:
+	Base32DecoderBuf _buf;
+	
+private:
+	Base32DecoderIOS(const Base32DecoderIOS&);
+	Base32DecoderIOS& operator = (const Base32DecoderIOS&);
+};
+
+
+class Foundation_API Base32Decoder: public Base32DecoderIOS, public std::istream
+	/// This istream base32-decodes all data
+	/// read from the istream connected to it.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	Base32Decoder(std::istream& istr);
+	~Base32Decoder();
+
+private:
+	Base32Decoder(const Base32Decoder&);
+	Base32Decoder& operator = (const Base32Decoder&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Base32Decoder_INCLUDED
diff --git a/Poco/Base32Encoder.h b/Poco/Base32Encoder.h
new file mode 100644
index 0000000..246f848
--- /dev/null
+++ b/Poco/Base32Encoder.h
@@ -0,0 +1,110 @@
+//
+// Base32Encoder.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  Base32
+//
+// Definition of class Base32Encoder.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Base32Encoder_INCLUDED
+#define Foundation_Base32Encoder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API Base32EncoderBuf: public UnbufferedStreamBuf
+	/// This streambuf base32-encodes all data written
+	/// to it and forwards it to a connected
+	/// ostream.
+	///
+	/// Note: The characters are directly written
+	/// to the ostream's streambuf, thus bypassing
+	/// the ostream. The ostream's state is therefore
+	/// not updated to match the buffer's state.
+{
+public:
+	Base32EncoderBuf(std::ostream& ostr, bool padding = true);
+	~Base32EncoderBuf();
+	
+	int close();
+		/// Closes the stream buffer.
+
+private:
+	int writeToDevice(char c);
+
+	unsigned char   _group[5];
+	int             _groupLength;
+	std::streambuf& _buf;
+	bool		_doPadding;
+	
+	static const unsigned char OUT_ENCODING[32];
+	
+	friend class Base32DecoderBuf;
+
+	Base32EncoderBuf(const Base32EncoderBuf&);
+	Base32EncoderBuf& operator = (const Base32EncoderBuf&);
+};
+
+
+class Foundation_API Base32EncoderIOS: public virtual std::ios
+	/// The base class for Base32Encoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	Base32EncoderIOS(std::ostream& ostr, bool padding = true);
+	~Base32EncoderIOS();
+	int close();
+	Base32EncoderBuf* rdbuf();
+
+protected:
+	Base32EncoderBuf _buf;
+
+private:
+	Base32EncoderIOS(const Base32EncoderIOS&);
+	Base32EncoderIOS& operator = (const Base32EncoderIOS&);
+};
+
+
+class Foundation_API Base32Encoder: public Base32EncoderIOS, public std::ostream
+	/// This ostream base32-encodes all data
+	/// written to it and forwards it to
+	/// a connected ostream.
+	/// Always call close() when done
+	/// writing data, to ensure proper
+	/// completion of the encoding operation.
+	///
+	/// Note: The characters are directly written
+	/// to the ostream's streambuf, thus bypassing
+	/// the ostream. The ostream's state is therefore
+	/// not updated to match the buffer's state.
+{
+public:
+	Base32Encoder(std::ostream& ostr, bool padding = true);
+	~Base32Encoder();
+
+private:
+	Base32Encoder(const Base32Encoder&);
+	Base32Encoder& operator = (const Base32Encoder&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Base32Encoder_INCLUDED
diff --git a/Poco/Base64Decoder.h b/Poco/Base64Decoder.h
new file mode 100644
index 0000000..5195823
--- /dev/null
+++ b/Poco/Base64Decoder.h
@@ -0,0 +1,108 @@
+//
+// Base64Decoder.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  Base64
+//
+// Definition of class Base64Decoder.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Base64Decoder_INCLUDED
+#define Foundation_Base64Decoder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class Foundation_API Base64DecoderBuf: public UnbufferedStreamBuf
+	/// This streambuf base64-decodes all data read
+	/// from the istream connected to it.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	Base64DecoderBuf(std::istream& istr, int options = 0);
+	~Base64DecoderBuf();
+
+private:
+	int readFromDevice();
+	int readOne();
+
+	int             _options;
+	unsigned char   _group[3];
+	int             _groupLength;
+	int             _groupIndex;
+	std::streambuf& _buf;
+	const unsigned char* _pInEncoding;
+
+	static unsigned char IN_ENCODING[256];
+	static bool          IN_ENCODING_INIT;
+	static unsigned char IN_ENCODING_URL[256];
+	static bool          IN_ENCODING_URL_INIT;
+
+private:
+	Base64DecoderBuf(const Base64DecoderBuf&);
+	Base64DecoderBuf& operator = (const Base64DecoderBuf&);
+};
+
+
+class Foundation_API Base64DecoderIOS: public virtual std::ios
+	/// The base class for Base64Decoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	Base64DecoderIOS(std::istream& istr, int options = 0);
+	~Base64DecoderIOS();
+	Base64DecoderBuf* rdbuf();
+
+protected:
+	Base64DecoderBuf _buf;
+
+private:
+	Base64DecoderIOS(const Base64DecoderIOS&);
+	Base64DecoderIOS& operator = (const Base64DecoderIOS&);
+};
+
+
+class Foundation_API Base64Decoder: public Base64DecoderIOS, public std::istream
+	/// This istream base64-decodes all data
+	/// read from the istream connected to it.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	Base64Decoder(std::istream& istr, int options = 0);
+	~Base64Decoder();
+
+private:
+	Base64Decoder(const Base64Decoder&);
+	Base64Decoder& operator = (const Base64Decoder&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Base64Decoder_INCLUDED
diff --git a/Poco/Base64Encoder.h b/Poco/Base64Encoder.h
new file mode 100644
index 0000000..4371803
--- /dev/null
+++ b/Poco/Base64Encoder.h
@@ -0,0 +1,138 @@
+//
+// Base64Encoder.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  Base64
+//
+// Definition of class Base64Encoder.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Base64Encoder_INCLUDED
+#define Foundation_Base64Encoder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <ostream>
+
+
+namespace Poco {
+
+
+enum Base64EncodingOptions
+{
+	BASE64_URL_ENCODING = 0x01,
+		/// Use the URL and filename-safe alphabet,
+		/// replacing '+' with '-' and '/' with '_'.
+		///
+		/// Will also set line length to unlimited.
+
+	BASE64_NO_PADDING   = 0x02
+		/// Do not append padding characters ('=') at end.
+};
+
+
+class Foundation_API Base64EncoderBuf: public UnbufferedStreamBuf
+	/// This streambuf base64-encodes all data written
+	/// to it and forwards it to a connected
+	/// ostream.
+	///
+	/// Note: The characters are directly written
+	/// to the ostream's streambuf, thus bypassing
+	/// the ostream. The ostream's state is therefore
+	/// not updated to match the buffer's state.
+{
+public:
+	Base64EncoderBuf(std::ostream& ostr, int options = 0);
+	~Base64EncoderBuf();
+
+	int close();
+		/// Closes the stream buffer.
+
+	void setLineLength(int lineLength);
+		/// Specify the line length.
+		///
+		/// After the given number of characters have been written, 
+		/// a newline character will be written.
+		///
+		/// Specify 0 for an unlimited line length.
+
+	int getLineLength() const;
+		/// Returns the currently set line length.
+
+private:
+	int writeToDevice(char c);
+
+	int             _options;
+	unsigned char   _group[3];
+	int             _groupLength;
+	int             _pos;
+	int             _lineLength;
+	std::streambuf& _buf;
+	const unsigned char* _pOutEncoding;
+
+	static const unsigned char OUT_ENCODING[64];
+	static const unsigned char OUT_ENCODING_URL[64];
+
+	friend class Base64DecoderBuf;
+
+	Base64EncoderBuf(const Base64EncoderBuf&);
+	Base64EncoderBuf& operator = (const Base64EncoderBuf&);
+};
+
+
+class Foundation_API Base64EncoderIOS: public virtual std::ios
+	/// The base class for Base64Encoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	Base64EncoderIOS(std::ostream& ostr, int options = 0);
+	~Base64EncoderIOS();
+	int close();
+	Base64EncoderBuf* rdbuf();
+
+protected:
+	Base64EncoderBuf _buf;
+
+private:
+	Base64EncoderIOS(const Base64EncoderIOS&);
+	Base64EncoderIOS& operator = (const Base64EncoderIOS&);
+};
+
+
+class Foundation_API Base64Encoder: public Base64EncoderIOS, public std::ostream
+	/// This ostream base64-encodes all data
+	/// written to it and forwards it to
+	/// a connected ostream.
+	/// Always call close() when done
+	/// writing data, to ensure proper
+	/// completion of the encoding operation.
+	///
+	/// Note: The characters are directly written
+	/// to the ostream's streambuf, thus bypassing
+	/// the ostream. The ostream's state is therefore
+	/// not updated to match the buffer's state.
+{
+public:
+	Base64Encoder(std::ostream& ostr, int options = 0);
+	~Base64Encoder();
+
+private:
+	Base64Encoder(const Base64Encoder&);
+	Base64Encoder& operator = (const Base64Encoder&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Base64Encoder_INCLUDED
diff --git a/Poco/BasicEvent.h b/Poco/BasicEvent.h
new file mode 100644
index 0000000..bc2dd51
--- /dev/null
+++ b/Poco/BasicEvent.h
@@ -0,0 +1,60 @@
+//
+// BasicEvent.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  BasicEvent
+//
+// Implementation of the BasicEvent template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_BasicEvent_INCLUDED
+#define Foundation_BasicEvent_INCLUDED
+
+
+#include "Poco/AbstractEvent.h"
+#include "Poco/DefaultStrategy.h"
+#include "Poco/AbstractDelegate.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class TArgs, class TMutex = FastMutex> 
+class BasicEvent: public AbstractEvent < 
+	TArgs, DefaultStrategy<TArgs, AbstractDelegate<TArgs> >,
+	AbstractDelegate<TArgs>,
+	TMutex
+>
+	/// A BasicEvent uses the DefaultStrategy which 
+	/// invokes delegates in the order they have been registered.
+	///
+	/// Please see the AbstractEvent class template documentation
+	/// for more information.
+{
+public:
+	BasicEvent()
+	{
+	}
+
+	~BasicEvent()
+	{
+	}
+
+private:
+	BasicEvent(const BasicEvent& e);
+	BasicEvent& operator = (const BasicEvent& e);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_BasicEvent_INCLUDED
diff --git a/Poco/BinaryReader.h b/Poco/BinaryReader.h
new file mode 100644
index 0000000..70d5954
--- /dev/null
+++ b/Poco/BinaryReader.h
@@ -0,0 +1,265 @@
+//
+// BinaryReader.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  BinaryReaderWriter
+//
+// Definition of the BinaryReader class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_BinaryReader_INCLUDED
+#define Foundation_BinaryReader_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Buffer.h"
+#include "Poco/MemoryStream.h"
+#include <vector>
+#include <istream>
+
+
+namespace Poco {
+
+
+class TextEncoding;
+class TextConverter;
+
+
+class Foundation_API BinaryReader
+	/// This class reads basic types (and std::vectors thereof)
+	/// in binary form into an input stream.
+	/// It provides an extractor-based interface similar to istream.
+	/// The reader also supports automatic conversion from big-endian
+	/// (network byte order) to little-endian and vice-versa.
+	/// Use a BinaryWriter to create a stream suitable for a BinaryReader.
+{
+public:
+	enum StreamByteOrder
+	{
+		NATIVE_BYTE_ORDER        = 1,  /// the host's native byte-order
+		BIG_ENDIAN_BYTE_ORDER    = 2,  /// big-endian (network) byte-order
+		NETWORK_BYTE_ORDER       = 2,  /// big-endian (network) byte-order
+		LITTLE_ENDIAN_BYTE_ORDER = 3,  /// little-endian byte-order
+		UNSPECIFIED_BYTE_ORDER   = 4   /// unknown, byte-order will be determined by reading the byte-order mark
+	};
+
+	BinaryReader(std::istream& istr, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
+		/// Creates the BinaryReader.
+
+	BinaryReader(std::istream& istr, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
+		/// Creates the BinaryReader using the given TextEncoding.
+		///
+		/// Strings will be converted from the specified encoding
+		/// to the currently set global encoding (see Poco::TextEncoding::global()).
+
+	~BinaryReader();
+		/// Destroys the BinaryReader.
+
+	BinaryReader& operator >> (bool& value);
+	BinaryReader& operator >> (char& value);
+	BinaryReader& operator >> (unsigned char& value);
+	BinaryReader& operator >> (signed char& value);
+	BinaryReader& operator >> (short& value);
+	BinaryReader& operator >> (unsigned short& value);
+	BinaryReader& operator >> (int& value);
+	BinaryReader& operator >> (unsigned int& value);
+	BinaryReader& operator >> (long& value);
+	BinaryReader& operator >> (unsigned long& value);
+	BinaryReader& operator >> (float& value);
+	BinaryReader& operator >> (double& value);
+
+#if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT)
+	BinaryReader& operator >> (Int64& value);
+	BinaryReader& operator >> (UInt64& value);
+#endif
+
+	BinaryReader& operator >> (std::string& value);
+
+	template <typename T>
+	BinaryReader& operator >> (std::vector<T>& value)
+	{
+		Poco::UInt32 size(0);
+		T elem;
+
+		*this >> size;
+		if (!good()) return *this;
+		value.reserve(size);
+		while (this->good() && size-- > 0)
+		{
+			*this >> elem;
+			value.push_back(elem);
+		}
+		return *this;
+	}
+
+	void read7BitEncoded(UInt32& value);
+		/// Reads a 32-bit unsigned integer in compressed format.
+		/// See BinaryWriter::write7BitEncoded() for a description
+		/// of the compression algorithm.
+
+#if defined(POCO_HAVE_INT64)
+	void read7BitEncoded(UInt64& value);
+		/// Reads a 64-bit unsigned integer in compressed format.
+		/// See BinaryWriter::write7BitEncoded() for a description
+		/// of the compression algorithm.
+#endif
+
+	void readRaw(std::streamsize length, std::string& value);
+		/// Reads length bytes of raw data into value.
+
+	void readRaw(char* buffer, std::streamsize length);
+		/// Reads length bytes of raw data into buffer.
+
+	void readBOM();
+		/// Reads a byte-order mark from the stream and configures
+		/// the reader for the encountered byte order.
+		/// A byte-order mark is a 16-bit integer with a value of 0xFEFF,
+		/// written in host byte order.
+		
+	bool good();
+		/// Returns _istr.good();
+		
+	bool fail();
+		/// Returns _istr.fail();
+
+	bool bad();
+		/// Returns _istr.bad();
+	
+	bool eof();
+		/// Returns _istr.eof();
+
+	std::istream& stream() const;
+		/// Returns the underlying stream.
+		
+	StreamByteOrder byteOrder() const;
+		/// Returns the byte-order used by the reader, which is
+		/// either BIG_ENDIAN_BYTE_ORDER or LITTLE_ENDIAN_BYTE_ORDER.
+
+	void setExceptions(std::ios_base::iostate st = (std::istream::failbit | std::istream::badbit));
+		/// Sets the stream to throw exception on specified state (default failbit and badbit);
+
+	std::streamsize available() const;
+		/// Returns the number of available bytes in the stream.
+
+private:
+	std::istream&  _istr;
+	bool           _flipBytes; 
+	TextConverter* _pTextConverter;
+};
+
+
+template <typename T>
+class BasicMemoryBinaryReader : public BinaryReader
+	/// A convenient wrapper for using Buffer and MemoryStream with BinaryReader.
+{
+public:
+	BasicMemoryBinaryReader(const Buffer<T>& data, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER):
+		BinaryReader(_istr, byteOrder),
+		_data(data),
+		_istr(data.begin(), data.capacity())
+	{
+	}
+
+	BasicMemoryBinaryReader(const Buffer<T>& data, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER):
+		BinaryReader(_istr, encoding, byteOrder),
+		_data(data),
+		_istr(data.begin(), data.capacity())
+	{
+	}
+
+	~BasicMemoryBinaryReader()
+	{
+	}
+
+	const Buffer<T>& data() const
+	{
+		return _data;
+	}
+
+	const MemoryInputStream& stream() const
+	{
+		return _istr;
+	}
+
+	MemoryInputStream& stream()
+	{
+		return _istr;
+	}
+
+private:
+	const Buffer<T>& _data;
+	MemoryInputStream _istr;
+};
+
+
+typedef BasicMemoryBinaryReader<char> MemoryBinaryReader;
+
+
+//
+// inlines
+//
+
+
+inline bool BinaryReader::good()
+{
+	return _istr.good();
+}
+
+	
+inline bool BinaryReader::fail()
+{
+	return _istr.fail();
+}
+
+
+inline bool BinaryReader::bad()
+{
+	return _istr.bad();
+}
+
+
+inline bool BinaryReader::eof()
+{
+	return _istr.eof();
+}
+
+
+inline std::istream& BinaryReader::stream() const
+{
+	return _istr;
+}
+
+	
+inline BinaryReader::StreamByteOrder BinaryReader::byteOrder() const
+{
+#if defined(POCO_ARCH_BIG_ENDIAN)
+	return _flipBytes ? LITTLE_ENDIAN_BYTE_ORDER : BIG_ENDIAN_BYTE_ORDER;
+#else
+	return _flipBytes ? BIG_ENDIAN_BYTE_ORDER : LITTLE_ENDIAN_BYTE_ORDER;
+#endif
+}
+
+
+inline void BinaryReader::setExceptions(std::ios_base::iostate st)
+{
+	_istr.exceptions(st);
+}
+
+
+inline std::streamsize BinaryReader::available() const
+{
+	return _istr.rdbuf()->in_avail();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_BinaryReader_INCLUDED
diff --git a/Poco/BinaryWriter.h b/Poco/BinaryWriter.h
new file mode 100644
index 0000000..7941117
--- /dev/null
+++ b/Poco/BinaryWriter.h
@@ -0,0 +1,269 @@
+//
+// BinaryWriter.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  BinaryReaderWriter
+//
+// Definition of the BinaryWriter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_BinaryWriter_INCLUDED
+#define Foundation_BinaryWriter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Buffer.h"
+#include "Poco/MemoryStream.h"
+#include <vector>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class TextEncoding;
+class TextConverter;
+
+
+class Foundation_API BinaryWriter
+	/// This class writes basic types (and std::vectors of these) 
+	/// in binary form into an output stream.
+	/// It provides an inserter-based interface similar to ostream.
+	/// The writer also supports automatic conversion from big-endian
+	/// (network byte order) to little-endian and vice-versa.
+	/// Use a BinaryReader to read from a stream created by a BinaryWriter.
+	/// Be careful when exchanging data between systems with different
+	/// data type sizes (e.g., 32-bit and 64-bit architectures), as the sizes
+	/// of some of the basic types may be different. For example, writing a
+	/// long integer on a 64-bit system and reading it on a 32-bit system
+	/// may yield an incorrent result. Use fixed-size types (Int32, Int64, etc.)
+	/// in such a case.
+{
+public:
+	enum StreamByteOrder
+	{
+		NATIVE_BYTE_ORDER        = 1, /// the host's native byte-order
+		BIG_ENDIAN_BYTE_ORDER    = 2, /// big-endian (network) byte-order
+		NETWORK_BYTE_ORDER       = 2, /// big-endian (network) byte-order
+		LITTLE_ENDIAN_BYTE_ORDER = 3  /// little-endian byte-order
+	};
+	
+	BinaryWriter(std::ostream& ostr, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
+		/// Creates the BinaryWriter.
+
+	BinaryWriter(std::ostream& ostr, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER);
+		/// Creates the BinaryWriter using the given TextEncoding.
+		///
+		/// Strings will be converted from the currently set global encoding
+		/// (see Poco::TextEncoding::global()) to the specified encoding.
+
+	~BinaryWriter();
+		/// Destroys the BinaryWriter.
+
+	BinaryWriter& operator << (bool value);
+	BinaryWriter& operator << (char value);
+	BinaryWriter& operator << (unsigned char value);
+	BinaryWriter& operator << (signed char value);
+	BinaryWriter& operator << (short value);
+	BinaryWriter& operator << (unsigned short value);
+	BinaryWriter& operator << (int value);
+	BinaryWriter& operator << (unsigned int value);
+	BinaryWriter& operator << (long value);
+	BinaryWriter& operator << (unsigned long value);
+	BinaryWriter& operator << (float value);
+	BinaryWriter& operator << (double value);
+
+#if defined(POCO_HAVE_INT64) && !defined(POCO_LONG_IS_64_BIT)
+	BinaryWriter& operator << (Int64 value);
+	BinaryWriter& operator << (UInt64 value);
+#endif
+
+	BinaryWriter& operator << (const std::string& value);
+	BinaryWriter& operator << (const char* value);
+
+	template <typename T>
+	BinaryWriter& operator << (const std::vector<T>& value)
+	{
+		Poco::UInt32 size(static_cast<Poco::UInt32>(value.size()));
+
+		*this << size;
+		for (typename std::vector<T>::const_iterator it = value.begin(); it != value.end(); ++it)
+		{
+			*this << *it;
+		}
+
+		return *this;
+	}
+	
+	void write7BitEncoded(UInt32 value);
+		/// Writes a 32-bit unsigned integer in a compressed format.
+		/// The value is written out seven bits at a time, starting 
+		/// with the seven least-significant bits. 
+		/// The high bit of a byte indicates whether there are more bytes to be 
+		/// written after this one.
+		/// If value will fit in seven bits, it takes only one byte of space. 
+		/// If value will not fit in seven bits, the high bit is set on the first byte and 
+		/// written out. value is then shifted by seven bits and the next byte is written. 
+		/// This process is repeated until the entire integer has been written.
+
+#if defined(POCO_HAVE_INT64)
+	void write7BitEncoded(UInt64 value);
+		/// Writes a 64-bit unsigned integer in a compressed format.
+		/// The value written out seven bits at a time, starting 
+		/// with the seven least-significant bits. 
+		/// The high bit of a byte indicates whether there are more bytes to be 
+		/// written after this one.
+		/// If value will fit in seven bits, it takes only one byte of space. 
+		/// If value will not fit in seven bits, the high bit is set on the first byte and 
+		/// written out. value is then shifted by seven bits and the next byte is written. 
+		/// This process is repeated until the entire integer has been written.
+#endif
+
+	void writeRaw(const std::string& rawData);
+		/// Writes the string as-is to the stream.
+		
+	void writeRaw(const char* buffer, std::streamsize length);
+		/// Writes length raw bytes from the given buffer to the stream.
+
+	void writeBOM();
+		/// Writes a byte-order mark to the stream. A byte order mark is
+		/// a 16-bit integer with a value of 0xFEFF, written in host byte-order. 
+		/// A BinaryReader uses the byte-order mark to determine the byte-order 
+		/// of the stream.
+
+	void flush();
+		/// Flushes the underlying stream.
+		
+	bool good();
+		/// Returns _ostr.good();
+		
+	bool fail();
+		/// Returns _ostr.fail();
+	
+	bool bad();
+		/// Returns _ostr.bad();
+		
+	std::ostream& stream() const;
+		/// Returns the underlying stream.
+		
+	StreamByteOrder byteOrder() const;
+		/// Returns the byte ordering used by the writer, which is
+		/// either BIG_ENDIAN_BYTE_ORDER or LITTLE_ENDIAN_BYTE_ORDER.
+
+private:
+	std::ostream&  _ostr;
+	bool           _flipBytes;
+	TextConverter* _pTextConverter;
+};
+
+
+template <typename T>
+class BasicMemoryBinaryWriter: public BinaryWriter
+	/// A convenient wrapper for using Buffer and MemoryStream with BinarWriter.
+{
+public:
+	BasicMemoryBinaryWriter(Buffer<T>& data, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER): 
+		BinaryWriter(_ostr, byteOrder),
+		_data(data),
+		_ostr(data.begin(), data.capacity())
+	{
+	}
+
+	BasicMemoryBinaryWriter(Buffer<T>& data, TextEncoding& encoding, StreamByteOrder byteOrder = NATIVE_BYTE_ORDER): 
+		BinaryWriter(_ostr, encoding, byteOrder),
+		_data(data),
+		_ostr(data.begin(), data.capacity())
+	{
+	}
+
+	~BasicMemoryBinaryWriter()
+	{
+		try
+		{
+			flush();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	Buffer<T>& data()
+	{
+		return _data;
+	}
+
+	const Buffer<T>& data() const
+	{
+		return _data;
+	}
+
+	const MemoryOutputStream& stream() const
+	{
+		return _ostr;
+	}
+
+	MemoryOutputStream& stream()
+	{
+		return _ostr;
+	}
+
+private:
+	Buffer<T>& _data;
+	MemoryOutputStream _ostr;
+};
+
+
+typedef BasicMemoryBinaryWriter<char> MemoryBinaryWriter;
+
+
+//
+// inlines
+//
+
+
+inline std::ostream& BinaryWriter::stream() const
+{
+	return _ostr;
+}
+
+
+inline bool BinaryWriter::good()
+{
+	return _ostr.good();
+}
+
+
+inline bool BinaryWriter::fail()
+{
+	return _ostr.fail();
+}
+
+
+inline bool BinaryWriter::bad()
+{
+	return _ostr.bad();
+}
+
+
+inline BinaryWriter::StreamByteOrder BinaryWriter::byteOrder() const
+{
+#if defined(POCO_ARCH_BIG_ENDIAN)
+	return _flipBytes ? LITTLE_ENDIAN_BYTE_ORDER : BIG_ENDIAN_BYTE_ORDER;
+#else
+	return _flipBytes ? BIG_ENDIAN_BYTE_ORDER : LITTLE_ENDIAN_BYTE_ORDER;
+#endif
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_BinaryWriter_INCLUDED
diff --git a/Poco/Buffer.h b/Poco/Buffer.h
new file mode 100644
index 0000000..7d239b1
--- /dev/null
+++ b/Poco/Buffer.h
@@ -0,0 +1,329 @@
+//
+// Buffer.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Buffer
+//
+// Definition of the Buffer class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Buffer_INCLUDED
+#define Foundation_Buffer_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <cstring>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+template <class T>
+class Buffer
+	/// A buffer class that allocates a buffer of a given type and size 
+	/// in the constructor and deallocates the buffer in the destructor.
+	///
+	/// This class is useful everywhere where a temporary buffer
+	/// is needed.
+{
+public:
+	Buffer(std::size_t capacity):
+		_capacity(capacity),
+		_used(capacity),
+		_ptr(0),
+		_ownMem(true)
+		/// Creates and allocates the Buffer.
+	{
+		if (capacity > 0)
+		{
+			_ptr = new T[capacity];
+		}
+	}
+
+	Buffer(T* pMem, std::size_t length):
+		_capacity(length),
+		_used(length),
+		_ptr(pMem),
+		_ownMem(false)
+		/// Creates the Buffer. Length argument specifies the length
+		/// of the supplied memory pointed to by pMem in the number
+		/// of elements of type T. Supplied pointer is considered
+		/// blank and not owned by Buffer, so in this case Buffer 
+		/// only acts as a wrapper around externally supplied 
+		/// (and lifetime-managed) memory.
+	{
+	}
+
+	Buffer(const T* pMem, std::size_t length):
+		_capacity(length),
+		_used(length),
+		_ptr(0),
+		_ownMem(true)
+		/// Creates and allocates the Buffer; copies the contents of
+		/// the supplied memory into the buffer. Length argument specifies
+		/// the length of the supplied memory pointed to by pMem in the
+		/// number of elements of type T.
+	{
+		if (_capacity > 0)
+		{
+			_ptr = new T[_capacity];
+			std::memcpy(_ptr, pMem, _used * sizeof(T));
+		}
+	}
+
+	Buffer(const Buffer& other):
+		/// Copy constructor.
+		_capacity(other._used),
+		_used(other._used),
+		_ptr(0),
+		_ownMem(true)
+	{
+		if (_used)
+		{
+			_ptr = new T[_used];
+			std::memcpy(_ptr, other._ptr, _used * sizeof(T));
+		}
+	}
+
+	Buffer& operator = (const Buffer& other)
+		/// Assignment operator.
+	{
+		if (this != &other)
+		{
+			Buffer tmp(other);
+			swap(tmp);
+		}
+
+		return *this;
+	}
+
+	~Buffer()
+		/// Destroys the Buffer.
+	{
+		if (_ownMem) delete [] _ptr;
+	}
+	
+	void resize(std::size_t newCapacity, bool preserveContent = true)
+		/// Resizes the buffer capacity and size. If preserveContent is true,
+		/// the content of the old buffer is copied over to the
+		/// new buffer. The new capacity can be larger or smaller than
+		/// the current one; if it is smaller, capacity will remain intact.
+		/// Size will always be set to the new capacity.
+		///  
+		/// Buffers only wrapping externally owned storage can not be 
+		/// resized. If resize is attempted on those, IllegalAccessException
+		/// is thrown.
+	{
+		if (!_ownMem) throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage.");
+
+		if (newCapacity > _capacity)
+		{
+			T* ptr = new T[newCapacity];
+			if (preserveContent)
+			{
+				std::memcpy(ptr, _ptr, _used * sizeof(T));
+			}
+			delete [] _ptr;
+			_ptr = ptr;
+			_capacity = newCapacity;
+		}
+		
+		_used = newCapacity;
+	}
+	
+	void setCapacity(std::size_t newCapacity, bool preserveContent = true)
+		/// Sets the buffer capacity. If preserveContent is true,
+		/// the content of the old buffer is copied over to the
+		/// new buffer. The new capacity can be larger or smaller than
+		/// the current one; size will be set to the new capacity only if 
+		/// new capacity is smaller than the current size, otherwise it will
+		/// remain intact.
+		/// 
+		/// Buffers only wrapping externally owned storage can not be 
+		/// resized. If resize is attempted on those, IllegalAccessException
+		/// is thrown.
+	{
+		if (!_ownMem) throw Poco::InvalidAccessException("Cannot resize buffer which does not own its storage.");
+
+		if (newCapacity != _capacity)
+		{
+			T* ptr = 0;
+			if (newCapacity > 0)
+			{
+				ptr = new T[newCapacity];
+				if (preserveContent)
+				{
+					std::size_t newSz = _used < newCapacity ? _used : newCapacity;
+					std::memcpy(ptr, _ptr, newSz * sizeof(T));
+				}
+			}
+			delete [] _ptr;
+			_ptr = ptr;
+			_capacity = newCapacity;
+
+			if (newCapacity < _used) _used = newCapacity;
+		}
+	}
+
+	void assign(const T* buf, std::size_t sz)
+		/// Assigns the argument buffer to this buffer.
+		/// If necessary, resizes the buffer.
+	{
+		if (0 == sz) return;
+		if (sz > _capacity) resize(sz, false);
+		std::memcpy(_ptr, buf, sz * sizeof(T));
+		_used = sz;
+	}
+
+	void append(const T* buf, std::size_t sz)
+		/// Resizes this buffer and appends the argument buffer.
+	{
+		if (0 == sz) return;
+		resize(_used + sz, true);
+		std::memcpy(_ptr + _used - sz, buf, sz * sizeof(T));
+	}
+
+	void append(T val)
+		/// Resizes this buffer by one element and appends the argument value.
+	{
+		resize(_used + 1, true);
+		_ptr[_used - 1] = val;
+	}
+
+	void append(const Buffer& buf)
+		/// Resizes this buffer and appends the argument buffer.
+	{
+		append(buf.begin(), buf.size());
+	}
+
+	std::size_t capacity() const
+		/// Returns the allocated memory size in elements.
+	{
+		return _capacity;
+	}
+
+	std::size_t capacityBytes() const
+		/// Returns the allocated memory size in bytes.
+	{
+		return _capacity * sizeof(T);
+	}
+
+	void swap(Buffer& other)
+	/// Swaps the buffer with another one.
+	{
+		using std::swap;
+
+		swap(_ptr, other._ptr);
+		swap(_capacity, other._capacity);
+		swap(_used, other._used);
+	}
+
+	bool operator == (const Buffer& other) const
+		/// Compare operator.
+	{
+		if (this != &other)
+		{
+			if (_used == other._used)
+			{
+				if (std::memcmp(_ptr, other._ptr, _used * sizeof(T)) == 0)
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+
+		return true;
+	}
+
+	bool operator != (const Buffer& other) const
+		/// Compare operator.
+	{
+		return !(*this == other);
+	}
+
+	void clear()
+		/// Sets the contents of the buffer to zero.
+	{
+		std::memset(_ptr, 0, _used * sizeof(T));
+	}
+
+	std::size_t size() const
+		/// Returns the used size of the buffer in elements.
+	{
+		return _used;
+	}
+
+	std::size_t sizeBytes() const
+		/// Returns the used size of the buffer in bytes.
+	{
+		return _used * sizeof(T);
+	}
+	
+	T* begin()
+		/// Returns a pointer to the beginning of the buffer.
+	{
+		return _ptr;
+	}
+	
+	const T* begin() const
+		/// Returns a pointer to the beginning of the buffer.
+	{
+		return _ptr;
+	}
+
+	T* end()
+		/// Returns a pointer to end of the buffer.
+	{
+		return _ptr + _used;
+	}
+	
+	const T* end() const
+		/// Returns a pointer to the end of the buffer.
+	{
+		return _ptr + _used;
+	}
+	
+	bool empty() const
+		/// Return true if buffer is empty.
+	{
+		return 0 == _used;
+	}
+
+	T& operator [] (std::size_t index)
+	{
+		poco_assert (index < _used);
+		
+		return _ptr[index];
+	}
+
+	const T& operator [] (std::size_t index) const
+	{
+		poco_assert (index < _used);
+		
+		return _ptr[index];
+	}
+
+private:
+	Buffer();
+
+	std::size_t _capacity;
+	std::size_t _used;
+	T*          _ptr;
+	bool        _ownMem;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Buffer_INCLUDED
diff --git a/Poco/BufferAllocator.h b/Poco/BufferAllocator.h
new file mode 100644
index 0000000..ac71746
--- /dev/null
+++ b/Poco/BufferAllocator.h
@@ -0,0 +1,52 @@
+//
+// BufferAllocator.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  BufferAllocator
+//
+// Definition of the BufferAllocator class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_BufferAllocator_INCLUDED
+#define Foundation_BufferAllocator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <ios>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+template <typename ch>
+class BufferAllocator
+	/// The BufferAllocator used if no specific
+	/// BufferAllocator has been specified.
+{
+public:
+	typedef ch char_type;
+
+	static char_type* allocate(std::streamsize size)
+	{
+		return new char_type[static_cast<std::size_t>(size)];
+	}
+	
+	static void deallocate(char_type* ptr, std::streamsize /*size*/) throw()
+	{
+		delete [] ptr;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_BufferAllocator_INCLUDED
diff --git a/Poco/BufferedBidirectionalStreamBuf.h b/Poco/BufferedBidirectionalStreamBuf.h
new file mode 100644
index 0000000..321c3b1
--- /dev/null
+++ b/Poco/BufferedBidirectionalStreamBuf.h
@@ -0,0 +1,181 @@
+//
+// BufferedBidirectionalStreamBuf.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamBuf
+//
+// Definition of template BasicBufferedBidirectionalStreamBuf and class BufferedBidirectionalStreamBuf.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_BufferedBidirectionalStreamBuf_INCLUDED
+#define Foundation_BufferedBidirectionalStreamBuf_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferAllocator.h"
+#include "Poco/StreamUtil.h"
+#include <streambuf>
+#include <iosfwd>
+#include <ios>
+
+
+namespace Poco {
+
+
+template <typename ch, typename tr, typename ba = BufferAllocator<ch> > 
+class BasicBufferedBidirectionalStreamBuf: public std::basic_streambuf<ch, tr>
+	/// This is an implementation of a buffered bidirectional 
+	/// streambuf that greatly simplifies the implementation of
+	/// custom streambufs of various kinds.
+	/// Derived classes only have to override the methods
+	/// readFromDevice() or writeToDevice().
+	///
+	/// In contrast to BasicBufferedStreambuf, this class supports
+	/// simultaneous read and write access, so in addition to
+	/// istream and ostream this streambuf can also be used
+	/// for implementing an iostream.
+{
+protected:
+	typedef std::basic_streambuf<ch, tr> Base;
+	typedef std::basic_ios<ch, tr> IOS;
+	typedef ch char_type;
+	typedef tr char_traits;
+	typedef ba Allocator;
+	typedef typename Base::int_type int_type;
+	typedef typename Base::pos_type pos_type;
+	typedef typename Base::off_type off_type;
+	typedef typename IOS::openmode openmode;
+
+public:
+	BasicBufferedBidirectionalStreamBuf(std::streamsize bufferSize, openmode mode):
+		_bufsize(bufferSize),
+		_pReadBuffer(Allocator::allocate(_bufsize)),
+		_pWriteBuffer(Allocator::allocate(_bufsize)),
+		_mode(mode)
+	{
+		resetBuffers();
+	}
+
+	~BasicBufferedBidirectionalStreamBuf()
+	{
+		Allocator::deallocate(_pReadBuffer, _bufsize);
+		Allocator::deallocate(_pWriteBuffer, _bufsize);
+	}
+	
+	virtual int_type overflow(int_type c)
+	{
+		if (!(_mode & IOS::out)) return char_traits::eof();
+
+		if (flushBuffer() == std::streamsize(-1)) return char_traits::eof();
+		if (c != char_traits::eof()) 
+		{
+			*this->pptr() = char_traits::to_char_type(c);
+			this->pbump(1);
+		}
+
+		return c;
+	}
+
+	virtual int_type underflow()
+	{
+		if (!(_mode & IOS::in)) return char_traits::eof();
+
+		if (this->gptr() && (this->gptr() < this->egptr()))
+			return char_traits::to_int_type(*this->gptr());
+
+		int putback = int(this->gptr() - this->eback());
+		if (putback > 4) putback = 4;
+
+		char_traits::move(_pReadBuffer + (4 - putback), this->gptr() - putback, putback);
+
+		int n = readFromDevice(_pReadBuffer + 4, _bufsize - 4);
+		if (n <= 0) return char_traits::eof();
+
+		this->setg(_pReadBuffer + (4 - putback), _pReadBuffer + 4, _pReadBuffer + 4 + n);
+
+		// return next character
+		return char_traits::to_int_type(*this->gptr());    
+	}
+
+	virtual int sync()
+	{
+		if (this->pptr() && this->pptr() > this->pbase()) 
+		{
+			if (flushBuffer() == -1) return -1;
+		}
+		return 0;
+	}
+
+protected:
+	void setMode(openmode mode)
+	{
+		_mode = mode;
+	}
+
+	openmode getMode() const
+	{
+		return _mode;
+	}
+	
+	void resetBuffers()
+	{
+		this->setg(_pReadBuffer + 4, _pReadBuffer + 4, _pReadBuffer + 4);
+		this->setp(_pWriteBuffer, _pWriteBuffer + _bufsize);
+	}
+
+private:
+	virtual int readFromDevice(char_type* /*buffer*/, std::streamsize /*length*/)
+	{
+		return 0;
+	}
+
+	virtual int writeToDevice(const char_type* /*buffer*/, std::streamsize /*length*/)
+	{
+		return 0;
+	}
+
+	int flushBuffer()
+	{
+		int n = int(this->pptr() - this->pbase());
+		if (writeToDevice(this->pbase(), n) == n) 
+		{
+			this->pbump(-n);
+			return n;
+		}
+		return -1;
+	}
+
+	std::streamsize _bufsize;
+	char_type*      _pReadBuffer;
+	char_type*      _pWriteBuffer;
+	openmode        _mode;
+
+	BasicBufferedBidirectionalStreamBuf(const BasicBufferedBidirectionalStreamBuf&);
+	BasicBufferedBidirectionalStreamBuf& operator = (const BasicBufferedBidirectionalStreamBuf&);
+};
+
+
+//
+// We provide an instantiation for char.
+//
+// Visual C++ needs a workaround - explicitly importing the template
+// instantiation - to avoid duplicate symbols due to multiple
+// instantiations in different libraries.
+//
+#if defined(_MSC_VER) && defined(POCO_DLL) && !defined(Foundation_EXPORTS) 
+template class Foundation_API BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char> >;
+#endif
+typedef BasicBufferedBidirectionalStreamBuf<char, std::char_traits<char> > BufferedBidirectionalStreamBuf;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_BufferedBidirectionalStreamBuf_INCLUDED
diff --git a/Poco/BufferedStreamBuf.h b/Poco/BufferedStreamBuf.h
new file mode 100644
index 0000000..3e39215
--- /dev/null
+++ b/Poco/BufferedStreamBuf.h
@@ -0,0 +1,173 @@
+//
+// BufferedStreamBuf.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamBuf
+//
+// Definition of template BasicBufferedStreamBuf and class BufferedStreamBuf.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_BufferedStreamBuf_INCLUDED
+#define Foundation_BufferedStreamBuf_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferAllocator.h"
+#include "Poco/StreamUtil.h"
+#include <streambuf>
+#include <iosfwd>
+#include <ios>
+
+
+namespace Poco {
+
+
+template <typename ch, typename tr, typename ba = BufferAllocator<ch> > 
+class BasicBufferedStreamBuf: public std::basic_streambuf<ch, tr>
+	/// This is an implementation of a buffered streambuf
+	/// that greatly simplifies the implementation of
+	/// custom streambufs of various kinds.
+	/// Derived classes only have to override the methods
+	/// readFromDevice() or writeToDevice().
+	///
+	/// This streambuf only supports unidirectional streams.
+	/// In other words, the BasicBufferedStreamBuf can be
+	/// used for the implementation of an istream or an
+	/// ostream, but not for an iostream.
+{
+protected:
+	typedef std::basic_streambuf<ch, tr> Base;
+	typedef std::basic_ios<ch, tr> IOS;
+	typedef ch char_type;
+	typedef tr char_traits;
+	typedef ba Allocator;
+	typedef typename Base::int_type int_type;
+	typedef typename Base::pos_type pos_type;
+	typedef typename Base::off_type off_type;
+	typedef typename IOS::openmode openmode;
+
+public:
+	BasicBufferedStreamBuf(std::streamsize bufferSize, openmode mode):
+		_bufsize(bufferSize),
+		_pBuffer(Allocator::allocate(_bufsize)),
+		_mode(mode)
+	{
+		this->setg(_pBuffer + 4, _pBuffer + 4, _pBuffer + 4);
+		this->setp(_pBuffer, _pBuffer + _bufsize);
+	}
+
+	~BasicBufferedStreamBuf()
+	{
+		Allocator::deallocate(_pBuffer, _bufsize);
+	}
+
+	virtual int_type overflow(int_type c)
+	{
+		if (!(_mode & IOS::out)) return char_traits::eof();
+
+		if (flushBuffer() == std::streamsize(-1)) return char_traits::eof();
+		if (c != char_traits::eof()) 
+		{
+			*this->pptr() = char_traits::to_char_type(c);
+			this->pbump(1);
+		}
+
+		return c;
+	}
+
+	virtual int_type underflow()
+	{
+		if (!(_mode & IOS::in)) return char_traits::eof();
+
+		if (this->gptr() && (this->gptr() < this->egptr()))
+			return char_traits::to_int_type(*this->gptr());
+
+		int putback = int(this->gptr() - this->eback());
+		if (putback > 4) putback = 4;
+
+		char_traits::move(_pBuffer + (4 - putback), this->gptr() - putback, putback);
+
+		int n = readFromDevice(_pBuffer + 4, _bufsize - 4);
+		if (n <= 0) return char_traits::eof();
+
+		this->setg(_pBuffer + (4 - putback), _pBuffer + 4, _pBuffer + 4 + n);
+
+		// return next character
+		return char_traits::to_int_type(*this->gptr());    
+	}
+
+	virtual int sync()
+	{
+		if (this->pptr() && this->pptr() > this->pbase()) 
+		{
+			if (flushBuffer() == -1) return -1;
+		}
+		return 0;
+	}
+
+protected:
+	void setMode(openmode mode)
+	{
+		_mode = mode;
+	}
+	
+	openmode getMode() const
+	{
+		return _mode;
+	}
+
+private:
+	virtual int readFromDevice(char_type* /*buffer*/, std::streamsize /*length*/)
+	{
+		return 0;
+	}
+
+	virtual int writeToDevice(const char_type* /*buffer*/, std::streamsize /*length*/)
+	{
+		return 0;
+	}
+
+	int flushBuffer()
+	{
+		int n = int(this->pptr() - this->pbase());
+		if (writeToDevice(this->pbase(), n) == n) 
+		{
+			this->pbump(-n);
+			return n;
+		}
+		return -1;
+	}
+
+	std::streamsize _bufsize;
+	char_type*      _pBuffer;
+	openmode        _mode;
+
+	BasicBufferedStreamBuf(const BasicBufferedStreamBuf&);
+	BasicBufferedStreamBuf& operator = (const BasicBufferedStreamBuf&);
+};
+
+
+//
+// We provide an instantiation for char.
+//
+// Visual C++ needs a workaround - explicitly importing the template
+// instantiation - to avoid duplicate symbols due to multiple
+// instantiations in different libraries.
+//
+#if defined(_MSC_VER) && defined(POCO_DLL) && !defined(Foundation_EXPORTS)
+template class Foundation_API BasicBufferedStreamBuf<char, std::char_traits<char> >;
+#endif
+typedef BasicBufferedStreamBuf<char, std::char_traits<char> > BufferedStreamBuf;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_BufferedStreamBuf_INCLUDED
diff --git a/Poco/Bugcheck.h b/Poco/Bugcheck.h
new file mode 100644
index 0000000..ca475b8
--- /dev/null
+++ b/Poco/Bugcheck.h
@@ -0,0 +1,206 @@
+//
+// Bugcheck.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Bugcheck
+//
+// Definition of the Bugcheck class and the self-testing macros.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Bugcheck_INCLUDED
+#define Foundation_Bugcheck_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <string>
+#include <cstdlib>
+#if defined(_DEBUG)
+#	include <iostream>
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API Bugcheck
+	/// This class provides some static methods that are
+	/// used by the
+	/// poco_assert_dbg(), poco_assert(), poco_check_ptr(), 
+	/// poco_bugcheck() and poco_unexpected() macros. 
+	/// You should not invoke these methods
+	/// directly. Use the macros instead, as they
+	/// automatically provide useful context information.
+{
+public:
+	static void assertion(const char* cond, const char* file, int line, const char* text = 0);
+		/// An assertion failed. Break into the debugger, if
+		/// possible, then throw an AssertionViolationException.
+
+	static void nullPointer(const char* ptr, const char* file, int line);
+		/// An null pointer was encountered. Break into the debugger, if
+		/// possible, then throw an NullPointerException.
+
+	static void bugcheck(const char* file, int line);
+		/// An internal error was encountered. Break into the debugger, if
+		/// possible, then throw an BugcheckException.
+
+	static void bugcheck(const char* msg, const char* file, int line);
+		/// An internal error was encountered. Break into the debugger, if
+		/// possible, then throw an BugcheckException.
+
+	static void unexpected(const char* file, int line);
+		/// An exception was caught in a destructor. Break into debugger,
+		/// if possible and report exception. Must only be called from
+		/// within a catch () block as it rethrows the exception to
+		/// determine its class.
+
+	static void debugger(const char* file, int line);
+		/// An internal error was encountered. Break into the debugger, if
+		/// possible.
+
+	static void debugger(const char* msg, const char* file, int line);
+		/// An internal error was encountered. Break into the debugger, if
+		/// possible.
+
+protected:
+	static std::string what(const char* msg, const char* file, int line, const char* text = 0);
+};
+
+
+} // namespace Poco
+
+
+//
+// useful macros (these automatically supply line number and file name)
+//
+#if defined(__KLOCWORK__) || defined(__clang_analyzer__)
+
+
+// Short-circuit these macros when under static analysis.
+// Ideally, static analysis tools should understand and reason correctly about
+// noreturn methods such as Bugcheck::bugcheck(). In practice, they don't.
+// Help them by turning these macros into std::abort() as described here:
+// https://developer.klocwork.com/documentation/en/insight/10-1/tuning-cc-analysis#Usingthe__KLOCWORK__macro
+
+#include <cstdlib> // for abort
+#define poco_assert_dbg(cond)           do { if (!(cond)) std::abort(); } while (0)
+#define poco_assert_msg_dbg(cond, text) do { if (!(cond)) std::abort(); } while (0)
+#define poco_assert(cond)               do { if (!(cond)) std::abort(); } while (0)
+#define poco_assert_msg(cond, text)     do { if (!(cond)) std::abort(); } while (0)
+#define poco_check_ptr(ptr)             do { if (!(ptr)) std::abort(); } while (0)
+#define poco_bugcheck()                 do { std::abort(); } while (0)
+#define poco_bugcheck_msg(msg)          do { std::abort(); } while (0)
+
+
+#else // defined(__KLOCWORK__) || defined(__clang_analyzer__)
+
+
+#if defined(_DEBUG)
+	#define poco_assert_dbg(cond) \
+		if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0
+
+	#define poco_assert_msg_dbg(cond, text) \
+		if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__, text); else (void) 0
+#else
+	#define poco_assert_msg_dbg(cond, text)
+	#define poco_assert_dbg(cond)
+#endif
+
+
+#define poco_assert(cond) \
+	if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__); else (void) 0
+
+
+#define poco_assert_msg(cond, text) \
+	if (!(cond)) Poco::Bugcheck::assertion(#cond, __FILE__, __LINE__, text); else (void) 0
+
+
+#define poco_check_ptr(ptr) \
+	if (!(ptr)) Poco::Bugcheck::nullPointer(#ptr, __FILE__, __LINE__); else (void) 0
+
+
+#define poco_bugcheck() \
+	Poco::Bugcheck::bugcheck(__FILE__, __LINE__)
+
+
+#define poco_bugcheck_msg(msg) \
+	Poco::Bugcheck::bugcheck(msg, __FILE__, __LINE__)
+
+
+#endif // defined(__KLOCWORK__) || defined(__clang_analyzer__)
+
+
+#define poco_unexpected() \
+	Poco::Bugcheck::unexpected(__FILE__, __LINE__);
+
+
+#define poco_debugger() \
+	Poco::Bugcheck::debugger(__FILE__, __LINE__)
+
+
+#define poco_debugger_msg(msg) \
+	Poco::Bugcheck::debugger(msg, __FILE__, __LINE__)
+
+
+#if defined(_DEBUG)
+#	define poco_stdout_dbg(outstr) \
+	std::cout << __FILE__ << '(' << std::dec << __LINE__ << "):" << outstr << std::endl;
+#else
+#	define poco_stdout_dbg(outstr)
+#endif
+
+
+#if defined(_DEBUG)
+#	define poco_stderr_dbg(outstr) \
+		std::cerr << __FILE__ << '(' << std::dec << __LINE__ << "):" << outstr << std::endl;
+#else
+#	define poco_stderr_dbg(outstr)
+#endif
+
+
+//
+// poco_static_assert
+//
+// The following was ported from <boost/static_assert.hpp>
+//
+
+
+template <bool x>
+struct POCO_STATIC_ASSERTION_FAILURE;
+
+
+template <>
+struct POCO_STATIC_ASSERTION_FAILURE<true>
+{
+	enum
+	{
+		value = 1
+	};
+};
+
+
+template <int x> 
+struct poco_static_assert_test
+{
+};
+
+
+#if defined(__GNUC__) && (__GNUC__ == 3) && ((__GNUC_MINOR__ == 3) || (__GNUC_MINOR__ == 4))
+#define poco_static_assert(B) \
+	typedef char POCO_JOIN(poco_static_assert_typedef_, __LINE__) \
+        [POCO_STATIC_ASSERTION_FAILURE<(bool) (B)>::value]
+#else
+#define poco_static_assert(B) \
+	typedef poco_static_assert_test<sizeof(POCO_STATIC_ASSERTION_FAILURE<(bool) (B)>)> \
+		POCO_JOIN(poco_static_assert_typedef_, __LINE__) POCO_UNUSED
+#endif
+
+
+#endif // Foundation_Bugcheck_INCLUDED
diff --git a/Poco/ByteOrder.h b/Poco/ByteOrder.h
new file mode 100644
index 0000000..97732bc
--- /dev/null
+++ b/Poco/ByteOrder.h
@@ -0,0 +1,239 @@
+//
+// ByteOrder.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  ByteOrder
+//
+// Copyright (c) 2004-2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ByteOrder_INCLUDED
+#define Foundation_ByteOrder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Types.h"
+#if defined(_MSC_VER)
+#include <stdlib.h> // builtins
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API ByteOrder
+	/// This class contains a number of static methods
+	/// to convert between big-endian and little-endian
+	/// integers of various sizes.
+{
+public:
+	static Int16 flipBytes(Int16 value);
+	static UInt16 flipBytes(UInt16 value);
+	static Int32 flipBytes(Int32 value);
+	static UInt32 flipBytes(UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 flipBytes(Int64 value);
+	static UInt64 flipBytes(UInt64 value);
+#endif
+
+	static Int16 toBigEndian(Int16 value);
+	static UInt16 toBigEndian (UInt16 value);
+	static Int32 toBigEndian(Int32 value);
+	static UInt32 toBigEndian (UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 toBigEndian(Int64 value);
+	static UInt64 toBigEndian (UInt64 value);
+#endif
+
+	static Int16 fromBigEndian(Int16 value);
+	static UInt16 fromBigEndian (UInt16 value);
+	static Int32 fromBigEndian(Int32 value);
+	static UInt32 fromBigEndian (UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 fromBigEndian(Int64 value);
+	static UInt64 fromBigEndian (UInt64 value);
+#endif
+
+	static Int16 toLittleEndian(Int16 value);
+	static UInt16 toLittleEndian (UInt16 value);
+	static Int32 toLittleEndian(Int32 value);
+	static UInt32 toLittleEndian (UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 toLittleEndian(Int64 value);
+	static UInt64 toLittleEndian (UInt64 value);
+#endif
+
+	static Int16 fromLittleEndian(Int16 value);
+	static UInt16 fromLittleEndian (UInt16 value);
+	static Int32 fromLittleEndian(Int32 value);
+	static UInt32 fromLittleEndian (UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 fromLittleEndian(Int64 value);
+	static UInt64 fromLittleEndian (UInt64 value);
+#endif
+
+	static Int16 toNetwork(Int16 value);
+	static UInt16 toNetwork (UInt16 value);
+	static Int32 toNetwork(Int32 value);
+	static UInt32 toNetwork (UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 toNetwork(Int64 value);
+	static UInt64 toNetwork (UInt64 value);
+#endif
+
+	static Int16 fromNetwork(Int16 value);
+	static UInt16 fromNetwork (UInt16 value);
+	static Int32 fromNetwork(Int32 value);
+	static UInt32 fromNetwork (UInt32 value);
+#if defined(POCO_HAVE_INT64)
+	static Int64 fromNetwork(Int64 value);
+	static UInt64 fromNetwork (UInt64 value);
+#endif
+};
+
+
+#if !defined(POCO_NO_BYTESWAP_BUILTINS)
+	#if defined(_MSC_VER)
+		#if (POCO_MSVC_VERSION > 71)
+			#define POCO_HAVE_MSC_BYTESWAP 1
+		#endif
+	#elif defined(__clang__) 
+		#if __has_builtin(__builtin_bswap32)
+			#define POCO_HAVE_GCC_BYTESWAP 1
+		#endif
+	#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+		#define POCO_HAVE_GCC_BYTESWAP 1
+	#endif
+#endif
+
+
+//
+// inlines
+//
+inline UInt16 ByteOrder::flipBytes(UInt16 value)
+{
+#if defined(POCO_HAVE_MSC_BYTESWAP)
+	return _byteswap_ushort(value);
+#else
+	return ((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00);
+#endif
+}
+
+
+inline Int16 ByteOrder::flipBytes(Int16 value)
+{
+	return Int16(flipBytes(UInt16(value)));
+}
+
+
+inline UInt32 ByteOrder::flipBytes(UInt32 value)
+{
+#if defined(POCO_HAVE_MSC_BYTESWAP)
+	return _byteswap_ulong(value);
+#elif defined(POCO_HAVE_GCC_BYTESWAP)
+	return __builtin_bswap32(value);
+#else
+	return ((value >> 24) & 0x000000FF) | ((value >> 8) & 0x0000FF00)
+	     | ((value << 8) & 0x00FF0000) | ((value << 24) & 0xFF000000);
+#endif
+}
+
+
+inline Int32 ByteOrder::flipBytes(Int32 value)
+{
+	return Int32(flipBytes(UInt32(value)));
+}
+
+
+#if defined(POCO_HAVE_INT64)
+inline UInt64 ByteOrder::flipBytes(UInt64 value)
+{
+#if defined(POCO_HAVE_MSC_BYTESWAP)
+	return _byteswap_uint64(value);
+#elif defined(POCO_HAVE_GCC_BYTESWAP)
+	return __builtin_bswap64(value);
+#else
+	UInt32 hi = UInt32(value >> 32);
+	UInt32 lo = UInt32(value & 0xFFFFFFFF);
+	return UInt64(flipBytes(hi)) | (UInt64(flipBytes(lo)) << 32);
+#endif
+}
+
+
+inline Int64 ByteOrder::flipBytes(Int64 value)
+{
+	return Int64(flipBytes(UInt64(value)));
+}
+#endif // POCO_HAVE_INT64
+
+
+//
+// some macro trickery to automate the method implementation
+//
+#define POCO_IMPLEMENT_BYTEORDER_NOOP_(op, type) \
+	inline type ByteOrder::op(type value)		\
+	{											\
+		return value;							\
+	}
+#define POCO_IMPLEMENT_BYTEORDER_FLIP_(op, type) \
+	inline type ByteOrder::op(type value)		\
+	{											\
+		return flipBytes(value);				\
+	}
+
+
+#if defined(POCO_HAVE_INT64)
+	#define POCO_IMPLEMENT_BYTEORDER_NOOP(op) \
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, Int16)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, UInt16)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, Int32)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, UInt32)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, Int64)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, UInt64)
+	#define POCO_IMPLEMENT_BYTEORDER_FLIP(op) \
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, Int16)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, UInt16)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, Int32)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, UInt32)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, Int64)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, UInt64)
+#else
+	#define POCO_IMPLEMENT_BYTEORDER_NOOP(op) \
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, Int16)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, UInt16)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, Int32)	\
+		POCO_IMPLEMENT_BYTEORDER_NOOP_(op, UInt32)
+	#define POCO_IMPLEMENT_BYTEORDER_FLIP(op) \
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, Int16)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, UInt16)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, Int32)	\
+		POCO_IMPLEMENT_BYTEORDER_FLIP_(op, UInt32)
+#endif
+
+
+#if defined(POCO_ARCH_BIG_ENDIAN)
+	#define POCO_IMPLEMENT_BYTEORDER_BIG POCO_IMPLEMENT_BYTEORDER_NOOP
+	#define POCO_IMPLEMENT_BYTEORDER_LIT POCO_IMPLEMENT_BYTEORDER_FLIP
+#else
+	#define POCO_IMPLEMENT_BYTEORDER_BIG POCO_IMPLEMENT_BYTEORDER_FLIP
+	#define POCO_IMPLEMENT_BYTEORDER_LIT POCO_IMPLEMENT_BYTEORDER_NOOP
+#endif
+
+
+POCO_IMPLEMENT_BYTEORDER_BIG(toBigEndian)
+POCO_IMPLEMENT_BYTEORDER_BIG(fromBigEndian)
+POCO_IMPLEMENT_BYTEORDER_BIG(toNetwork)
+POCO_IMPLEMENT_BYTEORDER_BIG(fromNetwork)
+POCO_IMPLEMENT_BYTEORDER_LIT(toLittleEndian)
+POCO_IMPLEMENT_BYTEORDER_LIT(fromLittleEndian)
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ByteOrder_INCLUDED
diff --git a/Poco/Channel.h b/Poco/Channel.h
new file mode 100644
index 0000000..f820a2c
--- /dev/null
+++ b/Poco/Channel.h
@@ -0,0 +1,78 @@
+//
+// Channel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  Channel
+//
+// Definition of the Channel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Channel_INCLUDED
+#define Foundation_Channel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Configurable.h"
+#include "Poco/Mutex.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Message;
+
+
+class Foundation_API Channel: public Configurable, public RefCountedObject
+	/// The base class for all Channel classes.
+	///
+	/// Supports reference counting based garbage
+	/// collection and provides trivial implementations
+	/// of getProperty() and setProperty().
+{
+public:
+	Channel();
+		/// Creates the channel and initializes
+		/// the reference count to one.
+
+	virtual void open();
+		/// Does whatever is necessary to open the channel. 
+		/// The default implementation does nothing.
+		
+	virtual void close();
+		/// Does whatever is necessary to close the channel.
+		/// The default implementation does nothing.
+		
+	virtual void log(const Message& msg) = 0;
+		/// Logs the given message to the channel. Must be
+		/// overridden by subclasses.
+		///
+		/// If the channel has not been opened yet, the log()
+		/// method will open it.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Throws a PropertyNotSupportedException.
+
+	std::string getProperty(const std::string& name) const;
+		/// Throws a PropertyNotSupportedException.
+		
+protected:
+	virtual ~Channel();
+	
+private:
+	Channel(const Channel&);
+	Channel& operator = (const Channel&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Channel_INCLUDED
diff --git a/Poco/Checksum.h b/Poco/Checksum.h
new file mode 100644
index 0000000..3961bb7
--- /dev/null
+++ b/Poco/Checksum.h
@@ -0,0 +1,108 @@
+//
+// Checksum.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Checksum
+//
+// Definition of the Checksum class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Checksum_INCLUDED
+#define Foundation_Checksum_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Checksum
+	/// This class calculates CRC-32 or Adler-32 checksums
+	/// for arbitrary data.
+	///
+	/// A cyclic redundancy check (CRC) is a type of hash function, which is used to produce a 
+	/// small, fixed-size checksum of a larger block of data, such as a packet of network 
+	/// traffic or a computer file. CRC-32 is one of the most commonly used CRC algorithms.
+	///
+	/// Adler-32 is a checksum algorithm which was invented by Mark Adler. 
+	/// It is almost as reliable as a 32-bit cyclic redundancy check for protecting against 
+	/// accidental modification of data, such as distortions occurring during a transmission, 
+	/// but is significantly faster to calculate in software.
+	
+{
+public:
+	enum Type
+	{
+		TYPE_ADLER32 = 0,
+		TYPE_CRC32
+	};
+
+	Checksum();
+		/// Creates a CRC-32 checksum initialized to 0.
+
+	Checksum(Type t);
+		/// Creates the Checksum, using the given type.
+
+	~Checksum();
+		/// Destroys the Checksum.
+
+	void update(const char* data, unsigned length);
+		/// Updates the checksum with the given data.
+
+	void update(const std::string& data);
+		/// Updates the checksum with the given data.
+
+	void update(char data);
+		/// Updates the checksum with the given data.
+
+	Poco::UInt32 checksum() const;
+		/// Returns the calculated checksum.
+
+	Type type() const;
+		/// Which type of checksum are we calulcating
+
+private:
+	Type         _type;
+	Poco::UInt32 _value;
+};
+
+
+//
+// inlines
+//
+inline void Checksum::update(const std::string& data)
+{
+	update(data.c_str(), static_cast<unsigned int>(data.size()));
+}
+
+
+inline void Checksum::update(char c)
+{
+	update(&c, 1);
+}
+
+
+inline Poco::UInt32 Checksum::checksum() const
+{
+	return _value;
+}
+
+
+inline Checksum::Type Checksum::type() const
+{
+	return _type;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Checksum_INCLUDED
diff --git a/Poco/ClassLibrary.h b/Poco/ClassLibrary.h
new file mode 100644
index 0000000..14b10ac
--- /dev/null
+++ b/Poco/ClassLibrary.h
@@ -0,0 +1,101 @@
+//
+// ClassLibrary.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  ClassLoader
+//
+// Definitions for class libraries.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ClassLibrary_INCLUDED
+#define Foundation_ClassLibrary_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Manifest.h"
+#include <typeinfo>
+
+
+#if defined(_WIN32)
+	#define POCO_LIBRARY_API __declspec(dllexport)
+#else
+	#define POCO_LIBRARY_API
+#endif
+
+
+//
+// the entry points for every class library
+//
+extern "C"
+{
+	bool POCO_LIBRARY_API pocoBuildManifest(Poco::ManifestBase* pManifest);
+	void POCO_LIBRARY_API pocoInitializeLibrary();
+	void POCO_LIBRARY_API pocoUninitializeLibrary();
+} 
+
+
+//
+// additional support for named manifests
+//
+#define POCO_DECLARE_NAMED_MANIFEST(name) \
+extern "C"	\
+{			\
+	bool POCO_LIBRARY_API POCO_JOIN(pocoBuildManifest, name)(Poco::ManifestBase* pManifest); \
+}
+
+
+//
+// Macros to automatically implement pocoBuildManifest
+//
+// usage:
+//
+// POCO_BEGIN_MANIFEST(MyBaseClass)
+//     POCO_EXPORT_CLASS(MyFirstClass)
+//     POCO_EXPORT_CLASS(MySecondClass)
+//     ...
+// POCO_END_MANIFEST
+//
+#define POCO_BEGIN_MANIFEST_IMPL(fnName, base) \
+	bool fnName(Poco::ManifestBase* pManifest_)										\
+	{																				\
+		typedef base _Base;															\
+		typedef Poco::Manifest<_Base> _Manifest;									\
+		std::string requiredType(typeid(_Manifest).name());							\
+		std::string actualType(pManifest_->className());							\
+		if (requiredType == actualType)												\
+		{																			\
+			Poco::Manifest<_Base>* pManifest = static_cast<_Manifest*>(pManifest_);
+
+
+#define POCO_BEGIN_MANIFEST(base) \
+	POCO_BEGIN_MANIFEST_IMPL(pocoBuildManifest, base)
+
+
+#define POCO_BEGIN_NAMED_MANIFEST(name, base)	\
+	POCO_DECLARE_NAMED_MANIFEST(name)			\
+	POCO_BEGIN_MANIFEST_IMPL(POCO_JOIN(pocoBuildManifest, name), base)
+
+
+#define POCO_END_MANIFEST \
+			return true;	\
+		}					\
+		else return false;	\
+	}
+
+
+#define POCO_EXPORT_CLASS(cls) \
+    pManifest->insert(new Poco::MetaObject<cls, _Base>(#cls));
+
+
+#define POCO_EXPORT_SINGLETON(cls) \
+	pManifest->insert(new Poco::MetaSingleton<cls, _Base>(#cls));
+
+
+#endif // Foundation_ClassLibrary_INCLUDED
diff --git a/Poco/ClassLoader.h b/Poco/ClassLoader.h
new file mode 100644
index 0000000..450aec2
--- /dev/null
+++ b/Poco/ClassLoader.h
@@ -0,0 +1,365 @@
+//
+// ClassLoader.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  ClassLoader
+//
+// Definition of the ClassLoader class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ClassLoader_INCLUDED
+#define Foundation_ClassLoader_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/MetaObject.h"
+#include "Poco/Manifest.h"
+#include "Poco/SharedLibrary.h"
+#include "Poco/Mutex.h"
+#include "Poco/Exception.h"
+#include <map>
+
+
+namespace Poco {
+
+
+template <class Base>
+class ClassLoader
+	/// The ClassLoader loads C++ classes from shared libraries
+	/// at runtime. It must be instantiated with a root class
+	/// of the loadable classes.
+	/// For a class to be loadable from a library, the library
+	/// must provide a Manifest of all the classes it contains.
+	/// The Manifest for a shared library can be easily built
+	/// with the help of the macros in the header file
+	/// "Foundation/ClassLibrary.h".
+	///
+	/// Starting with POCO release 1.3, a class library can
+	/// export multiple manifests. In addition to the default
+	/// (unnamed) manifest, multiple named manifests can
+	/// be exported, each having a different base class.
+	///
+	/// There is one important restriction: one instance of
+	/// ClassLoader can only load one manifest from a class
+	/// library.
+{
+public:
+	typedef AbstractMetaObject<Base> Meta;
+	typedef Manifest<Base> Manif;
+	typedef void (*InitializeLibraryFunc)();
+	typedef void (*UninitializeLibraryFunc)();
+	typedef bool (*BuildManifestFunc)(ManifestBase*);
+
+	struct LibraryInfo
+	{
+		SharedLibrary* pLibrary;
+		const Manif*   pManifest;
+		int            refCount;
+	};
+	typedef std::map<std::string, LibraryInfo> LibraryMap;
+
+	class Iterator
+		/// The ClassLoader's very own iterator class.
+	{
+	public:
+		typedef std::pair<std::string, const Manif*> Pair;
+
+		Iterator(const typename LibraryMap::const_iterator& it)
+		{
+			_it = it;
+		}
+		Iterator(const Iterator& it)
+		{
+			_it = it._it;
+		}
+		~Iterator()
+		{
+		}
+		Iterator& operator = (const Iterator& it)
+		{
+			_it = it._it;
+			return *this;
+		}
+		inline bool operator == (const Iterator& it) const
+		{
+			return _it == it._it;
+		}
+		inline bool operator != (const Iterator& it) const
+		{
+			return _it != it._it;
+		}
+		Iterator& operator ++ () // prefix
+		{
+			++_it;
+			return *this;
+		}
+		Iterator operator ++ (int) // postfix
+		{
+			Iterator result(_it);
+			++_it;
+			return result;
+		}
+		inline const Pair* operator * () const
+		{
+			_pair.first  = _it->first;
+			_pair.second = _it->second.pManifest;
+			return &_pair;
+		}
+		inline const Pair* operator -> () const
+		{
+			_pair.first  = _it->first;
+			_pair.second = _it->second.pManifest;
+			return &_pair;
+		}
+
+	private:
+		typename LibraryMap::const_iterator _it;
+		mutable Pair _pair;
+	};
+
+	ClassLoader()
+		/// Creates the ClassLoader.
+	{
+	}
+
+	virtual ~ClassLoader()
+		/// Destroys the ClassLoader.
+	{
+		for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
+		{
+			delete it->second.pLibrary;
+			delete it->second.pManifest;
+		}
+	}
+
+	void loadLibrary(const std::string& path, const std::string& manifest)
+		/// Loads a library from the given path, using the given manifest. 
+		/// Does nothing if the library is already loaded.
+		/// Throws a LibraryLoadException if the library
+		/// cannot be loaded or does not have a Manifest.
+		/// If the library exports a function named "pocoInitializeLibrary",
+		/// this function is executed.
+		/// If called multiple times for the same library,
+		/// the number of calls to unloadLibrary() must be the same
+		/// for the library to become unloaded.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		typename LibraryMap::iterator it = _map.find(path);
+		if (it == _map.end())
+		{
+			LibraryInfo li;
+			li.pLibrary  = 0;
+			li.pManifest = 0;
+			li.refCount  = 1;
+			try
+			{
+				li.pLibrary  = new SharedLibrary(path);
+				li.pManifest = new Manif();
+				std::string pocoBuildManifestSymbol("pocoBuildManifest");
+				pocoBuildManifestSymbol.append(manifest);
+				if (li.pLibrary->hasSymbol("pocoInitializeLibrary"))
+				{
+					InitializeLibraryFunc initializeLibrary = (InitializeLibraryFunc) li.pLibrary->getSymbol("pocoInitializeLibrary");
+					initializeLibrary();
+				}
+				if (li.pLibrary->hasSymbol(pocoBuildManifestSymbol))
+				{
+					BuildManifestFunc buildManifest = (BuildManifestFunc) li.pLibrary->getSymbol(pocoBuildManifestSymbol);
+					if (buildManifest(const_cast<Manif*>(li.pManifest)))
+						_map[path] = li;
+					else
+						throw LibraryLoadException(std::string("Manifest class mismatch in ") + path, manifest);
+				}
+				else throw LibraryLoadException(std::string("No manifest in ") + path, manifest);
+			}
+			catch (...)
+			{
+				delete li.pLibrary;
+				delete li.pManifest;
+				throw;
+			}
+		}
+		else
+		{
+			++it->second.refCount;
+		}
+	}
+
+	void loadLibrary(const std::string& path)
+		/// Loads a library from the given path. Does nothing
+		/// if the library is already loaded.
+		/// Throws a LibraryLoadException if the library
+		/// cannot be loaded or does not have a Manifest.
+		/// If the library exports a function named "pocoInitializeLibrary",
+		/// this function is executed.
+		/// If called multiple times for the same library,
+		/// the number of calls to unloadLibrary() must be the same
+		/// for the library to become unloaded.
+		///
+		/// Equivalent to loadLibrary(path, "").
+	{
+		loadLibrary(path, "");
+	}
+		
+	void unloadLibrary(const std::string& path)
+		/// Unloads the given library. 
+		/// Be extremely cautious when unloading shared libraries.
+		/// If objects from the library are still referenced somewhere,
+		/// a total crash is very likely.
+		/// If the library exports a function named "pocoUninitializeLibrary",
+		/// this function is executed before it is unloaded.
+		/// If loadLibrary() has been called multiple times for the same
+		/// library, the number of calls to unloadLibrary() must be the same
+		/// for the library to become unloaded.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		typename LibraryMap::iterator it = _map.find(path);
+		if (it != _map.end())
+		{
+			if (--it->second.refCount == 0)
+			{
+				if (it->second.pLibrary->hasSymbol("pocoUninitializeLibrary"))
+				{
+					UninitializeLibraryFunc uninitializeLibrary = (UninitializeLibraryFunc) it->second.pLibrary->getSymbol("pocoUninitializeLibrary");
+					uninitializeLibrary();
+				}
+				delete it->second.pManifest;
+				it->second.pLibrary->unload();
+				delete it->second.pLibrary;
+				_map.erase(it);
+			}
+		}
+		else throw NotFoundException(path);
+	}
+
+	const Meta* findClass(const std::string& className) const
+		/// Returns a pointer to the MetaObject for the given
+		/// class, or a null pointer if the class is not known.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		for (typename LibraryMap::const_iterator it = _map.begin(); it != _map.end(); ++it)
+		{
+			const Manif* pManif = it->second.pManifest;
+			typename Manif::Iterator itm = pManif->find(className);
+			if (itm != pManif->end())
+				return *itm;
+		}
+		return 0;
+	}
+	
+	const Meta& classFor(const std::string& className) const
+		/// Returns a reference to the MetaObject for the given
+		/// class. Throws a NotFoundException if the class
+		/// is not known.
+	{
+		const Meta* pMeta = findClass(className);
+		if (pMeta)
+			return *pMeta;
+		else
+			throw NotFoundException(className);
+	}
+	
+	Base* create(const std::string& className) const
+		/// Creates an instance of the given class.
+		/// Throws a NotFoundException if the class
+		/// is not known.
+	{
+		return classFor(className).create();
+	}
+	
+	Base& instance(const std::string& className) const
+		/// Returns a reference to the sole instance of
+		/// the given class. The class must be a singleton,
+		/// otherwise an InvalidAccessException will be thrown.
+		/// Throws a NotFoundException if the class
+		/// is not known.
+	{
+		return classFor(className).instance();
+	}
+	
+	bool canCreate(const std::string& className) const
+		/// Returns true if create() can create new instances
+		/// of the class.
+	{
+		return classFor(className).canCreate();
+	}
+
+	void destroy(const std::string& className, Base* pObject) const
+		/// Destroys the object pObject points to.
+		/// Does nothing if object is not found.
+	{
+		classFor(className).destroy(pObject);
+	}
+
+	bool isAutoDelete(const std::string& className, Base* pObject) const
+		/// Returns true if the object is automatically
+		/// deleted by its meta object.
+	{
+		return classFor(className).isAutoDelete(pObject);
+	}
+	
+	const Manif* findManifest(const std::string& path) const
+		/// Returns a pointer to the Manifest for the given
+		/// library, or a null pointer if the library has not been loaded.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		typename LibraryMap::const_iterator it = _map.find(path);
+		if (it != _map.end())
+			return it->second.pManifest;
+		else
+			return 0;
+	}
+	
+	const Manif& manifestFor(const std::string& path) const
+		/// Returns a reference to the Manifest for the given library
+		/// Throws a NotFoundException if the library has not been loaded.
+	{
+		const Manif* pManif = findManifest(path);
+		if (pManif)
+			return *pManif;
+		else
+			throw NotFoundException(path);
+	}
+
+	bool isLibraryLoaded(const std::string& path) const
+		/// Returns true if the library with the given name
+		/// has already been loaded.
+	{
+		return findManifest(path) != 0;
+	}
+
+	Iterator begin() const
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		return Iterator(_map.begin());
+	}
+
+	Iterator end() const
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		return Iterator(_map.end());
+	}
+
+private:
+	LibraryMap _map;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ClassLoader_INCLUDED
diff --git a/Poco/Clock.h b/Poco/Clock.h
new file mode 100644
index 0000000..43bb22f
--- /dev/null
+++ b/Poco/Clock.h
@@ -0,0 +1,238 @@
+//
+// Clock.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  Clock
+//
+// Definition of the Clock class.
+//
+// Copyright (c) 2013, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Clock_INCLUDED
+#define Foundation_Clock_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Clock
+	/// A Clock stores a monotonic* clock value
+	/// with (theoretical) microseconds resolution.
+	/// Clocks can be compared with each other
+	/// and simple arithmetics are supported.
+	///
+	/// [*] Note that Clock values are only monotonic if
+	/// the operating system provides a monotonic clock.
+	/// The monotonic() function can be used to check whether
+	/// the system's clock is monotonic.
+	///
+	/// Monotonic Clock is available on Windows, Linux, OS X 
+	/// and on POSIX platforms supporting clock_gettime() with CLOCK_MONOTONIC.	  
+	///
+	/// Clock values are relative to a system-dependent epoch time
+	/// (usually the system's startup time) and have no relation
+	/// to the time of day.
+{
+public:
+	typedef Int64 ClockVal;
+		/// Monotonic clock value in microsecond resolution.
+
+	typedef Int64 ClockDiff;
+		/// Difference between two ClockVal values in microseconds.
+
+	static const ClockVal CLOCKVAL_MIN; /// Minimum clock value.
+	static const ClockVal CLOCKVAL_MAX; /// Maximum clock value.
+
+	Clock();
+		/// Creates a Clock with the current system clock value.
+		
+	Clock(ClockVal tv);
+		/// Creates a Clock from the given clock value.
+		
+	Clock(const Clock& other);
+		/// Copy constructor.
+		
+	~Clock();
+		/// Destroys the Clock.
+		
+	Clock& operator = (const Clock& other);
+	Clock& operator = (ClockVal tv);
+	
+	void swap(Clock& clock);
+		/// Swaps the Clock with another one.
+	
+	void update();
+		/// Updates the Clock with the current system clock.
+
+	bool operator == (const Clock& ts) const;
+	bool operator != (const Clock& ts) const;
+	bool operator >  (const Clock& ts) const;
+	bool operator >= (const Clock& ts) const;
+	bool operator <  (const Clock& ts) const;
+	bool operator <= (const Clock& ts) const;
+	
+	Clock  operator +  (ClockDiff d) const;
+	Clock  operator -  (ClockDiff d) const;
+	ClockDiff operator - (const Clock& ts) const;
+	Clock& operator += (ClockDiff d);
+	Clock& operator -= (ClockDiff d);
+	
+	ClockVal microseconds() const;
+		/// Returns the clock value expressed in microseconds
+		/// since the system-specific epoch time (usually system
+		/// startup).
+
+	ClockVal raw() const;
+		/// Returns the clock value expressed in microseconds
+		/// since the system-specific epoch time (usually system
+		/// startup).
+		///
+		/// Same as microseconds().
+	
+	ClockDiff elapsed() const;
+		/// Returns the time elapsed since the time denoted by
+		/// the Clock instance. Equivalent to Clock() - *this.
+	
+	bool isElapsed(ClockDiff interval) const;
+		/// Returns true iff the given interval has passed
+		/// since the time denoted by the Clock instance.
+	
+	static ClockDiff resolution();
+		/// Returns the resolution in units per second.
+		/// Since the Clock clas has microsecond resolution,
+		/// the returned value is always 1000000.
+		
+	static ClockDiff accuracy();
+		/// Returns the system's clock accuracy in microseconds.
+		
+	static bool monotonic();
+		/// Returns true iff the system's clock is monotonic.
+
+private:
+	ClockVal _clock;
+};
+
+
+//
+// inlines
+//
+inline bool Clock::operator == (const Clock& ts) const
+{
+	return _clock == ts._clock;
+}
+
+
+inline bool Clock::operator != (const Clock& ts) const
+{
+	return _clock != ts._clock;
+}
+
+
+inline bool Clock::operator >  (const Clock& ts) const
+{
+	return _clock > ts._clock;
+}
+
+
+inline bool Clock::operator >= (const Clock& ts) const
+{
+	return _clock >= ts._clock;
+}
+
+
+inline bool Clock::operator <  (const Clock& ts) const
+{
+	return _clock < ts._clock;
+}
+
+
+inline bool Clock::operator <= (const Clock& ts) const
+{
+	return _clock <= ts._clock;
+}
+
+
+inline Clock Clock::operator + (Clock::ClockDiff d) const
+{
+	return Clock(_clock + d);
+}
+
+
+inline Clock Clock::operator - (Clock::ClockDiff d) const
+{
+	return Clock(_clock - d);
+}
+
+
+inline Clock::ClockDiff Clock::operator - (const Clock& ts) const
+{
+	return _clock - ts._clock;
+}
+
+
+inline Clock& Clock::operator += (Clock::ClockDiff d)
+{
+	_clock += d;
+	return *this;
+}
+
+
+inline Clock& Clock::operator -= (Clock::ClockDiff d)
+{
+	_clock -= d;
+	return *this;
+}
+
+
+inline Clock::ClockVal Clock::microseconds() const
+{
+	return _clock;
+}
+
+
+inline Clock::ClockDiff Clock::elapsed() const
+{
+	Clock now;
+	return now - *this;
+}
+
+
+inline bool Clock::isElapsed(Clock::ClockDiff interval) const
+{
+	Clock now;
+	Clock::ClockDiff diff = now - *this;
+	return diff >= interval;
+}
+
+
+inline Clock::ClockDiff Clock::resolution()
+{
+	return 1000000;
+}
+
+
+inline void swap(Clock& s1, Clock& s2)
+{
+	s1.swap(s2);
+}
+
+
+inline Clock::ClockVal Clock::raw() const
+{
+	return _clock;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Clock_INCLUDED
diff --git a/Poco/Condition.h b/Poco/Condition.h
new file mode 100644
index 0000000..3340533
--- /dev/null
+++ b/Poco/Condition.h
@@ -0,0 +1,137 @@
+//
+// Condition.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Condition
+//
+// Definition of the Condition class template.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Condition_INCLUDED
+#define Foundation_Condition_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include "Poco/ScopedUnlock.h"
+#include "Poco/Event.h"
+#include "Poco/Exception.h"
+#include <deque>
+
+
+namespace Poco {
+
+
+class Foundation_API Condition
+	/// A Condition is a synchronization object used to block a thread 
+	/// until a particular condition is met. 
+	/// A Condition object is always used in conjunction with
+	/// a Mutex (or FastMutex) object.
+	///
+	/// Condition objects are similar to POSIX condition variables, which the
+	/// difference that Condition is not subject to spurious wakeups.
+	///
+	/// Threads waiting on a Condition are resumed in FIFO order.
+{
+public:
+	Condition();
+		/// Creates the Condition.
+	
+	~Condition();
+		/// Destroys the Condition.
+	
+	template <class Mtx>
+	void wait(Mtx& mutex)
+		/// Unlocks the mutex (which must be locked upon calling
+		/// wait()) and waits until the Condition is signalled.
+		///
+		/// The given mutex will be locked again upon 
+		/// leaving the function, even in case of an exception.
+	{
+		ScopedUnlock<Mtx> unlock(mutex, false);
+		Event event;
+		{
+			FastMutex::ScopedLock lock(_mutex);
+			mutex.unlock();
+			enqueue(event);
+		}
+		event.wait();
+	}
+	
+	template <class Mtx>
+	void wait(Mtx& mutex, long milliseconds)
+		/// Unlocks the mutex (which must be locked upon calling
+		/// wait()) and waits for the given time until the Condition is signalled.
+		///
+		/// The given mutex will be locked again upon successfully leaving the 
+		/// function, even in case of an exception.
+		///
+		/// Throws a TimeoutException if the Condition is not signalled
+		/// within the given time interval.
+	{
+		if (!tryWait(mutex, milliseconds))
+			throw TimeoutException();
+	}
+	
+	template <class Mtx>
+	bool tryWait(Mtx& mutex, long milliseconds)
+		/// Unlocks the mutex (which must be locked upon calling
+		/// tryWait()) and waits for the given time until the Condition is signalled.
+		///
+		/// The given mutex will be locked again upon leaving the 
+		/// function, even in case of an exception.
+		///
+		/// Returns true if the Condition has been signalled
+		/// within the given time interval, otherwise false.
+	{
+		ScopedUnlock<Mtx> unlock(mutex, false);
+		Event event;
+		{
+			FastMutex::ScopedLock lock(_mutex);
+			mutex.unlock();
+			enqueue(event);
+		}
+		if (!event.tryWait(milliseconds))
+		{
+			FastMutex::ScopedLock lock(_mutex);
+			dequeue(event);
+			return false;
+		}
+		return true;
+	}
+	
+	void signal();
+		/// Signals the Condition and allows one waiting thread
+		/// to continue execution.
+
+	void broadcast();
+		/// Signals the Condition and allows all waiting
+		/// threads to continue their execution.
+
+protected:
+	void enqueue(Event& event);
+	void dequeue();
+	void dequeue(Event& event);
+	
+private:
+	Condition(const Condition&);
+	Condition& operator = (const Condition&);
+	
+	typedef std::deque<Event*> WaitQueue;
+	
+	FastMutex _mutex;
+	WaitQueue _waitQueue;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Condition_INCLUDED
diff --git a/Poco/Config.h b/Poco/Config.h
new file mode 100644
index 0000000..7dbe018
--- /dev/null
+++ b/Poco/Config.h
@@ -0,0 +1,207 @@
+//
+// Config.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Foundation
+//
+// Feature configuration for the POCO libraries.
+//
+// Copyright (c) 2006-2016, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Config_INCLUDED
+#define Foundation_Config_INCLUDED
+
+
+// Define to enable Windows Unicode (UTF-8) support
+// NOTE: As of POCO C++ Libraries release 1.6.0, compiling POCO
+// without POCO_WIN32_UTF8 defined on Windows is deprecated.
+#define POCO_WIN32_UTF8
+
+
+// Define to enable C++11 support
+// #define POCO_ENABLE_CPP11
+
+
+// Define to disable implicit linking
+// #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
+
+
+// Define if std::wstring is not available
+// #define POCO_NO_WSTRING
+
+
+// Define to disable shared memory
+// #define POCO_NO_SHAREDMEMORY
+
+
+// Define if no <locale> header is available (such as on WinCE)
+// #define POCO_NO_LOCALE
+
+
+// Define to desired default thread stack size
+// Zero means OS default
+#ifndef POCO_THREAD_STACK_SIZE
+	#define POCO_THREAD_STACK_SIZE 0
+#endif
+
+
+// Define to override system-provided
+// minimum thread priority value on POSIX
+// platforms (returned by Poco::Thread::getMinOSPriority()).
+// #define POCO_THREAD_PRIORITY_MIN 0
+
+
+// Define to override system-provided
+// maximum thread priority value on POSIX
+// platforms (returned by Poco::Thread::getMaxOSPriority()).
+// #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 POCO_SMALL_OBJECT_SIZE
+// (see below).
+//
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// !!! NOTE: Any/Dynamic::Var SOO will NOT work reliably   !!!
+// !!! without C++11 (std::aligned_storage in particular). !!!
+// !!! Only comment this out if your compiler has support  !!!
+// !!! for std::aligned_storage.                           !!!
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//
+#ifndef POCO_ENABLE_SOO
+#define POCO_NO_SOO
+#endif
+
+
+// Small object size in bytes. When assigned to Any or Var,
+// objects larger than this value will be alocated on the heap,
+// while those smaller will be placement new-ed into an
+// internal buffer.
+#if !defined(POCO_SMALL_OBJECT_SIZE) && !defined(POCO_NO_SOO)
+	#define POCO_SMALL_OBJECT_SIZE 32
+#endif
+
+
+// Define to disable compilation of DirectoryWatcher
+// on platforms with no inotify.
+// #define POCO_NO_INOTIFY
+
+
+// Following are options to remove certain features
+// to reduce library/executable size for smaller
+// embedded platforms. By enabling these options,
+// the size of a statically executable can be
+// reduced by a few 100 Kbytes.
+
+
+// No automatic registration of FileChannel in
+// LoggingFactory - avoids FileChannel and friends
+// being linked to executable.
+// #define POCO_NO_FILECHANNEL
+
+
+// No automatic registration of SplitterChannel in
+// LoggingFactory - avoids SplitterChannel being
+// linked to executable.
+// #define POCO_NO_SPLITTERCHANNEL
+
+
+// No automatic registration of SyslogChannel in
+// LoggingFactory - avoids SyslogChannel being
+// linked to executable on Unix/Linux systems.
+// #define POCO_NO_SYSLOGCHANNEL
+
+
+// Define to enable MSVC secure warnings
+// #define POCO_MSVC_SECURE_WARNINGS
+
+
+// No support for INI file configurations in
+// Poco::Util::Application.
+// #define POCO_UTIL_NO_INIFILECONFIGURATION
+
+
+// No support for JSON configuration in
+// Poco::Util::Application. Avoids linking of JSON
+// library and saves a few 100 Kbytes.
+// #define POCO_UTIL_NO_JSONCONFIGURATION
+
+
+// No support for XML configuration in
+// Poco::Util::Application. Avoids linking of XML
+// library and saves a few 100 Kbytes.
+// #define POCO_UTIL_NO_XMLCONFIGURATION
+
+
+// No IPv6 support
+// Define to disable IPv6
+// #define POCO_NET_NO_IPv6
+
+
+// Windows CE has no locale support
+#if defined(_WIN32_WCE)
+	#define POCO_NO_LOCALE
+#endif
+
+
+// Enable the poco_debug_* and poco_trace_* macros
+// even if the _DEBUG variable is not set.
+// This allows the use of these macros in a release version.
+// #define POCO_LOG_DEBUG
+
+
+// OpenSSL on Windows
+//
+// Poco has its own OpenSSL build system.
+// See <https://github.com/pocoproject/openssl/blob/master/README.md>
+// for details.
+//
+// These options are Windows only.
+//
+// To disable the use of Poco-provided OpenSSL binaries,
+// define POCO_EXTERNAL_OPENSSL.
+//
+// Possible values:
+//   POCO_EXTERNAL_OPENSSL_SLPRO:
+//     Automatically link OpenSSL libraries from OpenSSL Windows installer provided
+//     by Shining Light Productions <http://slproweb.com/products/Win32OpenSSL.html>
+//     The (global) library search path must be set accordingly.
+//   POCO_EXTERNAL_OPENSSL_DEFAULT:
+//     Automatically link OpenSSL libraries from standard OpenSSL Windows build.
+//     The (global) library search path must be set accordingly.
+//   empty or other value:
+//     Do not link any OpenSSL libraries automatically. You will have to edit the
+//     Visual C++ project files for Crypto and NetSSL_OpenSSL.
+// #define POCO_EXTERNAL_OPENSSL POCO_EXTERNAL_OPENSSL_SLPRO
+
+
+// Define to prevent changing the suffix for shared libraries
+// to "d.so", "d.dll", etc. for _DEBUG builds in Poco::SharedLibrary.
+// #define POCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX
+
+
+// Disarm POCO_DEPRECATED macro.
+// #define POCO_NO_DEPRECATED
+
+
+#endif // Foundation_Config_INCLUDED
diff --git a/Poco/Configurable.h b/Poco/Configurable.h
new file mode 100644
index 0000000..cb260d3
--- /dev/null
+++ b/Poco/Configurable.h
@@ -0,0 +1,70 @@
+//
+// Configurable.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  Configurable
+//
+// Definition of the Configurable class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Configurable_INCLUDED
+#define Foundation_Configurable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Configurable
+	/// A simple interface that defines
+	/// getProperty() and setProperty() methods.
+	///
+	/// This interface is implemented by Formatter and
+	/// Channel and is used to configure arbitrary
+	/// channels and formatters.
+	///
+	/// A property is basically a name-value pair. For
+	/// simplicity, both names and values are strings.
+	/// Every property controls a certain aspect of a
+	/// Formatter or Channel. For example, the PatternFormatter's
+	/// formatting pattern is set via a property.
+	///
+	/// NOTE: The following property names are use internally
+	/// by the logging framework and must not be used by
+	/// channels or formatters:
+	///   - class
+	///   - pattern (Channel)
+	///   - formatter (Channel)
+{
+public:
+	Configurable();
+		/// Creates the Configurable.
+		
+	virtual ~Configurable();
+		/// Destroys the Configurable.
+		
+	virtual void setProperty(const std::string& name, const std::string& value) = 0;
+		/// Sets the property with the given name to the given value.
+		/// If a property with the given name is not supported, a
+		/// PropertyNotSupportedException is thrown.
+		
+	virtual std::string getProperty(const std::string& name) const = 0;
+		/// Returns the value of the property with the given name.
+		/// If a property with the given name is not supported, a
+		/// PropertyNotSupportedException is thrown.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Configurable_INCLUDED
diff --git a/Poco/ConsoleChannel.h b/Poco/ConsoleChannel.h
new file mode 100644
index 0000000..28aab6e
--- /dev/null
+++ b/Poco/ConsoleChannel.h
@@ -0,0 +1,187 @@
+//
+// ConsoleChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  ConsoleChannel
+//
+// Definition of the ConsoleChannel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ConsoleChannel_INCLUDED
+#define Foundation_ConsoleChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Mutex.h"
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API ConsoleChannel: public Channel
+	/// A channel that writes to an ostream.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is contained 
+	/// in the text.
+	///
+	/// Similar to StreamChannel, except that a static
+	/// mutex is used to protect against multiple
+	/// console channels concurrently writing to the
+	/// same stream.
+{
+public:
+	ConsoleChannel();
+		/// Creates the channel and attaches std::clog.
+		
+	ConsoleChannel(std::ostream& str);
+		/// Creates the channel using the given stream.
+
+	void log(const Message& msg);
+		/// Logs the given message to the channel's stream.
+		
+protected:
+	~ConsoleChannel();
+
+private:
+	std::ostream& _str;
+	static FastMutex _mutex;
+};
+
+
+class Foundation_API ColorConsoleChannel: public Channel
+	/// A channel that writes to an ostream.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// Messages can be colored depending on priority.
+	/// The console device must support ANSI escape codes
+	/// in order to display colored messages.
+	///
+	/// To enable message coloring, set the "enableColors"
+	/// property to true (default). Furthermore, colors can be
+	/// configured by setting the following properties
+	/// (default values are given in parenthesis):
+	/// 
+	///   * traceColor (gray)
+	///   * debugColor (gray)
+	///   * informationColor (default)
+	///   * noticeColor (default)
+	///   * warningColor (yellow)
+	///   * errorColor (lightRed)
+	///   * criticalColor (lightRed)
+	///   * fatalColor (lightRed)
+	///
+	/// The following color values are supported:
+	/// 
+	///   * default
+	///   * black
+	///   * red
+	///   * green
+	///   * brown
+	///   * blue
+	///   * magenta
+	///   * cyan
+	///   * gray
+	///   * darkgray
+	///   * lightRed
+	///   * lightGreen
+	///   * yellow
+	///   * lightBlue
+	///   * lightMagenta
+	///   * lightCyan
+	///   * white
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is contained 
+	/// in the text.
+	///
+	/// Similar to StreamChannel, except that a static
+	/// mutex is used to protect against multiple
+	/// console channels concurrently writing to the
+	/// same stream.
+{
+public:	
+	ColorConsoleChannel();
+		/// Creates the channel and attaches std::clog.
+		
+	ColorConsoleChannel(std::ostream& str);
+		/// Creates the channel using the given stream.
+
+	void log(const Message& msg);
+		/// Logs the given message to the channel's stream.
+	
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given name. 
+		/// 
+		/// The following properties are supported:
+		///   * enableColors:      Enable or disable colors.
+		///   * traceColor:        Specify color for trace messages.
+		///   * debugColor:        Specify color for debug messages.
+		///   * informationColor:  Specify color for information messages.
+		///   * noticeColor:       Specify color for notice messages.
+		///   * warningColor:      Specify color for warning messages.
+		///   * errorColor:        Specify color for error messages.
+		///   * criticalColor:     Specify color for critical messages.
+		///   * fatalColor:        Specify color for fatal messages.
+		///
+		/// See the class documentation for a list of supported color values.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+		/// See setProperty() for a description of the supported
+		/// properties.
+
+protected:	
+	enum Color
+	{
+		CC_DEFAULT      = 0x0027,
+		CC_BLACK        = 0x001e,
+		CC_RED          = 0x001f,
+		CC_GREEN        = 0x0020,
+		CC_BROWN        = 0x0021,
+		CC_BLUE         = 0x0022,
+		CC_MAGENTA      = 0x0023,
+		CC_CYAN         = 0x0024,
+		CC_GRAY         = 0x0025,
+		CC_DARKGRAY     = 0x011e,
+		CC_LIGHTRED     = 0x011f,
+		CC_LIGHTGREEN   = 0x0120,
+		CC_YELLOW       = 0x0121,
+		CC_LIGHTBLUE    = 0x0122,
+		CC_LIGHTMAGENTA = 0x0123,
+		CC_LIGHTCYAN    = 0x0124,
+		CC_WHITE        = 0x0125
+	};
+
+	~ColorConsoleChannel();
+	Color parseColor(const std::string& color) const;
+	std::string formatColor(Color color) const;
+	void initColors();
+
+private:
+	std::ostream& _str;
+	bool _enableColors;
+	Color _colors[9];
+	static FastMutex _mutex;
+	static const std::string CSI;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ConsoleChannel_INCLUDED
diff --git a/Poco/CountingStream.h b/Poco/CountingStream.h
new file mode 100644
index 0000000..17da1e4
--- /dev/null
+++ b/Poco/CountingStream.h
@@ -0,0 +1,237 @@
+//
+// CountingStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  CountingStream
+//
+// Definition of the CountingStreamBuf, CountingInputStream and CountingOutputStream classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_CountingStream_INCLUDED
+#define Foundation_CountingStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API CountingStreamBuf: public UnbufferedStreamBuf
+	/// This stream buffer counts all characters and lines
+	/// going through it.
+{
+public:
+	CountingStreamBuf();
+		/// Creates an unconnected CountingStreamBuf.
+	
+	CountingStreamBuf(std::istream& istr);
+		/// Creates the CountingStreamBuf and connects it
+		/// to the given input stream.
+
+	CountingStreamBuf(std::ostream& ostr);
+		/// Creates the CountingStreamBuf and connects it
+		/// to the given output stream.
+
+	~CountingStreamBuf();
+		/// Destroys the CountingStream.
+		
+	int chars() const;
+		/// Returns the total number of characters.
+		
+	int lines() const;
+		/// Returns the total number of lines.
+		
+	int pos() const;
+		/// Returns the number of characters on the current line.
+		
+	void reset();
+		/// Resets all counters.
+		
+	void setCurrentLineNumber(int line);
+		/// Sets the current line number.
+		///
+		/// This is mainly useful when parsing C/C++
+		/// preprocessed source code containing #line directives.
+		
+	int getCurrentLineNumber() const;
+		/// Returns the current line number (same as lines()).
+
+	void addChars(int chars);
+		/// Add to the total number of characters.
+		
+	void addLines(int lines);
+		/// Add to the total number of lines.
+		
+	void addPos(int pos);
+		/// Add to the number of characters on the current line.
+
+protected:
+	int readFromDevice();
+	int writeToDevice(char c);
+
+private:
+	std::istream* _pIstr;
+	std::ostream* _pOstr;
+	int _chars;
+	int _lines;
+	int _pos;
+};
+
+
+class Foundation_API CountingIOS: public virtual std::ios
+	/// The base class for CountingInputStream and CountingOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	CountingIOS();
+		/// Creates the basic stream and leaves it unconnected.
+
+	CountingIOS(std::istream& istr);
+		/// Creates the basic stream and connects it
+		/// to the given input stream.
+
+	CountingIOS(std::ostream& ostr);
+		/// Creates the basic stream and connects it
+		/// to the given output stream.
+
+	~CountingIOS();
+		/// Destroys the stream.
+
+	int chars() const;
+		/// Returns the total number of characters.
+
+	int lines() const;
+		/// Returns the total number of lines.
+
+	int pos() const;
+		/// Returns the number of characters on the current line.
+
+	void reset();
+		/// Resets all counters.
+
+	void setCurrentLineNumber(int line);
+		/// Sets the current line number.
+		///
+		/// This is mainly useful when parsing C/C++
+		/// preprocessed source code containing #line directives.
+		
+	int getCurrentLineNumber() const;
+		/// Returns the current line number (same as lines()).
+
+	void addChars(int chars);
+		/// Add to the total number of characters.
+		
+	void addLines(int lines);
+		/// Add to the total number of lines.
+		
+	void addPos(int pos);
+		/// Add to the number of characters on the current line.
+
+	CountingStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	CountingStreamBuf _buf;
+};
+
+
+class Foundation_API CountingInputStream: public CountingIOS, public std::istream
+	/// This stream counts all characters and lines
+	/// going through it. This is useful for lexers and parsers
+	/// that need to determine the current position in the stream.
+{
+public:
+	CountingInputStream(std::istream& istr);
+		/// Creates the CountingInputStream and connects it
+		/// to the given input stream.
+
+	~CountingInputStream();
+		/// Destroys the stream.
+};
+
+
+class Foundation_API CountingOutputStream: public CountingIOS, public std::ostream
+	/// This stream counts all characters and lines
+	/// going through it.
+{
+public:
+	CountingOutputStream();
+		/// Creates an unconnected CountingOutputStream.
+	
+	CountingOutputStream(std::ostream& ostr);
+		/// Creates the CountingOutputStream and connects it
+		/// to the given output stream.
+
+	~CountingOutputStream();
+		/// Destroys the CountingOutputStream.
+};
+
+
+//
+// inlines
+//
+inline int CountingStreamBuf::chars() const
+{
+	return _chars;
+}
+
+
+inline int CountingStreamBuf::lines() const
+{
+	return _lines;
+}
+
+
+inline int CountingStreamBuf::pos() const
+{
+	return _pos;
+}
+
+
+inline int CountingStreamBuf::getCurrentLineNumber() const
+{
+	return _lines;
+}
+
+
+inline int CountingIOS::chars() const
+{
+	return _buf.chars();
+}
+
+
+inline int CountingIOS::lines() const
+{
+	return _buf.lines();
+}
+
+
+inline int CountingIOS::pos() const
+{
+	return _buf.pos();
+}
+
+
+inline int CountingIOS::getCurrentLineNumber() const
+{
+	return _buf.getCurrentLineNumber();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_CountingStream_INCLUDED
diff --git a/Poco/CppParser/Attributes.h b/Poco/CppParser/Attributes.h
new file mode 100644
index 0000000..2f90db2
--- /dev/null
+++ b/Poco/CppParser/Attributes.h
@@ -0,0 +1,123 @@
+//
+// Attributes.h
+//
+// Library: CppParser
+// Package: Attributes
+// Module:  Attributes
+//
+// Definition of the Attributes class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Attributes_INCLUDED
+#define CppParser_Attributes_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include <map>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API Attributes
+	/// This class stores attributes for a symbol table entry.
+	/// Attributes are simple name-value pairs, where both
+	/// name and values are strings.
+{
+public:
+	typedef std::map<std::string, std::string> AttrMap;
+	typedef AttrMap::const_iterator Iterator;
+	
+	Attributes();
+		/// Creates the Attributes object.
+
+	Attributes(const Attributes& attrs);
+		/// Creates the Attributes object by copying another one.
+
+	~Attributes();
+		/// Destroys the Attributes object.
+
+	Attributes& operator = (const Attributes& attrs);
+		/// Assignment operator.
+		
+	bool has(const std::string& name) const;
+		/// Returns true if an attribute with the given name exists.
+	
+	std::string getString(const std::string& name) const;
+		/// Returns the attribute's value as a string.
+		///
+		/// Throws a Poco::NotFoundException if the attribute does not exist.
+		
+	std::string getString(const std::string& name, const std::string& defaultValue) const;
+		/// Returns the attribute's value as a string, if it exists.
+		/// Returns the defaultValue if the attribute does not exist.
+
+	int getInt(const std::string& name) const;
+		/// Returns the attribute's value as an integer.
+		///
+		/// Throws a Poco::NotFoundException if the attribute does not exist.
+		/// Throws a Poco::SyntaxException if the stored value is not an integer.
+		
+	int getInt(const std::string& name, int defaultValue) const;
+		/// Returns the attribute's value as an integer, if it exists.
+		/// Returns the defaultValue if the attribute does not exist.
+		///
+		/// Throws a Poco::SyntaxException if the stored value is not an integer.
+
+	bool getBool(const std::string& name) const;
+		/// Returns the attribute's value as a boolean.
+		/// The returned value is 'true', iff the stored value is not "false".
+		/// 
+		/// Throws a Poco::NotFoundException if the attribute does not exist.
+
+	bool getBool(const std::string& name, bool defaultValue) const;
+		/// Returns the attribute's value as a boolean, if it exists.
+		/// The returned value is 'true', iff the stored value is not "false".
+
+	void set(const std::string& name, const std::string& value);
+		/// Sets the value of an attribute.
+	
+	void remove(const std::string& name);
+		/// Removes the attribute with the given name.
+		/// Does nothing if the attribute does not exist.
+		
+	const std::string& operator [] (const std::string& name) const;
+	std::string& operator [] (const std::string& name);		
+		
+	Iterator begin() const;
+	Iterator end() const;
+	
+	void clear();
+		/// Clears all attributes.
+
+private:
+	AttrMap _map;
+};
+
+
+//
+// inlines
+//
+inline Attributes::Iterator Attributes::begin() const
+{
+	return _map.begin();
+}
+
+
+inline Attributes::Iterator Attributes::end() const
+{
+	return _map.end();
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Attributes_INCLUDED
diff --git a/Poco/CppParser/AttributesParser.h b/Poco/CppParser/AttributesParser.h
new file mode 100644
index 0000000..8dcd625
--- /dev/null
+++ b/Poco/CppParser/AttributesParser.h
@@ -0,0 +1,114 @@
+//
+// AttributesParser.h
+//
+// Library: CppParser
+// Package: Attributes
+// Module:  AttributesParser
+//
+// Definition of the AttributesParser class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_AttributesParser_INCLUDED
+#define CppParser_AttributesParser_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Tokenizer.h"
+#include "Poco/CppParser/Attributes.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API AttributesParser
+	/// A parser for POCO-style C++ attributes.
+	///
+	/// Using a special comment syntax, C++ declarations for
+	/// structs/classes, functions, types, etc. can be annotated
+	/// with attributes.
+	///
+	/// Attributes always come immediately before the symbol that 
+	/// is being annotated, and are written inside special comments
+	/// with the syntax:
+	///     //@ <attrDecl>[,<attrDec>...]
+	/// where <attrDecl> is
+	///     <name>[=<value>]
+	/// <name> is a valid C++ identifier, or two identifiers separated by 
+	/// a period (struct accessor notation).
+	/// <value> is a string, integer, identifier, bool literal, or a complex value
+	/// in the form
+	///    {<name>=<value>[,<name>=<value>...]}
+{
+public:
+	AttributesParser(Attributes& attrs, std::istream& istr);
+		/// Creates the AttributesParser.
+
+	~AttributesParser();
+		/// Destroys the AttributesParser.
+
+	void parse();
+		/// Parses attributes.
+
+protected:
+	void setAttribute(const std::string& name, const std::string& value);
+	const Poco::Token* parseAttributes(const Poco::Token* pNext);
+	const Poco::Token* parseAttribute(const Poco::Token* pNext);
+	const Poco::Token* parseComplexAttribute(const Token* pNext, const std::string& id);
+	const Poco::Token* parseIdentifier(const Poco::Token* pNext, std::string& id);
+	const Poco::Token* next();
+	static bool isIdentifier(const Poco::Token* pToken);
+	static bool isOperator(const Poco::Token* pToken, int kind);
+	static bool isLiteral(const Poco::Token* pToken);
+	static bool isEOF(const Poco::Token* pToken);
+	
+private:
+	Attributes& _attrs;
+	Tokenizer   _tokenizer;
+	std::string _id;
+};
+
+
+//
+// inlines
+//
+inline const Poco::Token* AttributesParser::next()
+{
+	return _tokenizer.next();
+}
+
+
+inline bool AttributesParser::isEOF(const Poco::Token* pToken)
+{
+	return pToken->is(Token::EOF_TOKEN);
+}
+
+
+inline bool AttributesParser::isIdentifier(const Poco::Token* pToken)
+{
+	return pToken->is(Poco::Token::IDENTIFIER_TOKEN) || pToken->is(Poco::Token::KEYWORD_TOKEN);
+}
+
+
+inline bool AttributesParser::isOperator(const Poco::Token* pToken, int kind)
+{
+	return pToken->is(Poco::Token::OPERATOR_TOKEN) && pToken->asInteger() == kind;
+}
+
+
+inline bool AttributesParser::isLiteral(const Poco::Token* pToken)
+{
+	return pToken->is(Poco::Token::STRING_LITERAL_TOKEN) || pToken->is(Poco::Token::INTEGER_LITERAL_TOKEN);
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_AttributesParser_INCLUDED
diff --git a/Poco/CppParser/BuiltIn.h b/Poco/CppParser/BuiltIn.h
new file mode 100644
index 0000000..666cd70
--- /dev/null
+++ b/Poco/CppParser/BuiltIn.h
@@ -0,0 +1,47 @@
+//
+// BuiltIn.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  BuiltIn
+//
+// Definition of the BuiltIn class.
+//
+// Copyright (c) 2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_BuiltIn_INCLUDED
+#define CppParser_BuiltIn_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Symbol.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API BuiltIn: public Symbol
+	/// A placeholder for a built-in type.
+{
+public:
+	BuiltIn(const std::string& name, NameSpace* pNameSpace);
+		/// Creates the BuiltIn.
+
+	~BuiltIn();
+		/// Destroys the BuiltIn.
+
+	Symbol::Kind kind() const;
+	std::string toString() const;
+};
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_BuiltIn_INCLUDED
diff --git a/Poco/CppParser/CppParser.h b/Poco/CppParser/CppParser.h
new file mode 100644
index 0000000..ad7d66b
--- /dev/null
+++ b/Poco/CppParser/CppParser.h
@@ -0,0 +1,58 @@
+//
+// CppParser.h
+//
+// Library: CppParser
+// Package: CppParser
+// Module:  CppParser
+//
+// Basic definitions for the Poco CppParser library.
+// This file must be the first file included by every other CppParser
+// header file.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_CppParser_INCLUDED
+#define CppParser_CppParser_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the CppParser_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// CppParser_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(POCO_DLL)
+	#if defined(CppParser_EXPORTS)
+		#define CppParser_API __declspec(dllexport)
+	#else
+		#define CppParser_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(CppParser_API)
+	#define CppParser_API
+#endif
+
+
+//
+// Automatically link CppParser library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(CppParser_EXPORTS)
+		#pragma comment(lib, "PocoCppParser" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // CppParser_CppParser_INCLUDED
diff --git a/Poco/CppParser/CppToken.h b/Poco/CppParser/CppToken.h
new file mode 100644
index 0000000..e53fb99
--- /dev/null
+++ b/Poco/CppParser/CppToken.h
@@ -0,0 +1,281 @@
+//
+// CppToken.h
+//
+// Library: CppParser
+// Package: CppParser
+// Module:  CppToken
+//
+// Definition of the CppToken class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_CppToken_INCLUDED
+#define CppParser_CppToken_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/Token.h"
+#include <map>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API CppToken: public Poco::Token
+	/// The base class for all C++ tokens.
+{
+public:
+	CppToken();
+	~CppToken();
+	
+protected:
+	void syntaxError(const std::string& expected, const std::string& actual);
+};
+
+
+class CppParser_API OperatorToken: public CppToken
+{
+public:
+	enum Tokens
+	{
+		OP_OPENBRACKET = 1, // [
+		OP_CLOSBRACKET,     // ]
+		OP_OPENPARENT,      // (
+		OP_CLOSPARENT,      // )
+		OP_OPENBRACE,       // {
+		OP_CLOSBRACE,       // }
+		OP_LT,              // <
+		OP_LE,              // <=
+		OP_SHL,             // <<
+		OP_SHL_ASSIGN,		// <<=
+		OP_GT,              // >
+		OP_GE,              // >=
+		OP_SHR,             // >>
+		OP_SHR_ASSIGN,      // >>=
+		OP_ASSIGN,          // =
+		OP_EQ,              // ==
+		OP_NOT,             // !
+		OP_NE,              // !=
+		OP_BITAND,          // &
+		OP_BITAND_ASSIGN,   // &=
+		OP_AND,             // &&
+		OP_BITOR,           // |
+		OP_BITOR_ASSIGN,    // |= 
+		OP_OR,              // ||
+		OP_XOR,             // ^
+		OP_XOR_ASSIGN,      // ^=
+		OP_COMPL,           // ~
+		OP_ASTERISK,        // *
+		OP_ASTERISK_ASSIGN, // *=
+		OP_SLASH,           // /
+		OP_SLASH_ASSIGN,    // /=
+		OP_PLUS,            // +
+		OP_PLUS_ASSIGN,     // +=
+		OP_INCR,            // ++
+		OP_MINUS,           // -
+		OP_MINUS_ASSIGN,    // -=
+		OP_DECR,            // --
+		OP_ARROW,           // ->
+		OP_MOD,             // %
+		OP_MOD_ASSIGN,      // %=
+		OP_COMMA,           // ,
+		OP_PERIOD,          // .
+		OP_TRIPLE_PERIOD,   // ...
+		OP_COLON,           // :
+		OP_DBL_COLON,       // ::
+		OP_SEMICOLON,       // ;
+		OP_QUESTION         // ?
+	};
+	
+	OperatorToken();
+	~OperatorToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+	int asInteger() const;
+	
+private:
+	typedef std::map<std::string, int> OpMap;
+	
+	OpMap _opMap;
+};
+
+
+class CppParser_API IdentifierToken: public CppToken
+{
+public:
+	enum Keywords
+	{
+		KW_ALIGNAS = 1,
+		KW_ALIGNOF,
+		KW_AND,
+		KW_AND_EQ,
+		KW_ASM,
+		KW_AUTO,
+		KW_BITAND,
+		KW_BITOR,
+		KW_BOOL,
+		KW_BREAK,
+		KW_CASE,
+		KW_CATCH,
+		KW_CHAR,
+		KW_CHAR_16T,
+		KW_CHAR_32T,
+		KW_CLASS,
+		KW_COMPL,
+		KW_CONST,
+		KW_CONSTEXPR,
+		KW_CONST_CAST,
+		KW_CONTINUE,
+		KW_DECLTYPE,
+		KW_DEFAULT,
+		KW_DELETE,
+		KW_DO,
+		KW_DOUBLE,
+		KW_DYNAMIC_CAST,
+		KW_ELSE,
+		KW_ENUM,
+		KW_EXPLICIT,
+		KW_EXPORT,
+		KW_EXTERN,
+		KW_FALSE,
+		KW_FLOAT,
+		KW_FOR,
+		KW_FRIEND,
+		KW_GOTO,
+		KW_IF,
+		KW_INLINE,
+		KW_INT,
+		KW_LONG,
+		KW_MUTABLE,
+		KW_NAMESPACE,
+		KW_NEW,
+		KW_NOEXCEPT,
+		KW_NOT,
+		KW_NOT_EQ,
+		KW_NULLPTR,
+		KW_OPERATOR,
+		KW_OR,
+		KW_OR_EQ,
+		KW_PRIVATE,
+		KW_PROTECTED,
+		KW_PUBLIC,
+		KW_REGISTER,
+		KW_REINTERPRET_CAST,
+		KW_RETURN,
+		KW_SHORT,
+		KW_SIGNED,
+		KW_SIZEOF,
+		KW_STATIC,
+		KW_STATIC_ASSERT,
+		KW_STATIC_CAST,
+		KW_STRUCT,
+		KW_SWITCH,
+		KW_TEMPLATE,
+		KW_THIS,
+		KW_THREAD_LOCAL,
+		KW_THROW,
+		KW_TRUE,
+		KW_TRY,
+		KW_TYPEDEF,
+		KW_TYPEID,
+		KW_TYPENAME,
+		KW_UNION,
+		KW_UNSIGNED,
+		KW_USING,
+		KW_VIRTUAL,
+		KW_VOID,
+		KW_VOLATILE,
+		KW_WCHAR_T,
+		KW_WHILE,
+		KW_XOR,
+		KW_XOR_EQ
+	};
+	
+	IdentifierToken();
+	~IdentifierToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+	int asInteger() const;
+	
+private:
+	typedef std::map<std::string, int> KWMap;
+	
+	KWMap _kwMap;
+};
+
+
+class CppParser_API StringLiteralToken: public CppToken
+{
+public:
+	StringLiteralToken();
+	~StringLiteralToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+	std::string asString() const;
+};
+
+
+class CppParser_API CharLiteralToken: public CppToken
+{
+public:
+	CharLiteralToken();
+	~CharLiteralToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+	char asChar() const;
+};
+
+
+class CppParser_API NumberLiteralToken: public CppToken
+{
+public:
+	NumberLiteralToken();
+	~NumberLiteralToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+	int asInteger() const;
+	double asFloat() const;
+	
+private:
+	bool _isFloat;
+};
+
+
+class CppParser_API CommentToken: public CppToken
+{
+public:
+	CommentToken();
+	~CommentToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+	std::string asString() const;
+};
+
+
+class CppParser_API PreprocessorToken: public CppToken
+{
+public:
+	PreprocessorToken();
+	~PreprocessorToken();
+	Poco::Token::Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+};
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_CppToken_INCLUDED
diff --git a/Poco/CppParser/Decl.h b/Poco/CppParser/Decl.h
new file mode 100644
index 0000000..c67e306
--- /dev/null
+++ b/Poco/CppParser/Decl.h
@@ -0,0 +1,62 @@
+//
+// Decl.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Decl
+//
+// Definition of the Decl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Decl_INCLUDED
+#define CppParser_Decl_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Symbol.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API Decl: public Symbol
+	/// This class represents a simple declaration in a C++ source file.
+	/// It is a base class for Function, TypeDef or Variable.
+{
+public:
+	Decl(const std::string& decl, NameSpace* pNameSpace);
+		/// Creates the Decl.
+
+	~Decl();
+		/// Destroys the Decl.
+
+	const std::string& declaration() const;
+		/// Returns the declaration.
+
+	std::string toString() const;
+
+protected:
+	std::string _decl;
+};
+
+
+//
+// inlines
+//
+inline const std::string& Decl::declaration() const
+{
+	return _decl;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Decl_INCLUDED
diff --git a/Poco/CppParser/Enum.h b/Poco/CppParser/Enum.h
new file mode 100644
index 0000000..d4305c5
--- /dev/null
+++ b/Poco/CppParser/Enum.h
@@ -0,0 +1,77 @@
+//
+// Enum.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Enum
+//
+// Definition of the Enum class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Enum_INCLUDED
+#define CppParser_Enum_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Symbol.h"
+#include <vector>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class EnumValue;
+
+
+class CppParser_API Enum: public Symbol
+	/// This class represents an enum declaration.
+	///
+	/// An enumeration has an optional name and
+	/// a collection of EnumValues.
+{
+public:
+	typedef std::vector<EnumValue*> Values;
+	typedef Values::const_iterator Iterator;
+
+	Enum(const std::string& name, NameSpace* pNameSpace);
+		/// Creates the Enum.
+		///
+		/// If name is the empty string, an internal name
+		/// in the form #AnonEnum<n> (where <n> is a unique integer)
+		/// will be assigned.
+
+	~Enum();
+		/// Destroys the Enum.
+
+	void addValue(EnumValue* pValue);
+		/// Adds an enum value. The Enum takes ownership of the value.
+		
+	Iterator begin() const;
+		/// Returns an iterator for iterating over the Enum's EnumValue's.
+		
+	Iterator end() const;
+		/// Returns an iterator for iterating over the Enum's EnumValue's.
+	
+	Symbol::Kind kind() const;
+	std::string toString() const;
+
+protected:
+	static std::string processName(const std::string& name);
+
+private:	
+	Values _values;
+	static int _count;
+};
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Enum_INCLUDED
diff --git a/Poco/CppParser/EnumValue.h b/Poco/CppParser/EnumValue.h
new file mode 100644
index 0000000..f0e082f
--- /dev/null
+++ b/Poco/CppParser/EnumValue.h
@@ -0,0 +1,66 @@
+//
+// EnumValue.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  EnumValue
+//
+// Definition of the EnumValue class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_EnumValue_INCLUDED
+#define CppParser_EnumValue_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Symbol.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class Enum;
+
+
+class CppParser_API EnumValue: public Symbol
+	/// This class represents an enumeration value
+	/// inside an enum declaration.
+{
+public:
+	EnumValue(const std::string& name, const std::string& value, Enum* pEnum);
+		/// Creates the EnumValue, using the name and a value, which may be empty.
+
+	virtual ~EnumValue();
+		/// Destroys the EnumValue.
+
+	const std::string& value() const;
+		/// Returns the value, which may be empty.
+
+	Symbol::Kind kind() const;
+	std::string toString() const;
+
+private:
+	std::string _value;
+};
+
+
+//
+// inlines
+//
+inline const std::string& EnumValue::value() const
+{
+	return _value;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_EnumValue_INCLUDED
diff --git a/Poco/CppParser/Function.h b/Poco/CppParser/Function.h
new file mode 100644
index 0000000..8e051ba
--- /dev/null
+++ b/Poco/CppParser/Function.h
@@ -0,0 +1,166 @@
+//
+// Function.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Function
+//
+// Definition of the Function class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Function_INCLUDED
+#define CppParser_Function_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Decl.h"
+#include <vector>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class Parameter;
+
+
+class CppParser_API Function: public Decl
+	/// This class represents a (member) function declaration.
+{
+public:
+	enum Flags
+	{
+		FN_STATIC       = 1,   /// The function is static.
+		FN_VIRTUAL      = 2,   /// The function is virtual.
+		FN_INLINE       = 4,   /// The function is inline.
+		FN_CONST        = 8,   /// The function is const.
+		FN_TEMPLATE     = 16,  /// The function is a template.
+		FN_PURE_VIRTUAL = 32,  /// The function is pure virtual.
+		FN_FINAL        = 64,  /// The function is final.
+		FN_OVERRIDE     = 128, /// The function is override.
+		FN_NOEXCEPT     = 256, /// The function is noexcept.
+		FN_DEFAULT      = 512, /// The function is default.
+		FN_DELETE       = 1024 /// The function has been deleted.
+	};
+	
+	typedef std::vector<Parameter*> Parameters;
+	typedef Parameters::const_iterator Iterator;
+
+	Function(const std::string& decl, NameSpace* pNameSpace);
+		/// Creates the Function.
+
+	~Function();
+		/// Destroys the Function.
+
+	void addParameter(Parameter* pParam);
+		/// Adds a parameter to the function.
+
+	const std::string& getReturnParameter() const;
+
+	Iterator begin() const;
+		/// Returns an iterator for iterating over the Function's Parameter's.
+
+	Iterator end() const;
+		/// Returns an iterator for iterating over the Function's Parameter's.
+	
+	void makeInline();
+		/// Sets the FN_INLINE flag.
+	
+	void makeConst();
+		/// Sets the FN_CONST flag.
+		
+	void makePureVirtual();
+		/// Sets the FN_PURE_VIRTUAL flag.
+		
+	void makeFinal();
+		/// Sets the FN_FINAL flag.
+		
+	void makeOverride();
+		/// Sets the FN_OVERRIDE flag.
+		
+	void makeNoexcept();
+		/// Sets the FN_NOEXCEPT flag.
+
+	void makeDefault();
+		/// Sets the FN_DEFAULT flag.
+	
+	void makeDelete();
+		/// Sets the FN_DELETE flag.
+	
+	int flags() const;
+		/// Returns the function's flags.
+		
+	bool isConstructor() const;
+		/// Returns true iff the function is a constructor.
+		
+	bool isDestructor() const;
+		/// Returns true iff the function is a destructor.
+
+	bool isMethod() const;
+		/// Returns true iff the function is a method (it's part of
+		/// a Struct and it's neither a constructor nor a destructor).
+		
+	bool isFunction() const;
+		/// Returns true iff the function is not a member of a class
+		/// (a freestanding function).
+
+	bool isConst() const;
+		/// Returns true iff the method is const.
+		
+	int countParameters() const;
+		/// Returns the number of parameters.
+	
+	std::string signature() const;
+		/// Returns the signature of the function.
+		
+	bool isVirtual() const;
+		/// Returns true if the method is virtual. Also examines base
+		/// classes to check for a virtual function with the same
+		/// signature.
+		
+	Function* getOverridden() const;
+		/// If the function is virtual and overrides a function in a
+		/// base class, the base class function is returned.
+		/// Otherwise, null is returned.
+		
+	Symbol::Kind kind() const;
+	std::string toString() const;
+
+private:
+	Parameters  _params;
+	int         _flags;
+	std::string _retParam;
+};
+
+
+//
+// inlines
+//
+inline int Function::flags() const
+{
+	return _flags;
+}
+
+
+inline const std::string& Function::getReturnParameter() const
+{
+	return _retParam;
+}
+
+
+inline bool Function::isConst() const
+{
+	return (flags() & FN_CONST) != 0;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Function_INCLUDED
diff --git a/Poco/CppParser/NameSpace.h b/Poco/CppParser/NameSpace.h
new file mode 100644
index 0000000..6a3f260
--- /dev/null
+++ b/Poco/CppParser/NameSpace.h
@@ -0,0 +1,138 @@
+//
+// NameSpace.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  NameSpace
+//
+// Definition of the NameSpace class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_NameSpace_INCLUDED
+#define CppParser_NameSpace_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Symbol.h"
+#include <map>
+#include <vector>
+#include <set>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API NameSpace: public Symbol
+	/// This class represents a namespace.
+{
+public:
+	typedef std::multimap<std::string, Symbol*> SymbolTable;
+	typedef SymbolTable::const_iterator Iterator;
+	typedef std::map<std::string, std::string> AliasMap;
+	typedef std::vector<std::string> NameSpaceVec;
+	
+	NameSpace();
+		/// Creates the NameSpace.
+
+	NameSpace(const std::string& name, NameSpace* pNameSpace = 0);
+		/// Creates the NameSpace.
+
+	~NameSpace();
+		/// Destroys the NameSpace.
+	
+	void addSymbol(Symbol* pSymbol);
+		/// Adds a symbol to the namespace.
+		
+	void importSymbol(const std::string& fullName);
+		/// Imports a symbol from another namespace (using <symbol>).
+		
+	void importNameSpace(const std::string& nameSpace);
+		/// Imports a namespace (using namespace <namespace>).
+	
+	Iterator begin() const;
+		/// Returns an iterator for iterating over the NameSpace's Symbol's.
+
+	Iterator end() const;
+		/// Returns an iterator for iterating over the NameSpace's Symbol's.
+	
+	Symbol* lookup(const std::string& name) const;
+		/// Looks up the given name in the symbol table
+		/// and returns the corresponsing symbol, or null
+		/// if no symbol can be found. The name can include
+		/// a namespace.
+		
+	static NameSpace* root();
+		/// Returns the root namespace. Never delete this one!
+	
+	void nameSpaces(SymbolTable& table) const;
+		/// Fills the symbol table with all namespaces.
+		
+	void typeDefs(SymbolTable& table) const;
+		/// Fills the symbol table with all type definitions.
+		
+	void enums(SymbolTable& table) const;
+		/// Fills the symbol table with all enums.
+		
+	void classes(SymbolTable& table) const;
+		/// Fills the symbol table with all classes and structs.
+		
+	void functions(SymbolTable& table) const;
+		/// Fills the symbol table with all functions.
+		
+	void variables(SymbolTable& table) const;
+		/// Fills the symbol table with all variables.
+		
+	const AliasMap& importedSymbols() const;
+		/// Returns a const reference to a SymbolTable containing all
+		/// imported symbols.
+		
+	const NameSpaceVec& importedNameSpaces() const;
+		/// Returns a vector containing all imported namespaces.
+
+	Symbol::Kind kind() const;
+	std::string toString() const;
+
+private:
+	Symbol* lookup(const std::string& name, std::set<const NameSpace*>& alreadyVisited) const;
+		/// Looks up the given name in the symbol table
+		/// and returns the corresponsing symbol, or null
+		/// if no symbol can be found. The name can include
+		/// a namespace.
+
+protected:
+	void extract(Symbol::Kind kind, SymbolTable& table) const;
+	static void splitName(const std::string& name, std::string& head, std::string& tail);
+
+private:
+	SymbolTable _symbols;
+	AliasMap _importedSymbols;
+	NameSpaceVec _importedNameSpaces;
+};
+
+
+//
+// inlines
+//
+inline const NameSpace::AliasMap& NameSpace::importedSymbols() const
+{
+	return _importedSymbols;
+}
+
+	
+inline const NameSpace::NameSpaceVec& NameSpace::importedNameSpaces() const
+{
+	return _importedNameSpaces;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_NameSpace_INCLUDED
diff --git a/Poco/CppParser/Parameter.h b/Poco/CppParser/Parameter.h
new file mode 100644
index 0000000..61de6c0
--- /dev/null
+++ b/Poco/CppParser/Parameter.h
@@ -0,0 +1,142 @@
+//
+// Parameter.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Parameter
+//
+// Definition of the Parameter class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Parameter_INCLUDED
+#define CppParser_Parameter_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Decl.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class Function;
+
+
+class CppParser_API Parameter: public Decl
+	/// This class represents a parameter to a function.
+{
+public:
+	Parameter(const std::string& decl, Function* pFunction);
+		/// Creates the Parameter.
+
+	~Parameter();
+		/// Destroys the Parameter.
+
+	Symbol::Kind kind() const;
+
+	bool isReference() const;
+		/// Returns true iff the parameter is a reference.
+
+	bool isPointer() const;
+		/// Returns true iff the parameter is a pointer.
+
+	bool isConst() const;
+		/// Returns true iff the parameter is const.
+
+	bool hasDefaultValue() const;
+		/// Returns true if a defaultvalue was set at this parameter,
+		/// Example: const std::string& data = std::string("default").
+
+	const std::string& declType() const;
+		/// Returns the type of the parameter without const and & if present.
+		///
+		/// Example: a type const std::string& -> std::string, a type const std::string* returns std::string
+
+	const std::string& defaultValue() const;
+		/// If hasDefaultValue() returns true, this method returns the default value, i.e. all data found between
+		/// the opening and closing bracket of the init string.
+		///
+		/// Example: for const std::string& data = std::string("default") it will return "default",
+		/// for = std::string() it will return a zero length string, for = ComplexClass(13,12, "test", 0);
+		/// it will return 13,12, "test", 0.
+
+	const std::string& defaultDecl() const;
+		/// If hasDefaultValue() returns true, this method returns the
+		/// default value declaration.
+		///
+		/// Example: for const std::string& data = std::string("default") it will return std::string("default").
+
+	static bool vectorType(const std::string& type, NameSpace* pNS);
+
+private:
+	std::string handleDecl(const std::string& decl);
+	/// Removes initialization values, adds param Names if they are missing
+
+private:
+	std::string _type;
+	bool        _isRef;
+	bool        _isPointer;
+	bool        _isConst;
+	bool        _hasDefaultValue;
+	std::string _defaultValue;
+	std::string _defaultDecl;
+	static int  _count;
+};
+
+
+//
+// inlines
+//
+inline const std::string& Parameter::declType() const
+{
+	return _type;
+}
+
+
+inline bool Parameter::isReference() const
+{
+	return _isRef;
+}
+
+
+inline bool Parameter::isConst() const
+{
+	return _isConst;
+}
+
+
+inline bool Parameter::isPointer() const
+{
+	return _isPointer;
+}
+
+
+inline bool Parameter::hasDefaultValue() const
+{
+	return _hasDefaultValue;
+}
+
+
+inline const std::string& Parameter::defaultValue() const
+{
+	return _defaultValue;
+}
+
+
+inline const std::string& Parameter::defaultDecl() const
+{
+	return _defaultDecl;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Parameter_INCLUDED
diff --git a/Poco/CppParser/Parser.h b/Poco/CppParser/Parser.h
new file mode 100644
index 0000000..6c7e4a4
--- /dev/null
+++ b/Poco/CppParser/Parser.h
@@ -0,0 +1,127 @@
+//
+// Parser.h
+//
+// Library: CppParser
+// Package: CppParser
+// Module:  Parser
+//
+// Definition of the Parser class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Parser_INCLUDED
+#define CppParser_Parser_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Tokenizer.h"
+#include "Poco/CppParser/Symbol.h"
+#include "Poco/CppParser/NameSpace.h"
+#include "Poco/CountingStream.h"
+#include <vector>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class Enum;
+class Struct;
+class Function;
+
+
+class CppParser_API Parser
+	/// A minimal parser for C++ (header files).
+	///
+	/// The parser reads a (preprocessed) source or header file and
+	/// builds a symbol table containing as much information as
+	/// the parser is able to extract from the file.
+	///
+	/// A special comment syntax is used for inline API documentation.
+	///
+	/// A comment starting with three consecutive slashes (///) contains
+	/// API documentation for a symbol (class, function, typedef, enum, etc.).
+	/// API documentation comments always come after the declaration, with the
+	/// exception of structs and classes, where the comments are expected
+	/// immediately before the opening brace.
+{
+public:
+	Parser(NameSpace::SymbolTable& gst, const std::string& file, std::istream& istr);
+		/// Creates the Parser.
+
+	~Parser();
+		/// Destroys the Parser.
+
+	void parse();
+		/// Parses the file.
+
+protected:
+	const Poco::Token* parseFile(const Poco::Token* pNext);
+	const Poco::Token* parseNameSpace(const Poco::Token* pNext);
+	const Poco::Token* parseClass(const Poco::Token* pNext);
+	const Poco::Token* parseClass(const Poco::Token* pNext, std::string& decl);
+	const Poco::Token* parseTemplate(const Poco::Token* pNext);
+	const Poco::Token* parseTemplateArgs(const Poco::Token* pNext, std::string& decl);
+	const Poco::Token* parseVarFunc(const Poco::Token* pNext);
+	const Poco::Token* parseVarFunc(const Poco::Token* pNext, std::string& decl);
+	const Poco::Token* parseFriend(const Poco::Token* pNext);
+	const Poco::Token* parseExtern(const Poco::Token* pNext);
+	const Poco::Token* parseTypeDef(const Poco::Token* pNext);
+	const Poco::Token* parseUsing(const Poco::Token* pNext);
+	const Poco::Token* parseFunc(const Poco::Token* pNext, std::string& decl);
+	const Poco::Token* parseParameters(const Poco::Token* pNext, Function* pFunc);
+	const Poco::Token* parseBlock(const Poco::Token* pNext);
+	const Poco::Token* parseEnum(const Poco::Token* pNext);
+	const Poco::Token* parseEnumValue(const Poco::Token* pNext, Enum* pEnum);
+	const Poco::Token* parseBaseClassList(const Poco::Token* pNext, Struct* pClass);
+	const Poco::Token* parseClassMembers(const Poco::Token* pNext, Struct* pClass);
+	const Poco::Token* parseAccess(const Poco::Token* pNext);
+	const Poco::Token* parseIdentifier(const Poco::Token* pNext, std::string& id);
+	
+	void addSymbol(Symbol* pSymbol, int lineNumber, bool addGST = true);
+	void pushNameSpace(NameSpace* pNameSpace, int lineNumber, bool addGST = true);
+	void popNameSpace();
+	NameSpace* currentNameSpace() const;
+
+	static bool isIdentifier(const Poco::Token* pToken);
+	static bool isOperator(const Poco::Token* pToken, int kind);
+	static bool isKeyword(const Poco::Token* pToken, int kind);
+	static bool isEOF(const Poco::Token* pToken);
+	static void expectOperator(const Poco::Token* pToken, int kind, const std::string& msg);
+	static void syntaxError(const std::string& msg);
+	static void append(std::string& decl, const std::string& token);
+	static void append(std::string& decl, const Poco::Token* pToken);
+
+	const Poco::Token* next();
+	const Poco::Token* nextPreprocessed();
+	const Poco::Token* nextToken();
+
+private:
+	typedef std::vector<NameSpace*> NSStack;
+
+	NameSpace::SymbolTable& _gst;
+	Poco::CountingInputStream _istr;
+	Tokenizer      _tokenizer;
+	std::string    _file;
+	std::string    _path;
+	std::string    _currentPath;
+	bool           _inFile;
+	std::string    _package;
+	std::string    _library;
+	NSStack        _nsStack;
+	Symbol*        _pCurrentSymbol;
+	Symbol::Access _access;
+	std::string    _doc;
+	std::string    _attrs;
+};
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Parser_INCLUDED
diff --git a/Poco/CppParser/Struct.h b/Poco/CppParser/Struct.h
new file mode 100644
index 0000000..12c25cb
--- /dev/null
+++ b/Poco/CppParser/Struct.h
@@ -0,0 +1,205 @@
+//
+// Struct.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Struct
+//
+// Definition of the Struct class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Struct_INCLUDED
+#define CppParser_Struct_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/NameSpace.h"
+#include <vector>
+#include <set>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class Function;
+
+
+class CppParser_API Struct: public NameSpace
+	/// This class represents a struct or class declaration.
+{
+public:
+	enum Flags
+	{
+		FN_TEMPLATE = 1,
+		FN_INLINE   = 2, // when the whole class is inlined in a c++ file
+		FN_TEMPLATE_SPECIALIZATION = 4,
+		FN_FINAL = 8
+	};
+	
+	struct Base
+	{
+		Symbol::Access access;
+		bool           isVirtual;
+		std::string    name;
+		Struct*        pClass;
+	};
+	
+	typedef std::vector<Base>           BaseClasses;
+	typedef BaseClasses::const_iterator BaseIterator;
+	typedef std::vector<Struct*>        StructVec;
+	typedef StructVec::const_iterator   DerivedIterator;
+	typedef std::vector<Function*>      Functions;
+	typedef std::set<Function*>         FunctionSet;
+	typedef std::set<Struct*>           StructSet;
+
+	Struct(const std::string& decl, bool isClass, NameSpace* pNameSpace);
+		/// Creates the Struct.
+
+	~Struct();
+		/// Destroys the Struct.
+
+	void addBase(const std::string&, Symbol::Access access, bool isVirtual);
+		/// Adds a base class.
+				
+	BaseIterator baseBegin() const;
+		/// Returns an iterator for iterating over all base classes.
+		
+	BaseIterator baseEnd() const;
+		/// Returns an iterator for iterating over all base classes.
+	
+	void fixupBases();
+		/// Adds pointers for all base classes.
+
+	void addDerived(Struct* pClass);
+		/// Adds a derived class.
+
+	DerivedIterator derivedBegin() const;
+		/// Returns an iterator for iterating over all derived classes.
+
+	DerivedIterator derivedEnd() const;
+		/// Returns an iterator for iterating over all derived classes.
+
+	const std::string& declaration() const;
+		/// Returns the declaration.
+	
+	int flags() const;
+		/// Returns the struct's flags.
+
+	void makeInline();
+		/// Changes the class to a inline class, i.e. definition and implementation are hidden in a cpp file.
+		
+	void makeFinal();
+		/// Makes the class final.
+
+	bool isInline() const;
+		/// Returns true if the complete class is inlined in a cpp file.
+
+	bool isFinal() const;
+		/// Returns true if the class is final.
+
+	void constructors(Functions& functions) const;
+		/// Returns all constructors, sorted by their parameter count.
+	
+	Function* destructor() const;
+		/// Returns the destructor, or NULL if no
+		/// destructor is defined.
+
+	void methods(Symbol::Access access, Functions& functions) const;
+		/// Returns all functions with the given access.
+	
+	void inheritedMethods(FunctionSet& functions) const;
+		/// Returns all inherited methods.
+	
+	void bases(std::set<std::string>& bases) const;
+		/// Returns all base classes.
+		
+	void derived(StructSet& derived) const;
+		/// Returns all derived classes.	
+		
+	Function* findFunction(const std::string& signature) const;
+		/// Finds a function with the given signature.
+		
+	bool hasVirtualDestructor() const;
+		/// Returns true if the class CppParser_API or one if its base classes
+		/// has a virtual destructor.
+
+	bool isClass() const;
+		/// Returns true iff the struct was declared as class.
+		
+	bool isDerived() const;
+		/// Returns true iff the struct or class is derived from another struct or class.
+
+	Symbol::Kind kind() const;
+	std::string toString() const;
+	
+private:
+	std::string _decl;
+	BaseClasses _bases;
+	StructVec   _derived;
+	int         _flags;
+	bool        _isClass;
+};
+
+
+//
+// inlines
+//
+inline const std::string& Struct::declaration() const
+{
+	return _decl;
+}
+
+
+inline int Struct::flags() const
+{
+	return _flags;
+}
+
+
+inline bool Struct::isClass() const
+{
+	return _isClass;
+}
+
+
+inline void Struct::makeInline()
+{
+	_flags |= FN_INLINE;
+}
+
+
+inline void Struct::makeFinal()
+{
+	_flags |= FN_FINAL;
+}
+
+
+inline bool Struct::isInline() const
+{
+	return (_flags & FN_INLINE) != 0;
+}
+
+
+inline bool Struct::isFinal() const
+{
+	return (_flags & FN_FINAL) != 0;
+}
+
+
+inline bool Struct::isDerived() const
+{
+	return !_bases.empty();
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Struct_INCLUDED
diff --git a/Poco/CppParser/Symbol.h b/Poco/CppParser/Symbol.h
new file mode 100644
index 0000000..e731d45
--- /dev/null
+++ b/Poco/CppParser/Symbol.h
@@ -0,0 +1,266 @@
+//
+// Symbol.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Symbol
+//
+// Definition of the Symbol class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Symbol_INCLUDED
+#define CppParser_Symbol_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Attributes.h"
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class NameSpace;
+
+
+class CppParser_API Symbol
+	/// This is the base class for all symbols in the symbol table.
+	///
+	/// Every symbol has a unique ID (int) and a namespace (which
+	/// may be null).
+{
+public:
+	enum Kind
+	{
+		SYM_ENUM,       /// An enumeration
+		SYM_ENUM_VALUE, /// An enumeration value
+		SYM_FUNCTION,   /// A (member) function
+		SYM_NAMESPACE,  /// A namespace
+		SYM_PARAMETER,  /// A function parameter
+		SYM_STRUCT,     /// A struct or class
+		SYM_TYPEDEF,    /// A typedef
+		SYM_BUILTIN,    /// A built-in type
+		SYM_VARIABLE    /// A (member) variable
+	};
+	
+	enum Access
+	{
+		ACC_PUBLIC,     /// public access
+		ACC_PROTECTED,  /// protected access
+		ACC_PRIVATE     /// private access
+	};
+	
+	Symbol();
+		/// Creates the Symbol and assigns the symbol
+		/// a unique ID.
+		
+	Symbol(const std::string& name, NameSpace* pNameSpace = 0);
+		/// Creates the Symbol and assigns the symbol
+		/// a unique ID.
+
+	virtual ~Symbol();
+		/// Destroys the Symbol.
+
+	int id() const;
+		/// Returns the symbol's unique ID.
+
+	const std::string& name() const;
+		/// Returns the symbol's (local) name.
+		
+	NameSpace* nameSpace() const;
+		/// Returns the symbol's namespace which
+		/// may be null.
+	
+	void setAccess(Access v);
+		/// Sets the symbol's access.
+		
+	Access getAccess() const;
+		/// Returns the symbol's access.
+		
+	void setDocumentation(const std::string& text);
+		/// Sets the symbol's documentation.
+		
+	void addDocumentation(const std::string& text);
+		/// Adds text to the symbol's documentation.
+		
+	const std::string& getDocumentation() const;
+		/// Returns the symbol's documentation.
+		
+	void setFile(const std::string& path);
+		/// Sets the file where the symbol is declared.
+		
+	const std::string& getFile() const;
+		/// Returns the file where the symbol is defined.
+		
+	void setLineNumber(int line);
+		/// Sets the line number of the symbol's declaration.
+		
+	int getLineNumber() const;
+		/// Returns the line number of the symbol's declaration.
+	
+	void setPackage(const std::string& package);
+		/// Sets the symbol's package.
+		
+	const std::string& getPackage() const;
+		/// Returns the symbol's package.
+		
+	void setLibrary(const std::string& library);
+		/// Sets the symbol's library.
+		
+	const std::string& getLibrary() const;
+		/// Returns the symbol's library.
+	
+	const Attributes& attrs() const;
+		/// Returns the symbol's attributes.
+
+	Attributes& attrs();
+		/// Returns the symbol's attributes.
+				
+	const Attributes& getAttributes() const;
+		/// Returns the symbol's attributes.
+		
+	void setAttributes(const Attributes& attrs);
+		/// Sets the symbol's attributes.
+	
+	std::string fullName() const;
+		/// Returns the symbol's fully qualified name.
+
+	static std::string extractName(const std::string& decl);
+		/// Extracts the name from the declaration.
+		
+	virtual Kind kind() const = 0;
+		/// Returns the symbol's kind.
+		
+	virtual std::string toString() const = 0;
+		/// Returns a string representation of the symbol.
+		
+	bool isPublic() const;
+		/// Returns true iff the symbol is public.
+		
+	bool isProtected() const;
+		/// Returns true iff the symbol is public.
+
+	bool isPrivate() const;
+		/// Returns true iff the symbol is public.
+		
+protected:
+	static bool isIdent(char c);
+	static bool hasAttr(const std::string& decl, const std::string& attr);
+	
+private:
+	Symbol(const Symbol&);
+	Symbol& operator = (const Symbol&);
+
+	int         _id;
+	std::string _name;
+	NameSpace*  _pNameSpace;
+	Access      _access;
+	std::string _documentation;
+	std::string _file;
+	int         _line;
+	std::string _package;
+	std::string _library;
+	Attributes  _attrs;
+	
+	static int  _nextId;
+};
+
+
+//
+// inlines
+//
+inline int Symbol::id() const
+{
+	return _id;
+}
+
+
+inline const std::string& Symbol::name() const
+{
+	return _name;
+}
+
+
+inline const std::string& Symbol::getDocumentation() const
+{
+	return _documentation;
+}
+
+
+inline Symbol::Access Symbol::getAccess() const
+{
+	return _access;
+}
+
+
+inline NameSpace* Symbol::nameSpace() const
+{
+	return _pNameSpace;
+}
+
+
+inline const std::string& Symbol::getFile() const
+{
+	return _file;
+}
+
+
+inline int Symbol::getLineNumber() const
+{
+	return _line;
+}
+
+
+inline const std::string& Symbol::getPackage() const
+{
+	return _package;
+}
+
+
+inline const std::string& Symbol::getLibrary() const
+{
+	return _library;
+}
+
+
+inline const Attributes& Symbol::attrs() const
+{
+	return _attrs;
+}
+
+
+inline Attributes& Symbol::attrs()
+{
+	return _attrs;
+}
+
+
+inline bool Symbol::isPublic() const
+{
+	return _access == ACC_PUBLIC;
+}
+
+
+inline bool Symbol::isProtected() const
+{
+	return _access == ACC_PROTECTED;
+}
+
+
+inline bool Symbol::isPrivate() const
+{
+	return _access == ACC_PRIVATE;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Symbol_INCLUDED
diff --git a/Poco/CppParser/Tokenizer.h b/Poco/CppParser/Tokenizer.h
new file mode 100644
index 0000000..8a59d1d
--- /dev/null
+++ b/Poco/CppParser/Tokenizer.h
@@ -0,0 +1,44 @@
+//
+// Tokenizer.h
+//
+// Library: CppParser
+// Package: CppParser
+// Module:  Tokenizer
+//
+// Definition of the Tokenizer class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Tokenizer_INCLUDED
+#define CppParser_Tokenizer_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/StreamTokenizer.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API Tokenizer: public Poco::StreamTokenizer
+	/// A Tokenizer for C++.
+{
+public:
+	Tokenizer(std::istream& istr);
+		/// Creates the Tokenizer.
+
+	~Tokenizer();
+		/// Destroys the Tokenizer.
+};
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Tokenizer_INCLUDED
diff --git a/Poco/CppParser/TypeDef.h b/Poco/CppParser/TypeDef.h
new file mode 100644
index 0000000..d629464
--- /dev/null
+++ b/Poco/CppParser/TypeDef.h
@@ -0,0 +1,49 @@
+//
+// TypeDef.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  TypeDef
+//
+// Definition of the TypeDef class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_TypeDef_INCLUDED
+#define CppParser_TypeDef_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Decl.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API TypeDef: public Decl
+	/// This class represents a type definition (typedef).
+{
+public:
+	TypeDef(const std::string& decl, NameSpace* pNameSpace);
+		/// Creates the TypeDef.
+
+	~TypeDef();
+		/// Destroys the TypeDef.
+
+	Symbol::Kind kind() const;
+	
+	std::string baseType() const;
+		/// Returns the underlying base type.
+};
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_TypeDef_INCLUDED
diff --git a/Poco/CppParser/Utility.h b/Poco/CppParser/Utility.h
new file mode 100644
index 0000000..3ded488
--- /dev/null
+++ b/Poco/CppParser/Utility.h
@@ -0,0 +1,85 @@
+//
+// Utility.h
+//
+// Library: CppParser
+// Package: CppParser
+// Module:  Utility
+//
+// Definition of the Utility class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Utility_INCLUDED
+#define CppParser_Utility_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/NameSpace.h"
+#include <vector>
+#include <set>
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API Utility
+	/// Various helpers for parsing and analyzing C++ header files.
+{
+public:
+	class CppParser_API FwdDeclBlock
+	{
+	public:
+		std::string beginNameSpaceDecl;      // contains either $(NS)_BEGIN or the namespace x { decl
+		std::string endNameSpaceDecl;        // contains either $(NS)_END or the closing brackets }
+		std::vector<std::string> classDecls; // contains strings of the form "class X;" 
+	};
+	
+	static void parse(const std::string& file, NameSpace::SymbolTable& st, const std::string& exec, const std::string& options, const std::string& path);
+		/// Preprocesses and parses the file. The resulting symboltable has base class references already fixed,
+
+	static void parseDir(const std::vector <std::string>& includePattern, const std::vector <std::string>& excludePattern, NameSpace::SymbolTable& st, const std::string& exec, const std::string& options, const std::string& path);
+		/// Preprocesses and parses all files specified by the include pattern (e.g.: p:/poco/Foundation/include/*/*.h) minus the ones defined in the exclude pattern
+
+	static void fixup(NameSpace::SymbolTable& st);
+		/// Fixes all base pointers in the symbol table
+
+	static void detectPrefixAndIncludes(const std::string& origHFile, std::vector<std::string>& lines, std::string& prefix);
+		/// This method is poco coding style specific! It looks for a $(PREFIX)_BEGIN and extracts from it a prefix, also include files and fwd declarations are extracted from the h file.
+
+	static void removeFile(const std::string& preprocessedfile);
+		/// Tries to remove the file. If it fails, the error is silently ignored.
+
+protected:
+	static std::string preprocessFile(const std::string& file, const std::string& exec, const std::string& options, const std::string& path);
+		/// Preprocess the include file with name file. Parameter exec must contain the name of the preprocessor binary (e.g.: "cl" for Visual Studio).
+		/// Parameter options contains the flag for the preprocessor, and parameter path sets the environment PATH settings during preprocessing.
+		/// Returns the name of the created file or throws an exception.
+
+	static void parseOnly(const std::string& file, NameSpace::SymbolTable& st, const std::string& preprocessedFile, bool removePreprocessedFile = true);
+		/// Parses the file, throws an exception if anything goes wrong.
+
+	static void buildFileList(std::set<std::string>& files, const std::vector<std::string>& includePattern, const std::vector<std::string>& excludePattern);
+		/// Searches all files that match the defined patterns and inserts them into files.
+private:
+	Utility();
+	~Utility();
+	Utility(const Utility&);
+	Utility& operator=(const Utility&);
+
+};
+
+
+std::string CppParser_API replace(const std::string& input, const std::string& oldToken, const std::string& newToken);
+	/// Replaces in character input all oldTokens with the newToken
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Utility_INCLUDED
diff --git a/Poco/CppParser/Variable.h b/Poco/CppParser/Variable.h
new file mode 100644
index 0000000..d167eda
--- /dev/null
+++ b/Poco/CppParser/Variable.h
@@ -0,0 +1,92 @@
+//
+// Variable.h
+//
+// Library: CppParser
+// Package: SymbolTable
+// Module:  Variable
+//
+// Definition of the Variable class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef CppParser_Variable_INCLUDED
+#define CppParser_Variable_INCLUDED
+
+
+#include "Poco/CppParser/CppParser.h"
+#include "Poco/CppParser/Decl.h"
+
+
+namespace Poco {
+namespace CppParser {
+
+
+class CppParser_API Variable: public Decl
+	/// This class represents (member) variable declaration.
+{
+public:
+	enum Flags
+	{
+		VAR_STATIC  = 1,  /// The variable is static.
+		VAR_MUTABLE = 2,  /// The variable is mutable.
+		VAR_VOLATILE = 4, /// The variable is volatile.
+		VAR_CONST    = 8  /// The variable is const.
+	};
+	
+	Variable(const std::string& decl, NameSpace* pNameSpace);
+		/// Creates the Variable.
+
+	~Variable();
+		/// Destroys the Variable.
+		
+	int flags() const;
+		/// Returns the variable's flags.
+
+	bool isPointer() const;
+		/// Returns true iff the variable holds a pointer.
+
+	Symbol::Kind kind() const;
+
+	const std::string& declType() const;
+		/// Returns the type of the parameter without const and & if present.
+		///
+		/// Example: a type const std::string& -> std::string, a type const std::string* returns std::string
+
+		
+private:
+	int _flags;
+	bool _isPointer;
+	std::string _type;
+};
+
+
+//
+// inlines
+//
+inline int Variable::flags() const
+{
+	return _flags;
+}
+
+
+inline bool Variable::isPointer() const
+{
+	return _isPointer;
+}
+
+
+inline const std::string& Variable::declType() const
+{
+	return _type;
+}
+
+
+} } // namespace Poco::CppParser
+
+
+#endif // CppParser_Variable_INCLUDED
diff --git a/Poco/Crypto/Cipher.h b/Poco/Crypto/Cipher.h
new file mode 100644
index 0000000..fbe0c30
--- /dev/null
+++ b/Poco/Crypto/Cipher.h
@@ -0,0 +1,138 @@
+//
+// Cipher.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  Cipher
+//
+// Definition of the Cipher class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_Cipher_INCLUDED
+#define Crypto_Cipher_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <istream>
+#include <ostream>
+#include <vector>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class CryptoTransform;
+
+
+class Crypto_API Cipher: public Poco::RefCountedObject
+	/// Represents the abstract base class from which all implementations of
+	/// symmetric/asymmetric encryption algorithms must inherit.  Use the CipherFactory
+	/// class to obtain an instance of this class:
+	///
+	///     CipherFactory& factory = CipherFactory::defaultFactory();
+	///     // Creates a 256-bit AES cipher
+	///     Cipher* pCipher = factory.createCipher(CipherKey("aes-256"));
+	///     Cipher* pRSACipher = factory.createCipher(RSAKey(RSAKey::KL_1024, RSAKey::EXP_SMALL));
+	///
+	/// Check the different Key constructors on how to initialize/create
+	/// a key. The above example auto-generates random keys.
+	///
+	/// Note that you won't be able to decrypt data encrypted with a random key
+	/// once the Cipher is destroyed unless you persist the generated key and IV.
+	/// An example usage for random keys is to encrypt data saved in a temporary
+	/// file.
+	///
+	/// Once your key is set up, you can use the Cipher object to encrypt or
+	/// decrypt strings or, in conjunction with a CryptoInputStream or a
+	/// CryptoOutputStream, to encrypt streams of data.
+	///
+	/// Since encrypted strings will contain arbitrary binary data that will cause
+	/// problems in applications that are not binary-safe (eg., when sending
+	/// encrypted data in e-mails), the encryptString() and decryptString() can
+	/// encode (or decode, respectively) encrypted data using a "transport encoding".
+	/// Supported encodings are Base64 and BinHex.
+	///
+	/// The following example encrypts and decrypts a string utilizing Base64
+	/// encoding:
+	///
+	///     std::string plainText = "This is my secret information";
+	///     std::string encrypted = pCipher->encryptString(plainText, Cipher::ENC_BASE64);
+	///     std::string decrypted = pCipher->decryptString(encrypted, Cipher::ENC_BASE64);
+	///
+	/// In order to encrypt a stream of data (eg. to encrypt files), you can use
+	/// a CryptoStream:
+	///
+	///     // Create an output stream that will encrypt all data going through it
+	///     // and write pass it to the underlying file stream.
+	///     Poco::FileOutputStream sink("encrypted.dat");
+	///     CryptoOutputStream encryptor(sink, pCipher->createEncryptor());
+	///     
+	///     Poco::FileInputStream source("source.txt");
+	///     Poco::StreamCopier::copyStream(source, encryptor);
+	///     
+	///     // Always close output streams to flush all internal buffers
+	///     encryptor.close();
+	///     sink.close();
+{
+public:
+	typedef Poco::AutoPtr<Cipher> Ptr;
+	typedef std::vector<unsigned char> ByteVec;
+
+	enum Encoding
+		/// Transport encoding to use for encryptString() and decryptString().
+	{
+		ENC_NONE         = 0x00, /// Plain binary output
+		ENC_BASE64       = 0x01, /// Base64-encoded output
+		ENC_BINHEX       = 0x02, /// BinHex-encoded output
+		ENC_BASE64_NO_LF = 0x81, /// Base64-encoded output, no linefeeds
+		ENC_BINHEX_NO_LF = 0x82  /// BinHex-encoded output, no linefeeds
+		
+	};
+
+	virtual ~Cipher();
+		/// Destroys the Cipher.
+
+	virtual const std::string& name() const = 0;
+		/// Returns the name of the Cipher.
+
+	virtual CryptoTransform* createEncryptor() = 0;
+		/// Creates an encryptor object to be used with a CryptoStream.
+
+	virtual CryptoTransform* createDecryptor() = 0;
+		/// Creates a decryptor object to be used with a CryptoStream.
+
+	virtual std::string encryptString(const std::string& str, Encoding encoding = ENC_NONE);
+		/// Directly encrypt a string and encode it using the given encoding.
+
+	virtual std::string decryptString(const std::string& str, Encoding encoding = ENC_NONE);
+		/// Directly decrypt a string that is encoded with the given encoding.
+
+	virtual void encrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE);
+		/// Directly encrypts an input stream and encodes it using the given encoding.
+
+	virtual void decrypt(std::istream& source, std::ostream& sink, Encoding encoding = ENC_NONE);
+		/// Directly decrypt an input stream that is encoded with the given encoding.
+
+protected:
+	Cipher();
+		/// Creates a new Cipher object.
+
+private:
+	Cipher(const Cipher&);
+	Cipher& operator = (const Cipher&);
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_Cipher_INCLUDED
diff --git a/Poco/Crypto/CipherFactory.h b/Poco/Crypto/CipherFactory.h
new file mode 100644
index 0000000..36aa964
--- /dev/null
+++ b/Poco/Crypto/CipherFactory.h
@@ -0,0 +1,75 @@
+//
+// CipherFactory.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  CipherFactory
+//
+// Definition of the CipherFactory class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CipherFactory_INCLUDED
+#define Crypto_CipherFactory_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Cipher;
+class CipherKey;
+class RSAKey;
+
+
+class Crypto_API CipherFactory
+	/// A factory for Cipher objects. See the Cipher class for examples on how to
+	/// use the CipherFactory.
+{
+public:
+	CipherFactory();
+		/// Creates a new CipherFactory object.
+
+	virtual ~CipherFactory();
+		/// Destroys the CipherFactory.
+
+	Cipher* createCipher(const CipherKey& key);
+		/// Creates a Cipher object for the given Cipher name. Valid cipher 
+		/// names depend on the OpenSSL version the library is linked with;  
+		/// see the output of
+		///
+		///     openssl enc --help
+		///
+		/// for a list of supported block and stream ciphers.
+		///
+		/// Common examples are:
+		///
+		///   * AES: "aes-128", "aes-256"
+		///   * DES: "des", "des3"
+		///   * Blowfish: "bf"
+
+	Cipher* createCipher(const RSAKey& key, RSAPaddingMode paddingMode = RSA_PADDING_PKCS1);
+		/// Creates a RSACipher using the given RSA key and padding mode
+		/// for public key encryption/private key decryption.
+	
+	static CipherFactory& defaultFactory();
+		/// Returns the default CipherFactory.
+
+private:
+	CipherFactory(const CipherFactory&);
+	CipherFactory& operator = (const CipherFactory&);
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CipherFactory_INCLUDED
diff --git a/Poco/Crypto/CipherImpl.h b/Poco/Crypto/CipherImpl.h
new file mode 100644
index 0000000..d6e8e0e
--- /dev/null
+++ b/Poco/Crypto/CipherImpl.h
@@ -0,0 +1,69 @@
+//
+// CipherImpl.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  CipherImpl
+//
+// Definition of the CipherImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CipherImpl_INCLUDED
+#define Crypto_CipherImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/Cipher.h"
+#include "Poco/Crypto/CipherKey.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include <openssl/evp.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class CipherImpl: public Cipher
+	/// An implementation of the Cipher class for OpenSSL's crypto library.
+{
+public:
+	CipherImpl(const CipherKey& key);
+		/// Creates a new CipherImpl object for the given CipherKey.
+
+	virtual ~CipherImpl();
+		/// Destroys the CipherImpl.
+
+	const std::string& name() const;
+		/// Returns the name of the cipher.
+
+	CryptoTransform* createEncryptor();
+		/// Creates an encryptor object.
+
+	CryptoTransform* createDecryptor();
+		/// Creates a decryptor object.
+
+private:
+	CipherKey _key;
+	OpenSSLInitializer _openSSLInitializer;
+};
+
+
+//
+// Inlines
+//
+inline const std::string& CipherImpl::name() const
+{
+	return _key.name();
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CipherImpl_INCLUDED
diff --git a/Poco/Crypto/CipherKey.h b/Poco/Crypto/CipherKey.h
new file mode 100644
index 0000000..b102cc2
--- /dev/null
+++ b/Poco/Crypto/CipherKey.h
@@ -0,0 +1,201 @@
+//
+// CipherKey.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  CipherKey
+//
+// Definition of the CipherKey class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CipherKey_INCLUDED
+#define Crypto_CipherKey_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/CipherKeyImpl.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API CipherKey
+	/// CipherKey stores the key information for decryption/encryption of data.
+	/// To create a random key, using the following code:
+	///
+	///     CipherKey key("aes-256");
+	///
+	/// Note that you won't be able to decrypt data encrypted with a random key
+	/// once the Cipher is destroyed unless you persist the generated key and IV.
+	/// An example usage for random keys is to encrypt data saved in a temporary
+	/// file.
+	///
+	/// To create a key using a human-readable password
+	/// string, use the following code. We create a AES Cipher and 
+	/// use a salt value to make the key more robust:
+	///
+	///     std::string password = "secret";
+	///     std::string salt("asdff8723lasdf(**923412");
+	///     CipherKey key("aes-256", password, salt);
+	///
+	/// You may also control the digest and the number of iterations used to generate the key
+	/// by specifying the specific values. Here we create a key with the same data as before,
+	/// except that we use 100 iterations instead of DEFAULT_ITERATION_COUNT, and sha1 instead of
+	/// the default md5:
+	///
+	///     std::string password = "secret";
+	///     std::string salt("asdff8723lasdf(**923412");
+	///     std::string digest ("sha1");
+	///     CipherKey key("aes-256", password, salt, 100, digest);
+	///
+{
+public:
+	typedef CipherKeyImpl::Mode Mode;
+	typedef CipherKeyImpl::ByteVec ByteVec;
+
+	enum
+	{
+		DEFAULT_ITERATION_COUNT = 2000
+			/// Default iteration count to use with
+			/// generateKey(). RSA security recommends
+			/// an iteration count of at least 1000.
+	};
+
+	CipherKey(const std::string& name, 
+		const std::string& passphrase, 
+		const std::string& salt = "",
+		int iterationCount = DEFAULT_ITERATION_COUNT,
+		const std::string& digest = "md5");
+		/// Creates a new CipherKeyImpl object using the given
+		/// cipher name, passphrase, salt value, iteration count and digest.
+
+	CipherKey(const std::string& name, 
+		const ByteVec& key, 
+		const ByteVec& iv);
+		/// Creates a new CipherKeyImpl object using the given cipher
+		/// name, key and initialization vector (IV).
+		///
+		/// The size of the IV must match the cipher's expected
+		/// IV size (see ivSize()), except for GCM mode, which allows
+		/// a custom IV size.
+
+	CipherKey(const std::string& name);
+		/// Creates a new CipherKeyImpl object. Autoinitializes key and 
+		/// initialization vector.
+
+	~CipherKey();
+		/// Destroys the CipherKeyImpl.
+
+	const std::string& name() const;
+		/// Returns the name of the Cipher.
+
+	int keySize() const;
+		/// Returns the key size of the Cipher.
+
+	int blockSize() const;
+		/// Returns the block size of the Cipher.
+
+	int ivSize() const;
+		/// Returns the IV size of the Cipher.
+
+	Mode mode() const;
+		/// Returns the Cipher's mode of operation.
+	
+	const ByteVec& getKey() const;
+		/// Returns the key for the Cipher.
+
+	void setKey(const ByteVec& key);
+		/// Sets the key for the Cipher.
+
+	const ByteVec& getIV() const;
+		/// Returns the initialization vector (IV) for the Cipher.
+
+	void setIV(const ByteVec& iv);
+		/// Sets the initialization vector (IV) for the Cipher.
+		///
+		/// The size of the vector must match the cipher's expected
+		/// IV size (see ivSize()), except for GCM mode, which allows
+		/// a custom IV size.
+
+	CipherKeyImpl::Ptr impl();
+		/// Returns the impl object
+
+private:
+	CipherKeyImpl::Ptr _pImpl;
+};
+
+
+//
+// inlines
+//
+inline const std::string& CipherKey::name() const
+{
+	return _pImpl->name();
+}
+
+
+inline int CipherKey::keySize() const
+{
+	return _pImpl->keySize();
+}
+
+
+inline int CipherKey::blockSize() const
+{
+	return _pImpl->blockSize();
+}
+
+
+inline int CipherKey::ivSize() const
+{
+	return _pImpl->ivSize();
+}
+
+
+inline CipherKey::Mode CipherKey::mode() const
+{
+	return _pImpl->mode();
+}
+
+
+inline const CipherKey::ByteVec& CipherKey::getKey() const
+{
+	return _pImpl->getKey();
+}
+
+
+inline void CipherKey::setKey(const CipherKey::ByteVec& key)
+{
+	_pImpl->setKey(key);
+}
+
+
+inline const CipherKey::ByteVec& CipherKey::getIV() const
+{
+	return _pImpl->getIV();
+}
+
+
+inline void CipherKey::setIV(const CipherKey::ByteVec& iv)
+{
+	_pImpl->setIV(iv);
+}
+
+
+inline CipherKeyImpl::Ptr CipherKey::impl()
+{
+	return _pImpl;
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CipherKey_INCLUDED
diff --git a/Poco/Crypto/CipherKeyImpl.h b/Poco/Crypto/CipherKeyImpl.h
new file mode 100644
index 0000000..f7807aa
--- /dev/null
+++ b/Poco/Crypto/CipherKeyImpl.h
@@ -0,0 +1,168 @@
+//
+// CipherKeyImpl.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  CipherKeyImpl
+//
+// Definition of the CipherKeyImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CipherKeyImpl_INCLUDED
+#define Crypto_CipherKeyImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <vector>
+
+
+struct evp_cipher_st;
+typedef struct evp_cipher_st EVP_CIPHER;
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class CipherKeyImpl: public RefCountedObject
+	/// An implementation of the CipherKey class for OpenSSL's crypto library.
+{
+public:
+	typedef std::vector<unsigned char> ByteVec;
+	typedef Poco::AutoPtr<CipherKeyImpl> Ptr;
+
+	enum Mode
+		/// Cipher mode of operation. This mode determines how multiple blocks
+		/// are connected; this is essential to improve security.
+	{
+		MODE_STREAM_CIPHER,	/// Stream cipher
+		MODE_ECB,			/// Electronic codebook (plain concatenation)
+		MODE_CBC,			/// Cipher block chaining (default)
+		MODE_CFB,			/// Cipher feedback
+		MODE_OFB,			/// Output feedback
+		MODE_CTR,           /// Counter mode
+		MODE_GCM,           /// Galois/Counter mode
+		MODE_CCM            /// Counter with CBC-MAC
+	};
+
+	CipherKeyImpl(const std::string& name,
+		const std::string& passphrase,
+		const std::string& salt,
+		int iterationCount,
+		const std::string& digest);
+		/// Creates a new CipherKeyImpl object, using
+		/// the given cipher name, passphrase, salt value
+		/// and iteration count.
+
+	CipherKeyImpl(const std::string& name,
+		const ByteVec& key,
+		const ByteVec& iv);
+		/// Creates a new CipherKeyImpl object, using the
+		/// given cipher name, key and initialization vector.
+
+	CipherKeyImpl(const std::string& name);
+		/// Creates a new CipherKeyImpl object. Autoinitializes key
+		/// and initialization vector.
+
+	virtual ~CipherKeyImpl();
+		/// Destroys the CipherKeyImpl.
+
+	const std::string& name() const;
+		/// Returns the name of the Cipher.
+
+	int keySize() const;
+		/// Returns the key size of the Cipher.
+
+	int blockSize() const;
+		/// Returns the block size of the Cipher.
+
+	int ivSize() const;
+		/// Returns the IV size of the Cipher.
+
+	Mode mode() const;
+		/// Returns the Cipher's mode of operation.
+
+	const ByteVec& getKey() const;
+		/// Returns the key for the Cipher.
+
+	void setKey(const ByteVec& key);
+		/// Sets the key for the Cipher.
+
+	const ByteVec& getIV() const;
+		/// Returns the initialization vector (IV) for the Cipher.
+
+	void setIV(const ByteVec& iv);
+		/// Sets the initialization vector (IV) for the Cipher.
+
+	const EVP_CIPHER* cipher();
+		/// Returns the cipher object
+
+private:
+	void generateKey(const std::string& passphrase,
+		const std::string& salt,
+		int iterationCount);
+	 	/// Generates key and IV from a password and optional salt string.
+
+	void generateKey();
+		/// Generates key and IV from random data.
+
+	void getRandomBytes(ByteVec& vec, std::size_t count);
+		/// Stores random bytes in vec.
+
+private:
+	const EVP_CIPHER*  _pCipher;
+	const EVP_MD*      _pDigest;
+	std::string	       _name;
+	ByteVec		       _key;
+	ByteVec		       _iv;
+	OpenSSLInitializer _openSSLInitializer;
+};
+
+
+//
+// Inlines
+//
+inline const std::string& CipherKeyImpl::name() const
+{
+	return _name;
+}
+
+
+inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getKey() const
+{
+	return _key;
+}
+
+
+inline void CipherKeyImpl::setKey(const ByteVec& key)
+{
+	poco_assert(key.size() == static_cast<ByteVec::size_type>(keySize()));
+	_key = key;
+}
+
+
+inline const CipherKeyImpl::ByteVec& CipherKeyImpl::getIV() const
+{
+	return _iv;
+}
+
+
+inline const EVP_CIPHER* CipherKeyImpl::cipher()
+{
+	return _pCipher;
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CipherKeyImpl_INCLUDED
diff --git a/Poco/Crypto/Crypto.h b/Poco/Crypto/Crypto.h
new file mode 100644
index 0000000..e87a25d
--- /dev/null
+++ b/Poco/Crypto/Crypto.h
@@ -0,0 +1,185 @@
+//
+// Crypto.h
+//
+// Library: Crypto
+// Package: CryptoCore
+// Module:  Crypto
+//
+// Basic definitions for the Poco Crypto library.
+// This file must be the first file included by every other Crypto
+// header file.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_Crypto_INCLUDED
+#define Crypto_Crypto_INCLUDED
+
+
+#define POCO_EXTERNAL_OPENSSL_DEFAULT 1
+#define POCO_EXTERNAL_OPENSSL_SLPRO 2
+
+
+#include "Poco/Foundation.h"
+#include <openssl/opensslv.h>
+
+
+#ifndef OPENSSL_VERSION_PREREQ
+#define OPENSSL_VERSION_PREREQ(maj, min) \
+	((OPENSSL_VERSION_MAJOR << 16) + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))
+#endif
+
+
+enum RSAPaddingMode
+	/// The padding mode used for RSA public key encryption.
+{
+	RSA_PADDING_PKCS1,
+		/// PKCS #1 v1.5 padding. This currently is the most widely used mode. 
+		
+	RSA_PADDING_PKCS1_OAEP,
+		/// EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty 
+		/// encoding parameter. This mode is recommended for all new applications.
+		
+	RSA_PADDING_SSLV23,
+		/// PKCS #1 v1.5 padding with an SSL-specific modification that denotes 
+		/// that the server is SSL3 capable. 
+		
+	RSA_PADDING_NONE
+		/// Raw RSA encryption. This mode should only be used to implement cryptographically 
+		/// sound padding modes in the application code. Encrypting user data directly with RSA 
+		/// is insecure. 
+};
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Crypto_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Crypto_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32)
+	#if defined(POCO_DLL)
+		#if defined(Crypto_EXPORTS)
+			#define Crypto_API __declspec(dllexport)
+		#else
+			#define Crypto_API __declspec(dllimport)
+		#endif
+	#endif
+#endif
+
+
+#if !defined(Crypto_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Crypto_API __attribute__ ((visibility ("default")))
+	#else
+		#define Crypto_API
+	#endif
+#endif
+
+
+//
+// Automatically link Crypto and OpenSSL libraries.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS)
+		#if defined(POCO_INTERNAL_OPENSSL_MSVC_VER)
+			#if defined(POCO_EXTERNAL_OPENSSL)
+				#pragma message("External OpenSSL defined but internal headers used - possible mismatch!")
+			#endif // POCO_EXTERNAL_OPENSSL
+			#if !defined(_DEBUG)
+				#define POCO_DEBUG_SUFFIX ""
+				#if !defined (_DLL)
+					#define POCO_STATIC_SUFFIX "mt"
+				#else // _DLL
+					#define POCO_STATIC_SUFFIX ""
+				#endif
+			#else // _DEBUG
+				#define POCO_DEBUG_SUFFIX "d"
+				#if !defined (_DLL)
+					#define POCO_STATIC_SUFFIX "mt"
+				#else // _DLL
+					#define POCO_STATIC_SUFFIX ""
+				#endif
+			#endif
+			#pragma comment(lib, "libcrypto" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
+			#pragma comment(lib, "libssl" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
+			#if !defined(_WIN64) && !defined (_DLL) && \
+						(POCO_INTERNAL_OPENSSL_MSVC_VER == 120) && \
+						(POCO_MSVC_VERSION < POCO_INTERNAL_OPENSSL_MSVC_VER)
+				#pragma comment(lib, "libPreVS2013CRT" POCO_STATIC_SUFFIX POCO_DEBUG_SUFFIX ".lib")
+			#endif
+			#if !defined (_DLL) && (POCO_MSVS_VERSION >= 2015)
+				#pragma comment(lib, "legacy_stdio_definitions.lib")
+				#pragma comment(lib, "legacy_stdio_wide_specifiers.lib")
+			#endif
+		#elif defined(POCO_EXTERNAL_OPENSSL)
+			#if POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_SLPRO
+				#if defined(POCO_DLL)
+					#if OPENSSL_VERSION_PREREQ(1,1)
+						#pragma comment(lib, "libcrypto.lib")
+						#pragma comment(lib, "libssl.lib")
+					#else
+						#pragma comment(lib, "libeay32.lib")
+						#pragma comment(lib, "ssleay32.lib")
+					#endif
+			  	#else
+					#if OPENSSL_VERSION_PREREQ(1,1)
+						#pragma comment(lib, "libcrypto" POCO_LIB_SUFFIX)
+						#pragma comment(lib, "libssl" POCO_LIB_SUFFIX)
+					#else
+						#pragma comment(lib, "libeay32" POCO_LIB_SUFFIX)
+						#pragma comment(lib, "ssleay32" POCO_LIB_SUFFIX)
+					#endif
+				#endif
+			#elif POCO_EXTERNAL_OPENSSL == POCO_EXTERNAL_OPENSSL_DEFAULT
+				#if OPENSSL_VERSION_PREREQ(1,1)
+					#pragma comment(lib, "libcrypto.lib")
+					#pragma comment(lib, "libssl.lib")
+				#else
+					#pragma comment(lib, "libeay32.lib")
+					#pragma comment(lib, "ssleay32.lib")
+				#endif
+			#endif
+		#endif // POCO_INTERNAL_OPENSSL_MSVC_VER
+		#if !defined(Crypto_EXPORTS)
+			#pragma comment(lib, "PocoCrypto" POCO_LIB_SUFFIX)
+		#endif
+	#endif // POCO_NO_AUTOMATIC_LIBS
+#endif
+
+
+namespace Poco {
+namespace Crypto {
+
+
+void Crypto_API initializeCrypto();
+	/// Initialize the Crypto library, as well as the underlying OpenSSL
+	/// libraries, by calling OpenSSLInitializer::initialize().
+	///
+	/// Should be called before using any class from the Crypto library.
+	/// The Crypto library will be initialized automatically, through
+	/// OpenSSLInitializer instances held by various Crypto classes
+	/// (Cipher, CipherKey, RSAKey, X509Certificate).
+	/// However, it is recommended to call initializeCrypto()
+	/// in any case at application startup.
+	///
+	/// Can be called multiple times; however, for every call to
+	/// initializeCrypto(), a matching call to uninitializeCrypto()
+	/// must be performed.
+
+
+void Crypto_API uninitializeCrypto();
+	/// Uninitializes the Crypto library by calling
+	/// OpenSSLInitializer::uninitialize().
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_Crypto_INCLUDED
diff --git a/Poco/Crypto/CryptoException.h b/Poco/Crypto/CryptoException.h
new file mode 100644
index 0000000..34c1511
--- /dev/null
+++ b/Poco/Crypto/CryptoException.h
@@ -0,0 +1,56 @@
+//
+// CryptoException.h
+//
+//
+// Library: Crypto
+// Package: Crypto
+// Module:  CryptoException
+//
+// Definition of the CryptoException class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CryptoException_INCLUDED
+#define Crypto_CryptoException_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+POCO_DECLARE_EXCEPTION(Crypto_API, CryptoException, Poco::Exception)
+
+
+class Crypto_API OpenSSLException : public CryptoException
+{
+public:
+	OpenSSLException(int code = 0);
+	OpenSSLException(const std::string& msg, int code = 0);
+	OpenSSLException(const std::string& msg, const std::string& arg, int code = 0);
+	OpenSSLException(const std::string& msg, const Poco::Exception& exc, int code = 0);
+	OpenSSLException(const OpenSSLException& exc);
+	~OpenSSLException() throw();
+	OpenSSLException& operator = (const OpenSSLException& exc);
+	const char* name() const throw();
+	const char* className() const throw();
+	Poco::Exception* clone() const;
+	void rethrow() const;
+
+private:
+	void setExtMessage();
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CryptoException_INCLUDED
diff --git a/Poco/Crypto/CryptoStream.h b/Poco/Crypto/CryptoStream.h
new file mode 100644
index 0000000..25a99a4
--- /dev/null
+++ b/Poco/Crypto/CryptoStream.h
@@ -0,0 +1,192 @@
+//
+// CryptoStream.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  CryptoStream
+//
+// Definition of the CryptoStreamBuf, CryptoInputStream and CryptoOutputStream
+// classes.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CryptoStream_INCLUDED
+#define Crypto_CryptoStream_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/BufferedStreamBuf.h"
+#include "Poco/Buffer.h"
+#include <iostream>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class CryptoTransform;
+class Cipher;
+
+
+class Crypto_API CryptoStreamBuf: public Poco::BufferedStreamBuf
+	/// This stream buffer performs cryptographic transformation on the data
+	/// going through it.
+{
+public:
+	CryptoStreamBuf(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
+	CryptoStreamBuf(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
+
+	virtual ~CryptoStreamBuf();
+
+	void close();
+		/// Flushes all buffers and finishes the encryption.
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	CryptoTransform* _pTransform;
+	std::istream*	 _pIstr;
+	std::ostream*	 _pOstr;
+	bool			 _eof;
+
+	Poco::Buffer<unsigned char> _buffer;
+
+	CryptoStreamBuf(const CryptoStreamBuf&);
+	CryptoStreamBuf& operator = (const CryptoStreamBuf&);
+};
+
+
+class Crypto_API CryptoIOS: public virtual std::ios
+	/// The base class for CryptoInputStream and CryptoOutputStream.
+	///
+	/// This class is needed to ensure correct initialization order of the
+	/// stream buffer and base classes.
+{
+public:
+	CryptoIOS(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
+	CryptoIOS(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
+	~CryptoIOS();
+	CryptoStreamBuf* rdbuf();
+
+protected:
+	CryptoStreamBuf _buf;
+};
+
+
+class Crypto_API CryptoInputStream: public CryptoIOS, public std::istream
+	/// This stream transforms all data passing through it using the given
+	/// CryptoTransform.
+	///
+	/// Use a CryptoTransform object provided by Cipher::createEncrytor() or
+	/// Cipher::createDecryptor() to create an encrypting or decrypting stream,
+	/// respectively.
+{
+public:
+	CryptoInputStream(std::istream& istr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
+		/// Create a new CryptoInputStream object. The CryptoInputStream takes the
+		/// ownership of the given CryptoTransform object.
+
+	CryptoInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192);
+		/// Create a new encrypting CryptoInputStream object using the given cipher.
+
+	~CryptoInputStream();
+		/// Destroys the CryptoInputStream.
+};
+
+
+class Crypto_API CryptoOutputStream: public CryptoIOS, public std::ostream
+	/// This stream transforms all data passing through it using the given
+	/// CryptoTransform.
+	///
+	/// Use a CryptoTransform object provided by Cipher::createEncrytor() or
+	/// Cipher::createDecryptor() to create an encrypting or decrypting stream,
+	/// respectively.
+	///
+	/// After all data has been passed through the stream, close() must be called
+	/// to ensure completion of cryptographic transformation.
+{
+public:
+	CryptoOutputStream(std::ostream& ostr, CryptoTransform* pTransform, std::streamsize bufferSize = 8192);
+		/// Create a new CryptoOutputStream object. The CryptoOutputStream takes the
+		/// ownership of the given CryptoTransform object.
+
+	CryptoOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192);
+		/// Create a new decrypting CryptoOutputStream object using the given cipher.
+
+	~CryptoOutputStream();
+		/// Destroys the CryptoOutputStream.
+
+	void close();
+		/// Flushes all buffers and finishes the encryption.
+};
+
+
+class Crypto_API DecryptingInputStream: public CryptoIOS, public std::istream
+	/// This stream decrypts all data passing through it using the given
+	/// Cipher.
+{
+public:
+	DecryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192);
+		/// Create a new DecryptingInputStream object using the given cipher.
+
+	~DecryptingInputStream();
+		/// Destroys the DecryptingInputStream.
+};
+
+
+class Crypto_API DecryptingOutputStream: public CryptoIOS, public std::ostream
+	/// This stream decrypts all data passing through it using the given
+	/// Cipher.
+{
+public:
+	DecryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192);
+		/// Create a new DecryptingOutputStream object using the given cipher.
+
+	~DecryptingOutputStream();
+		/// Destroys the DecryptingOutputStream.
+
+	void close();
+		/// Flushes all buffers and finishes the decryption.
+};
+
+
+class Crypto_API EncryptingInputStream: public CryptoIOS, public std::istream
+	/// This stream encrypts all data passing through it using the given
+	/// Cipher.
+{
+public:
+	EncryptingInputStream(std::istream& istr, Cipher& cipher, std::streamsize bufferSize = 8192);
+		/// Create a new EncryptingInputStream object using the given cipher.
+
+	~EncryptingInputStream();
+		/// Destroys the EncryptingInputStream.
+};
+
+
+class Crypto_API EncryptingOutputStream: public CryptoIOS, public std::ostream
+	/// This stream encrypts all data passing through it using the given
+	/// Cipher.
+{
+public:
+	EncryptingOutputStream(std::ostream& ostr, Cipher& cipher, std::streamsize bufferSize = 8192);
+		/// Create a new EncryptingOutputStream object using the given cipher.
+
+	~EncryptingOutputStream();
+		/// Destroys the EncryptingOutputStream.
+
+	void close();
+		/// Flushes all buffers and finishes the encryption.
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CryptoStream_INCLUDED
diff --git a/Poco/Crypto/CryptoTransform.h b/Poco/Crypto/CryptoTransform.h
new file mode 100644
index 0000000..9fa3806
--- /dev/null
+++ b/Poco/Crypto/CryptoTransform.h
@@ -0,0 +1,87 @@
+//
+// CryptoTransform.h
+//
+// Library: Crypto
+// Package: Cipher
+// Module:  CryptoTransform
+//
+// Definition of the CryptoTransform class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_CryptoTransform_INCLUDED
+#define Crypto_CryptoTransform_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include <ios>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API CryptoTransform
+	/// This interface represents the basic operations for cryptographic
+	/// transformations to be used with a CryptoInputStream or a
+	/// CryptoOutputStream.
+	///
+	/// Implementations of this class are returned by the Cipher class to
+	/// perform encryption or decryption of data.
+{
+public:
+	CryptoTransform();
+		/// Creates a new CryptoTransform object.
+
+	virtual ~CryptoTransform();
+		/// Destroys the CryptoTransform.
+
+	virtual std::size_t blockSize() const = 0;
+		/// Returns the block size for this CryptoTransform.
+
+	virtual int setPadding(int padding);
+		/// Enables or disables padding. By default encryption operations are padded using standard block
+		/// padding and the padding is checked and removed when decrypting. If the padding parameter is zero then
+		/// no padding is performed, the total amount of data encrypted or decrypted must then be a multiple of
+		/// the block size or an error will occur.
+
+	virtual std::string getTag(std::size_t tagSize = 16) = 0;
+		/// Returns the GCM tag after encrypting using GCM mode.
+		///
+		/// Must be called after finalize().
+
+	virtual void setTag(const std::string& tag) = 0;
+		/// Sets the GCM tag for authenticated decryption using GCM mode.
+		///
+		/// Must be set before finalize() is called, otherwise
+		/// decryption will fail.
+
+	virtual std::streamsize transform(
+		const unsigned char* input,
+		std::streamsize		 inputLength,
+		unsigned char*		 output,
+		std::streamsize		 outputLength) = 0;
+		/// Transforms a chunk of data. The inputLength is arbitrary and does not
+		/// need to be a multiple of the block size. The output buffer has a maximum
+		/// capacity of the given outputLength that must be at least
+		///   inputLength + blockSize() - 1
+		/// Returns the number of bytes written to the output buffer.
+
+	virtual std::streamsize finalize(unsigned char* output, std::streamsize length) = 0;
+		/// Finalizes the transformation. The output buffer must contain enough
+		/// space for at least two blocks, ie.
+		///   length >= 2*blockSize()
+		/// must be true.  Returns the number of bytes written to the output
+		/// buffer.
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_CryptoTransform_INCLUDED
diff --git a/Poco/Crypto/DigestEngine.h b/Poco/Crypto/DigestEngine.h
new file mode 100644
index 0000000..8244a6e
--- /dev/null
+++ b/Poco/Crypto/DigestEngine.h
@@ -0,0 +1,80 @@
+//
+// DigestEngine.h
+//
+// Library: Crypto
+// Package: Digest
+// Module:  DigestEngine
+//
+// Definition of the DigestEngine class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_DigestEngine_INCLUDED
+#define Crypto_DigestEngine_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/DigestEngine.h"
+#include <openssl/evp.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API DigestEngine: public Poco::DigestEngine
+	/// This class implements a Poco::DigestEngine for all
+	/// digest algorithms supported by OpenSSL.
+{
+public:
+	DigestEngine(const std::string& name);
+		/// Creates a DigestEngine using the digest with the given name
+		/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
+		/// See the OpenSSL documentation for a list of supported digest algorithms.
+		///
+		/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
+		
+	~DigestEngine();
+		/// Destroys the DigestEngine.
+	
+	const std::string& algorithm() const;
+		/// Returns the name of the digest algorithm.
+	
+	int nid() const;
+		/// Returns the NID (OpenSSL object identifier) of the digest algorithm.
+
+	// DigestEngine
+	std::size_t digestLength() const;
+	void reset();
+	const Poco::DigestEngine::Digest& digest();
+
+protected:
+	void updateImpl(const void* data, std::size_t length);
+	
+private:
+	std::string _name;
+	EVP_MD_CTX* _pContext;
+	Poco::DigestEngine::Digest _digest;
+	OpenSSLInitializer _openSSLInitializer;
+};
+
+
+//
+// inlines
+//
+inline const std::string& DigestEngine::algorithm() const
+{
+	return _name;
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_DigestEngine_INCLUDED
diff --git a/Poco/Crypto/ECDSADigestEngine.h b/Poco/Crypto/ECDSADigestEngine.h
new file mode 100644
index 0000000..ed6fab4
--- /dev/null
+++ b/Poco/Crypto/ECDSADigestEngine.h
@@ -0,0 +1,101 @@
+//
+// ECDSADigestEngine.h
+//
+//
+// Library: Crypto
+// Package: ECDSA
+// Module:  ECDSADigestEngine
+//
+// Definition of the ECDSADigestEngine class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_ECDSADigestEngine_INCLUDED
+#define Crypto_ECDSADigestEngine_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/ECKey.h"
+#include "Poco/DigestEngine.h"
+#include "Poco/Crypto/DigestEngine.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API ECDSADigestEngine: public Poco::DigestEngine
+	/// This class implements a Poco::DigestEngine that can be
+	/// used to compute a secure digital signature.
+	///
+	/// First another Poco::Crypto::DigestEngine is created and
+	/// used to compute a cryptographic hash of the data to be
+	/// signed. Then, the hash value is encrypted, using
+	/// the ECDSA private key.
+	///
+	/// To verify a signature, pass it to the verify() 
+	/// member function. It will decrypt the signature
+	/// using the ECDSA public key and compare the resulting
+	/// hash with the actual hash of the data.
+{
+public:
+
+	ECDSADigestEngine(const ECKey& key, const std::string &name);
+		/// Creates the ECDSADigestEngine with the given ECDSA key,
+		/// using the hash algorithm with the given name
+		/// (e.g., "SHA1", "SHA256", "SHA512", etc.).
+		/// See the OpenSSL documentation for a list of supported digest algorithms.
+		///
+		/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
+
+	~ECDSADigestEngine();
+		/// Destroys the ECDSADigestEngine.
+
+	std::size_t digestLength() const;
+		/// Returns the length of the digest in bytes.
+
+	void reset();
+		/// Resets the engine so that a new
+		/// digest can be computed.
+		
+	const DigestEngine::Digest& digest();
+		/// Finishes the computation of the digest 
+		/// (the first time it's called) and
+		/// returns the message digest. 
+		///
+		/// Can be called multiple times.
+
+	const DigestEngine::Digest& signature();
+		/// Signs the digest using the ECDSADSA algorithm
+		/// and the private key (the first time it's
+		/// called) and returns the result.
+		///
+		/// Can be called multiple times.
+
+	bool verify(const DigestEngine::Digest& signature);
+		/// Verifies the data against the signature.
+		///
+		/// Returns true if the signature can be verified, false otherwise.
+
+protected:
+	void updateImpl(const void* data, std::size_t length);
+
+private:
+	ECKey _key;
+	Poco::Crypto::DigestEngine _engine;
+	Poco::DigestEngine::Digest _digest;
+	Poco::DigestEngine::Digest _signature;
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_ECDSADigestEngine_INCLUDED
diff --git a/Poco/Crypto/ECKey.h b/Poco/Crypto/ECKey.h
new file mode 100644
index 0000000..14f2ac0
--- /dev/null
+++ b/Poco/Crypto/ECKey.h
@@ -0,0 +1,136 @@
+//
+// ECKey.h
+//
+//
+// Library: Crypto
+// Package: EC
+// Module:  ECKey
+//
+// Definition of the ECKey class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_ECKey_INCLUDED
+#define Crypto_ECKey_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/KeyPair.h"
+#include "Poco/Crypto/ECKeyImpl.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class X509Certificate;
+class PKCS12Container;
+
+
+class Crypto_API ECKey : public KeyPair
+	/// This class stores an EC key pair, consisting
+	/// of private and public key. Storage of the private
+	/// key is optional.
+	///
+	/// If a private key is available, the ECKey can be
+	/// used for decrypting data (encrypted with the public key)
+	/// or computing secure digital signatures.
+{
+public:
+	ECKey(const EVPPKey& key);
+		/// Constructs ECKeyImpl by extracting the EC key.
+
+	ECKey(const X509Certificate& cert);
+		/// Extracts the EC public key from the given certificate.
+
+	ECKey(const PKCS12Container& cert);
+		/// Extracts the EC private key from the given certificate.
+
+	ECKey(const std::string& eccGroup);
+		/// Creates the ECKey. Creates a new public/private keypair using the given parameters.
+		/// Can be used to sign data and verify signatures.
+
+	ECKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = "");
+		/// Creates the ECKey, by reading public and private key from the given files and
+		/// using the given passphrase for the private key.
+		///
+		/// Cannot be used for signing or decryption unless a private key is available.
+		///
+		/// If a private key is specified, you don't need to specify a public key file.
+		/// OpenSSL will auto-create the public key from the private key.
+
+	ECKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "");
+		/// Creates the ECKey, by reading public and private key from the given streams and
+		/// using the given passphrase for the private key.
+		///
+		/// Cannot be used for signing or decryption unless a private key is available.
+		///
+		/// If a private key is specified, you don't need to specify a public key file.
+		/// OpenSSL will auto-create the public key from the private key.
+
+	~ECKey();
+		/// Destroys the ECKey.
+
+	ECKeyImpl::Ptr impl() const;
+		/// Returns the impl object.
+
+	static std::string getCurveName(int nid = -1);
+		/// Returns elliptical curve name corresponding to
+		/// the given nid; if nid is not found, returns
+		/// empty string.
+		///
+		/// If nid is -1, returns first curve name.
+		///
+		/// If no curves are found, returns empty string;
+
+	static int getCurveNID(std::string& name);
+		/// Returns the NID of the specified curve.
+		///
+		/// If name is empty, returns the first curve NID
+		/// and updates the name accordingly.
+
+	static bool hasCurve(const std::string& name);
+		/// Returns true if the named curve is found,
+		/// false otherwise.
+
+private:
+	ECKeyImpl::Ptr _pImpl;
+};
+
+
+//
+// inlines
+//
+inline ECKeyImpl::Ptr ECKey::impl() const
+{
+	return _pImpl;
+}
+
+
+inline std::string ECKey::getCurveName(int nid)
+{
+	return ECKeyImpl::getCurveName(nid);
+}
+
+
+inline int ECKey::getCurveNID(std::string& name)
+{
+	return ECKeyImpl::getCurveNID(name);
+}
+
+
+inline bool ECKey::hasCurve(const std::string& name)
+{
+	return ECKeyImpl::hasCurve(name);
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_ECKey_INCLUDED
diff --git a/Poco/Crypto/ECKeyImpl.h b/Poco/Crypto/ECKeyImpl.h
new file mode 100644
index 0000000..8407643
--- /dev/null
+++ b/Poco/Crypto/ECKeyImpl.h
@@ -0,0 +1,174 @@
+//
+// ECKeyImpl.h
+//
+//
+// Library: Crypto
+// Package: EC
+// Module:  ECKeyImpl
+//
+// Definition of the ECKeyImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_ECKeyImplImpl_INCLUDED
+#define Crypto_ECKeyImplImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/EVPPKey.h"
+#include "Poco/Crypto/KeyPairImpl.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <istream>
+#include <ostream>
+#include <vector>
+#include <openssl/objects.h>
+#include <openssl/ec.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class X509Certificate;
+class PKCS12Container;
+
+
+class ECKeyImpl: public KeyPairImpl
+	/// Elliptic Curve key clas implementation.
+{
+public:
+	typedef Poco::AutoPtr<ECKeyImpl> Ptr;
+	typedef std::vector<unsigned char> ByteVec;
+
+	ECKeyImpl(const EVPPKey& key);
+		/// Constructs ECKeyImpl by extracting the EC key.
+
+	ECKeyImpl(const X509Certificate& cert);
+		/// Constructs ECKeyImpl by extracting the EC public key from the given certificate.
+
+	ECKeyImpl(const PKCS12Container& cert);
+		/// Constructs ECKeyImpl by extracting the EC private key from the given certificate.
+
+	ECKeyImpl(int eccGroup);
+		/// Creates the ECKey of the specified group. Creates a new public/private keypair using the given parameters.
+		/// Can be used to sign data and verify signatures.
+
+	ECKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase);
+		/// Creates the ECKey, by reading public and private key from the given files and
+		/// using the given passphrase for the private key. Can only by used for signing if 
+		/// a private key is available. 
+
+	ECKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase);
+		/// Creates the ECKey. Can only by used for signing if pPrivKey
+		/// is not null. If a private key file is specified, you don't need to
+		/// specify a public key file. OpenSSL will auto-create it from the private key.
+
+	~ECKeyImpl();
+		/// Destroys the ECKeyImpl.
+
+	EC_KEY* getECKey();
+		/// Returns the OpenSSL EC key.
+
+	const EC_KEY* getECKey() const;
+		/// Returns the OpenSSL EC key.
+
+	int size() const;
+		/// Returns the EC key length in bits.
+
+	int groupId() const;
+		/// Returns the EC key group integer Id.
+
+	std::string groupName() const;
+		/// Returns the EC key group name.
+
+	void save(const std::string& publicKeyFile,
+		const std::string& privateKeyFile = "",
+		const std::string& privateKeyPassphrase = "") const;
+		/// Exports the public and private keys to the given files. 
+		///
+		/// If an empty filename is specified, the corresponding key
+		/// is not exported.
+
+	void save(std::ostream* pPublicKeyStream,
+		std::ostream* pPrivateKeyStream = 0,
+		const std::string& privateKeyPassphrase = "") const;
+		/// Exports the public and private key to the given streams.
+		///
+		/// If a null pointer is passed for a stream, the corresponding
+		/// key is not exported.
+
+	static std::string getCurveName(int nid = -1);
+		/// Returns elliptical curve name corresponding to
+		/// the given nid; if nid is not found, returns
+		/// empty string.
+		///
+		/// If nid is -1, returns first curve name.
+		///
+		/// If no curves are found, returns empty string;
+
+	static int getCurveNID(std::string& name);
+		/// Returns the NID of the specified curve.
+		///
+		/// If name is empty, returns the first curve NID
+		/// and updates the name accordingly.
+
+	static bool hasCurve(const std::string& name);
+		/// Returns true if the named curve is found,
+		/// false otherwise.
+
+private:
+	void checkEC(const std::string& method, const std::string& func) const;
+	void freeEC();
+
+	EC_KEY* _pEC;
+};
+
+
+//
+// inlines
+//
+inline EC_KEY* ECKeyImpl::getECKey()
+{
+	return _pEC;
+}
+
+
+inline const EC_KEY* ECKeyImpl::getECKey() const
+{
+	return _pEC;
+}
+
+
+inline std::string ECKeyImpl::groupName() const
+{
+	return OBJ_nid2sn(groupId());
+}
+
+
+inline void ECKeyImpl::save(const std::string& publicKeyFile,
+	const std::string& privateKeyFile,
+	const std::string& privateKeyPassphrase) const
+{
+	EVPPKey(_pEC).save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
+}
+
+
+inline void ECKeyImpl::save(std::ostream* pPublicKeyStream,
+	std::ostream* pPrivateKeyStream,
+	const std::string& privateKeyPassphrase) const
+{
+	EVPPKey(_pEC).save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_ECKeyImplImpl_INCLUDED
diff --git a/Poco/Crypto/EVPPKey.h b/Poco/Crypto/EVPPKey.h
new file mode 100644
index 0000000..fbcdad5
--- /dev/null
+++ b/Poco/Crypto/EVPPKey.h
@@ -0,0 +1,354 @@
+//
+// EVPPKey.h
+//
+//
+// Library: Crypto
+// Package: CryptoCore
+// Module:  EVPPKey
+//
+// Definition of the EVPPKey class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_EVPPKeyImpl_INCLUDED
+#define Crypto_EVPPKeyImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/CryptoException.h"
+#include "Poco/StreamCopier.h"
+#include <openssl/ec.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <sstream>
+#include <typeinfo>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class ECKey;
+class RSAKey;
+
+
+class Crypto_API EVPPKey
+	/// Utility class for conversion of native keys to EVP.
+	/// Currently, only RSA and EC keys are supported.
+{
+public:
+	explicit EVPPKey(const std::string& ecCurveName);
+		/// Constructs EVPPKey from ECC curve name.
+		///
+		/// Only EC keys can be wrapped by an EVPPKey
+		/// created using this constructor.
+
+	explicit EVPPKey(const char* ecCurveName);
+		/// Constructs EVPPKey from ECC curve name.
+		///
+		/// Only EC keys can be wrapped by an EVPPKey
+		/// created using this constructor.
+
+	explicit EVPPKey(EVP_PKEY* pEVPPKey);
+		/// Constructs EVPPKey from EVP_PKEY pointer.
+		/// The content behind the supplied pointer is internally duplicated.
+
+	template<typename K>
+	explicit EVPPKey(K* pKey): _pEVPPKey(EVP_PKEY_new())
+		/// Constructs EVPPKey from a "native" OpenSSL (RSA or EC_KEY),
+		/// or a Poco wrapper (RSAKey, ECKey) key pointer.
+	{
+		if (!_pEVPPKey) throw OpenSSLException();
+		setKey(pKey);
+	}
+
+	EVPPKey(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase = "");
+		/// Creates the EVPPKey, by reading public and private key from the given files and
+		/// using the given passphrase for the private key. Can only by used for signing if
+		/// a private key is available.
+
+	EVPPKey(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase = "");
+		/// Creates the EVPPKey. Can only by used for signing if pPrivKey
+		/// is not null. If a private key file is specified, you don't need to
+		/// specify a public key file. OpenSSL will auto-create it from the private key.
+
+	EVPPKey(const EVPPKey& other);
+		/// Copy constructor.
+
+	EVPPKey& operator=(const EVPPKey& other);
+		/// Assignment operator.
+
+#ifdef POCO_ENABLE_CPP11
+
+	EVPPKey(EVPPKey&& other);
+		/// Move constructor.
+
+	EVPPKey& operator=(EVPPKey&& other);
+		/// Assignment move operator.
+
+#endif // POCO_ENABLE_CPP11
+
+	~EVPPKey();
+		/// Destroys the EVPPKey.
+
+	bool operator == (const EVPPKey& other) const;
+		/// Comparison operator.
+		/// Returns true if public key components and parameters
+		/// of the other key are equal to this key.
+		///
+		/// Works as expected when one key contains only public key,
+		/// while the other one contains private (thus also public) key.
+
+	bool operator != (const EVPPKey& other) const;
+		/// Comparison operator.
+		/// Returns true if public key components and parameters
+		/// of the other key are different from this key.
+		///
+		/// Works as expected when one key contains only public key,
+		/// while the other one contains private (thus also public) key.
+
+	void save(const std::string& publicKeyFile, const std::string& privateKeyFile = "", const std::string& privateKeyPassphrase = "") const;
+		/// Exports the public and/or private keys to the given files.
+		///
+		/// If an empty filename is specified, the corresponding key
+		/// is not exported.
+
+	void save(std::ostream* pPublicKeyStream, std::ostream* pPrivateKeyStream = 0, const std::string& privateKeyPassphrase = "") const;
+		/// Exports the public and/or private key to the given streams.
+		///
+		/// If a null pointer is passed for a stream, the corresponding
+		/// key is not exported.
+
+	int type() const;
+		/// Retuns the EVPPKey type NID.
+
+	bool isSupported(int type) const;
+		/// Returns true if OpenSSL type is supported
+
+	operator const EVP_PKEY*() const;
+		/// Returns const pointer to the OpenSSL EVP_PKEY structure.
+
+	operator EVP_PKEY*();
+		/// Returns pointer to the OpenSSL EVP_PKEY structure.
+
+	static EVP_PKEY* duplicate(const EVP_PKEY* pFromKey, EVP_PKEY** pToKey);
+		/// Duplicates pFromKey into *pToKey and returns
+		// the pointer to duplicated EVP_PKEY.
+
+private:
+	EVPPKey();
+
+	static int type(const EVP_PKEY* pEVPPKey);
+	void newECKey(const char* group);
+	void duplicate(EVP_PKEY* pEVPPKey);
+
+	void setKey(ECKey* pKey);
+	void setKey(RSAKey* pKey);
+	void setKey(EC_KEY* pKey);
+	void setKey(RSA* pKey);
+	static int passCB(char* buf, int size, int, void* pass);
+
+	typedef EVP_PKEY* (*PEM_read_FILE_Key_fn)(FILE*, EVP_PKEY**, pem_password_cb*, void*);
+	typedef EVP_PKEY* (*PEM_read_BIO_Key_fn)(BIO*, EVP_PKEY**, pem_password_cb*, void*);
+	typedef void* (*EVP_PKEY_get_Key_fn)(EVP_PKEY*);
+
+	// The following load*() functions are used by both native and EVP_PKEY type key
+	// loading from BIO/FILE.
+	// When used for EVP key loading, getFunc is null (ie. native key is not extracted
+	// from the loaded EVP_PKEY).
+	template <typename K, typename F>
+	static bool loadKey(K** ppKey,
+		PEM_read_FILE_Key_fn readFunc,
+		F getFunc,
+		const std::string& keyFile,
+		const std::string& pass = "")
+	{
+		poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) ||
+						((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc));
+		poco_check_ptr (ppKey);
+		poco_assert_dbg (!*ppKey);
+
+		FILE* pFile = 0;
+		if (!keyFile.empty())
+		{
+			if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
+			EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
+			if (pKey)
+			{
+				pFile = fopen(keyFile.c_str(), "r");
+				if (pFile)
+				{
+					pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB;
+					void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str();
+					if (readFunc(pFile, &pKey, pCB, pPassword))
+					{
+						fclose(pFile); pFile = 0;
+						if(getFunc)
+						{
+							*ppKey = (K*)getFunc(pKey);
+							EVP_PKEY_free(pKey);
+						}
+						else
+						{
+							poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
+							*ppKey = (K*)pKey;
+						}
+						if(!*ppKey) goto error;
+						return true;
+					}
+					goto error;
+				}
+				else
+				{
+					if (getFunc) EVP_PKEY_free(pKey);
+					throw IOException("ECKeyImpl, cannot open file", keyFile);
+				}
+			}
+			else goto error;
+		}
+		return false;
+
+	error:
+		if (pFile) fclose(pFile);
+		throw OpenSSLException("EVPKey::loadKey(string)");
+	}
+
+	template <typename K, typename F>
+	static bool loadKey(K** ppKey,
+		PEM_read_BIO_Key_fn readFunc,
+		F getFunc,
+		std::istream* pIstr,
+		const std::string& pass = "")
+	{
+		poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) ||
+						((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc));
+		poco_check_ptr(ppKey);
+		poco_assert_dbg(!*ppKey);
+
+		BIO* pBIO = 0;
+		if (pIstr)
+		{
+			std::ostringstream ostr;
+			Poco::StreamCopier::copyStream(*pIstr, ostr);
+			std::string key = ostr.str();
+			pBIO = BIO_new_mem_buf(const_cast<char*>(key.data()), static_cast<int>(key.size()));
+			if (pBIO)
+			{
+				if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
+				EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
+				if (pKey)
+				{
+					pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB;
+					void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str();
+					if (readFunc(pBIO, &pKey, pCB, pPassword))
+					{
+						BIO_free(pBIO); pBIO = 0;
+						if (getFunc)
+						{
+							*ppKey = (K*)getFunc(pKey);
+							EVP_PKEY_free(pKey);
+						}
+						else
+						{
+							poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
+							*ppKey = (K*)pKey;
+						}
+						if (!*ppKey) goto error;
+						return true;
+					}
+					if (getFunc) EVP_PKEY_free(pKey);
+					goto error;
+				}
+				else goto error;
+			}
+			else goto error;
+		}
+		return false;
+
+	error:
+		if (pBIO) BIO_free(pBIO);
+		throw OpenSSLException("EVPKey::loadKey(stream)");
+	}
+
+	EVP_PKEY* _pEVPPKey;
+
+	friend class ECKeyImpl;
+	friend class RSAKeyImpl;
+};
+
+
+//
+// inlines
+//
+
+
+inline bool EVPPKey::operator == (const EVPPKey& other) const
+{
+	poco_check_ptr (other._pEVPPKey);
+	poco_check_ptr (_pEVPPKey);
+	return (1 == EVP_PKEY_cmp(_pEVPPKey, other._pEVPPKey));
+}
+
+
+inline bool EVPPKey::operator != (const EVPPKey& other) const
+{
+	return !(other == *this);
+}
+
+
+inline int EVPPKey::type(const EVP_PKEY* pEVPPKey)
+{
+	if (!pEVPPKey) return NID_undef;
+
+	return EVP_PKEY_type(EVP_PKEY_id(pEVPPKey));
+}
+
+
+inline int EVPPKey::type() const
+{
+	return type(_pEVPPKey);
+}
+
+
+inline bool EVPPKey::isSupported(int type) const
+{
+	return type == EVP_PKEY_EC || type == EVP_PKEY_RSA;
+}
+
+
+inline EVPPKey::operator const EVP_PKEY*() const
+{
+	return _pEVPPKey;
+}
+
+
+inline EVPPKey::operator EVP_PKEY*()
+{
+	return _pEVPPKey;
+}
+
+
+inline void EVPPKey::setKey(EC_KEY* pKey)
+{
+	if (!EVP_PKEY_set1_EC_KEY(_pEVPPKey, pKey))
+		throw OpenSSLException();
+}
+
+
+inline void EVPPKey::setKey(RSA* pKey)
+{
+	if (!EVP_PKEY_set1_RSA(_pEVPPKey, pKey))
+		throw OpenSSLException();
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_EVPPKeyImpl_INCLUDED
diff --git a/Poco/Crypto/KeyPair.h b/Poco/Crypto/KeyPair.h
new file mode 100644
index 0000000..b9a705f
--- /dev/null
+++ b/Poco/Crypto/KeyPair.h
@@ -0,0 +1,133 @@
+//
+// KeyPair.h
+//
+//
+// Library: Crypto
+// Package: CryptoCore
+// Module:  KeyPair
+//
+// Definition of the KeyPair class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_KeyPair_INCLUDED
+#define Crypto_KeyPair_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/KeyPairImpl.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class X509Certificate;
+
+
+class Crypto_API KeyPair
+	/// This is a parent class for classes storing a key pair, consisting
+	/// of private and public key. Storage of the private key is optional.
+	///
+	/// If a private key is available, the KeyPair can be
+	/// used for decrypting data (encrypted with the public key)
+	/// or computing secure digital signatures.
+{
+public:
+	enum Type
+	{
+		KT_RSA = KeyPairImpl::KT_RSA_IMPL,
+		KT_EC = KeyPairImpl::KT_EC_IMPL
+	};
+
+	explicit KeyPair(KeyPairImpl::Ptr pKeyPairImpl = 0);
+		/// Extracts the RSA public key from the given certificate.
+
+	virtual ~KeyPair();
+		/// Destroys the KeyPair.
+
+	virtual int size() const;
+		/// Returns the RSA modulus size.
+
+	virtual void save(const std::string& publicKeyPairFile,
+		const std::string& privateKeyPairFile = "",
+		const std::string& privateKeyPairPassphrase = "") const;
+		/// Exports the public and private keys to the given files. 
+		///
+		/// If an empty filename is specified, the corresponding key
+		/// is not exported.
+
+	virtual void save(std::ostream* pPublicKeyPairStream,
+		std::ostream* pPrivateKeyPairStream = 0,
+		const std::string& privateKeyPairPassphrase = "") const;
+		/// Exports the public and private key to the given streams.
+		///
+		/// If a null pointer is passed for a stream, the corresponding
+		/// key is not exported.
+
+	KeyPairImpl::Ptr impl() const;
+		/// Returns the impl object.
+
+	const std::string& name() const;
+		/// Returns key pair name
+
+	Type type() const;
+		/// Returns key pair type
+	
+private:
+	KeyPairImpl::Ptr _pImpl;
+};
+
+
+//
+// inlines
+//
+
+inline int KeyPair::size() const
+{
+	return _pImpl->size();
+}
+
+
+inline void KeyPair::save(const std::string& publicKeyFile,
+	const std::string& privateKeyFile,
+	const std::string& privateKeyPassphrase) const
+{
+	_pImpl->save(publicKeyFile, privateKeyFile, privateKeyPassphrase);
+}
+
+
+inline void KeyPair::save(std::ostream* pPublicKeyStream,
+	std::ostream* pPrivateKeyStream,
+	const std::string& privateKeyPassphrase) const
+{
+	_pImpl->save(pPublicKeyStream, pPrivateKeyStream, privateKeyPassphrase);
+}
+
+
+inline const std::string& KeyPair::name() const
+{
+	return _pImpl->name();
+}
+
+inline KeyPairImpl::Ptr KeyPair::impl() const
+{
+	return _pImpl;
+}
+
+
+inline KeyPair::Type KeyPair::type() const
+{
+	return (KeyPair::Type)impl()->type();
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_KeyPair_INCLUDED
diff --git a/Poco/Crypto/KeyPairImpl.h b/Poco/Crypto/KeyPairImpl.h
new file mode 100644
index 0000000..e6320df
--- /dev/null
+++ b/Poco/Crypto/KeyPairImpl.h
@@ -0,0 +1,107 @@
+//
+// KeyPairImpl.h
+//
+//
+// Library: Crypto
+// Package: CryptoCore
+// Module:  KeyPairImpl
+//
+// Definition of the KeyPairImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_KeyPairImplImpl_INCLUDED
+#define Crypto_KeyPairImplImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <string>
+#include <vector>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class KeyPairImpl: public Poco::RefCountedObject
+	/// Class KeyPairImpl
+{
+public:
+	enum Type
+	{
+		KT_RSA_IMPL = 0,
+		KT_EC_IMPL
+	};
+
+	typedef Poco::AutoPtr<KeyPairImpl> Ptr;
+	typedef std::vector<unsigned char> ByteVec;
+
+	KeyPairImpl(const std::string& name, Type type);
+		/// Create KeyPairImpl with specified type and name.
+
+	virtual ~KeyPairImpl();
+		/// Destroys the KeyPairImpl.
+
+	virtual int size() const = 0;
+		/// Returns the key size.
+
+	virtual void save(const std::string& publicKeyFile,
+		const std::string& privateKeyFile = "",
+		const std::string& privateKeyPassphrase = "") const = 0;
+		/// Exports the public and private keys to the given files. 
+		///
+		/// If an empty filename is specified, the corresponding key
+		/// is not exported.
+
+	virtual void save(std::ostream* pPublicKeyStream,
+		std::ostream* pPrivateKeyStream = 0,
+		const std::string& privateKeyPassphrase = "") const = 0;
+		/// Exports the public and private key to the given streams.
+		///
+		/// If a null pointer is passed for a stream, the corresponding
+		/// key is not exported.
+
+	const std::string& name() const;
+		/// Returns key pair name
+
+	Type type() const;
+		/// Returns key pair type
+
+private:
+	KeyPairImpl();
+
+	std::string _name;
+	Type        _type;
+	OpenSSLInitializer _openSSLInitializer;
+};
+
+
+//
+// inlines
+//
+
+
+inline const std::string& KeyPairImpl::name() const
+{
+	return _name;
+}
+
+
+inline KeyPairImpl::Type KeyPairImpl::type() const
+{
+	return _type;
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_KeyPairImplImpl_INCLUDED
diff --git a/Poco/Crypto/OpenSSLInitializer.h b/Poco/Crypto/OpenSSLInitializer.h
new file mode 100644
index 0000000..42c97ae
--- /dev/null
+++ b/Poco/Crypto/OpenSSLInitializer.h
@@ -0,0 +1,115 @@
+//
+// OpenSSLInitializer.h
+//
+// Library: Crypto
+// Package: CryptoCore
+// Module:  OpenSSLInitializer
+//
+// Definition of the OpenSSLInitializer class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_OpenSSLInitializer_INCLUDED
+#define Crypto_OpenSSLInitializer_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Mutex.h"
+#include "Poco/AtomicCounter.h"
+#include <openssl/crypto.h>
+
+#if defined(OPENSSL_FIPS) && OPENSSL_VERSION_NUMBER < 0x010001000L
+#include <openssl/fips.h>
+#endif
+
+
+extern "C"
+{
+	struct CRYPTO_dynlock_value
+	{
+		Poco::FastMutex _mutex;
+	};
+}
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API OpenSSLInitializer
+	/// Initalizes the OpenSSL library.
+	///
+	/// The class ensures the earliest initialization and the
+	/// latest shutdown of the OpenSSL library.
+{
+public:
+	OpenSSLInitializer();
+		/// Automatically initialize OpenSSL on startup.
+		
+	~OpenSSLInitializer();
+		/// Automatically shut down OpenSSL on exit.
+	
+	static void initialize();
+		/// Initializes the OpenSSL machinery.
+
+	static void uninitialize();
+		/// Shuts down the OpenSSL machinery.
+
+	static bool isFIPSEnabled();
+		// Returns true if FIPS mode is enabled, false otherwise.
+
+	static void enableFIPSMode(bool enabled);
+		// Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything.
+
+protected:
+	enum
+	{
+		SEEDSIZE = 256
+	};
+	
+	// OpenSSL multithreading support
+	static void lock(int mode, int n, const char* file, int line);
+	static unsigned long id();
+	static struct CRYPTO_dynlock_value* dynlockCreate(const char* file, int line);
+	static void dynlock(int mode, struct CRYPTO_dynlock_value* lock, const char* file, int line);
+	static void dynlockDestroy(struct CRYPTO_dynlock_value* lock, const char* file, int line);
+
+private:
+	static Poco::FastMutex* _mutexes;
+	static Poco::AtomicCounter _rc;
+};
+
+
+//
+// inlines
+//
+inline bool OpenSSLInitializer::isFIPSEnabled()
+{
+#ifdef OPENSSL_FIPS
+	return FIPS_mode() ? true : false;
+#else
+	return false;
+#endif
+}
+
+#ifdef OPENSSL_FIPS
+inline void OpenSSLInitializer::enableFIPSMode(bool enabled)
+{
+	FIPS_mode_set(enabled);
+}
+#else
+inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/)
+{
+}
+#endif
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_OpenSSLInitializer_INCLUDED
diff --git a/Poco/Crypto/PKCS12Container.h b/Poco/Crypto/PKCS12Container.h
new file mode 100644
index 0000000..63cc224
--- /dev/null
+++ b/Poco/Crypto/PKCS12Container.h
@@ -0,0 +1,159 @@
+//
+// PKCS12Container.h
+//
+// Library: Crypto
+// Package: Certificate
+// Module:  PKCS12Container
+//
+// Definition of the PKCS12Container class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_PKCS12Container_INCLUDED
+#define Crypto_PKCS12Container_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/Crypto/X509Certificate.h"
+#include "Poco/Crypto/EVPPKey.h"
+#include "Poco/Path.h"
+#include <memory>
+#include <istream>
+#include <openssl/pkcs12.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API PKCS12Container
+	/// This class implements PKCS#12 container functionality.
+{
+public:
+	typedef X509Certificate::List CAList;
+	typedef std::vector<std::string> CANameList;
+
+	explicit PKCS12Container(std::istream& istr, const std::string& password = "");
+		/// Creates the PKCS12Container object from a stream.
+
+	explicit PKCS12Container(const std::string& path, const std::string& password = "");
+		/// Creates the PKCS12Container object from a file.
+
+	PKCS12Container(const PKCS12Container& cont);
+		/// Copy constructor.
+
+	PKCS12Container& operator = (const PKCS12Container& cont);
+		/// Assignment operator.
+
+#ifdef POCO_ENABLE_CPP11
+
+	PKCS12Container(PKCS12Container&& cont);
+		/// Move constructor.
+
+	PKCS12Container& operator = (PKCS12Container&& cont);
+		/// Move assignment operator.
+
+#endif // POCO_ENABLE_CPP11
+
+	~PKCS12Container();
+		/// Destroys the PKCS12Container.
+
+	bool hasKey() const;
+		/// Returns true if container contains the key.
+
+	EVPPKey getKey() const;
+		/// Return key as openssl EVP_PKEY wrapper object.
+
+	bool hasX509Certificate() const;
+		/// Returns true if container has X509 certificate.
+
+	const X509Certificate& getX509Certificate() const;
+		/// Returns the X509 certificate.
+		/// Throws NotFoundException if there is no certificate.
+
+	const CAList& getCACerts() const;
+		/// Returns the list of CA certificates in this container.
+
+	const std::string& getFriendlyName() const;
+		/// Returns the friendly name of the certificate bag.
+
+	const CANameList& getFriendlyNamesCA() const;
+		/// Returns a list of CA certificates friendly names.
+
+private:
+	void load(PKCS12* pPKCS12, const std::string& password = "");
+	std::string extractFriendlyName(X509* pCert);
+
+#ifdef POCO_ENABLE_CPP11
+	typedef std::unique_ptr<X509Certificate> CertPtr;
+#else
+	typedef std::auto_ptr<X509Certificate> CertPtr;
+#endif // #ifdef POCO_ENABLE_CPP11
+
+	OpenSSLInitializer _openSSLInitializer;
+	EVP_PKEY*          _pKey;
+	CertPtr            _pX509Cert;
+	CAList             _caCertList;
+	CANameList         _caCertNames;
+	std::string        _pkcsFriendlyName;
+};
+
+
+//
+// inlines
+//
+
+inline bool PKCS12Container::hasX509Certificate() const
+{
+	return _pX509Cert.get() != 0;
+}
+
+
+inline const X509Certificate& PKCS12Container::getX509Certificate() const
+{
+	if (!hasX509Certificate())
+		throw NotFoundException("PKCS12Container X509 certificate");
+	return *_pX509Cert;
+}
+
+
+inline const std::string& PKCS12Container::getFriendlyName() const
+{
+	return _pkcsFriendlyName;
+}
+
+
+inline const PKCS12Container::CAList& PKCS12Container::getCACerts() const
+{
+	return _caCertList;
+}
+
+
+inline const PKCS12Container::CANameList& PKCS12Container::getFriendlyNamesCA() const
+{
+	return _caCertNames;
+}
+
+
+inline bool PKCS12Container::hasKey() const
+{
+	return _pKey != 0;
+}
+
+
+inline EVPPKey PKCS12Container::getKey() const
+{
+	return EVPPKey(_pKey);
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_PKCS12Container_INCLUDED
diff --git a/Poco/Crypto/RSACipherImpl.h b/Poco/Crypto/RSACipherImpl.h
new file mode 100644
index 0000000..2ebc38e
--- /dev/null
+++ b/Poco/Crypto/RSACipherImpl.h
@@ -0,0 +1,77 @@
+//
+// RSACipherImpl.h
+//
+// Library: Crypto
+// Package: RSA
+// Module:  RSACipherImpl
+//
+// Definition of the RSACipherImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_RSACipherImpl_INCLUDED
+#define Crypto_RSACipherImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/Cipher.h"
+#include "Poco/Crypto/RSAKey.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include <openssl/evp.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class RSACipherImpl: public Cipher
+	/// An implementation of the Cipher class for 
+	/// asymmetric (public-private key) encryption
+	/// based on the the RSA algorithm in OpenSSL's 
+	/// crypto library.
+	///
+	/// Encryption is using the public key, decryption
+	/// requires the private key.
+{
+public:
+	RSACipherImpl(const RSAKey& key, RSAPaddingMode paddingMode);
+		/// Creates a new RSACipherImpl object for the given RSAKey
+		/// and using the given padding mode.
+
+	virtual ~RSACipherImpl();
+		/// Destroys the RSACipherImpl.
+
+	const std::string& name() const;
+		/// Returns the name of the Cipher.
+	
+	CryptoTransform* createEncryptor();
+		/// Creates an encryptor object.
+
+	CryptoTransform* createDecryptor();
+		/// Creates a decryptor object.
+
+private:
+	RSAKey _key;
+	RSAPaddingMode _paddingMode;
+	OpenSSLInitializer _openSSLInitializer;
+};
+
+
+//
+// Inlines
+//
+inline const std::string& RSACipherImpl::name() const
+{
+	return _key.name();
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_RSACipherImpl_INCLUDED
diff --git a/Poco/Crypto/RSADigestEngine.h b/Poco/Crypto/RSADigestEngine.h
new file mode 100644
index 0000000..7c4d386
--- /dev/null
+++ b/Poco/Crypto/RSADigestEngine.h
@@ -0,0 +1,111 @@
+//
+// RSADigestEngine.h
+//
+// Library: Crypto
+// Package: RSA
+// Module:  RSADigestEngine
+//
+// Definition of the RSADigestEngine class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_RSADigestEngine_INCLUDED
+#define Crypto_RSADigestEngine_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/RSAKey.h"
+#include "Poco/DigestEngine.h"
+#include "Poco/Crypto/DigestEngine.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API RSADigestEngine: public Poco::DigestEngine
+	/// This class implements a Poco::DigestEngine that can be
+	/// used to compute a secure digital signature.
+	///
+	/// First another Poco::Crypto::DigestEngine is created and
+	/// used to compute a cryptographic hash of the data to be
+	/// signed. Then, the hash value is encrypted, using
+	/// the RSA private key.
+	///
+	/// To verify a signature, pass it to the verify() 
+	/// member function. It will decrypt the signature
+	/// using the RSA public key and compare the resulting
+	/// hash with the actual hash of the data.
+{
+public:
+	enum DigestType
+	{
+		DIGEST_MD5,
+		DIGEST_SHA1
+	};
+	
+	//@ deprecated
+	RSADigestEngine(const RSAKey& key, DigestType digestType = DIGEST_SHA1);
+		/// Creates the RSADigestEngine with the given RSA key,
+		/// using the MD5 or SHA-1 hash algorithm.
+		/// Kept for backward compatibility
+
+	RSADigestEngine(const RSAKey& key, const std::string &name);
+		/// Creates the RSADigestEngine with the given RSA key,
+		/// using the hash algorithm with the given name
+		/// (e.g., "MD5", "SHA1", "SHA256", "SHA512", etc.).
+		/// See the OpenSSL documentation for a list of supported digest algorithms.
+		///
+		/// Throws a Poco::NotFoundException if no algorithm with the given name exists.
+
+	~RSADigestEngine();
+		/// Destroys the RSADigestEngine.
+
+	std::size_t digestLength() const;
+		/// Returns the length of the digest in bytes.
+
+	void reset();
+		/// Resets the engine so that a new
+		/// digest can be computed.
+		
+	const DigestEngine::Digest& digest();
+		/// Finishes the computation of the digest 
+		/// (the first time it's called) and
+		/// returns the message digest. 
+		///
+		/// Can be called multiple times.
+
+	const DigestEngine::Digest& signature();
+		/// Signs the digest using the RSA algorithm
+		/// and the private key (the first time it's
+		/// called) and returns the result.
+		///
+		/// Can be called multiple times.
+
+	bool verify(const DigestEngine::Digest& signature);
+		/// Verifies the data against the signature.
+		///
+		/// Returns true if the signature can be verified, false otherwise.
+
+protected:
+	void updateImpl(const void* data, std::size_t length);
+
+private:
+	RSAKey _key;
+	Poco::Crypto::DigestEngine _engine;
+	Poco::DigestEngine::Digest _digest;
+	Poco::DigestEngine::Digest _signature;
+};
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_RSADigestEngine_INCLUDED
diff --git a/Poco/Crypto/RSAKey.h b/Poco/Crypto/RSAKey.h
new file mode 100644
index 0000000..ad9163e
--- /dev/null
+++ b/Poco/Crypto/RSAKey.h
@@ -0,0 +1,125 @@
+//
+// RSAKey.h
+//
+// Library: Crypto
+// Package: RSA
+// Module:  RSAKey
+//
+// Definition of the RSAKey class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_RSAKey_INCLUDED
+#define Crypto_RSAKey_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/KeyPair.h"
+#include "Poco/Crypto/RSAKeyImpl.h"
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class X509Certificate;
+class PKCS12Container;
+
+
+class Crypto_API RSAKey : public KeyPair
+	/// This class stores an RSA key pair, consisting
+	/// of private and public key. Storage of the private
+	/// key is optional.
+	///
+	/// If a private key is available, the RSAKey can be
+	/// used for decrypting data (encrypted with the public key)
+	/// or computing secure digital signatures.
+{
+public:
+	enum KeyLength
+	{
+		KL_512  = 512,
+		KL_1024 = 1024,
+		KL_2048 = 2048,
+		KL_4096 = 4096
+	};
+
+	enum Exponent
+	{
+		EXP_SMALL = 0,
+		EXP_LARGE
+	};
+
+	RSAKey(const EVPPKey& key);
+		/// Constructs ECKeyImpl by extracting the EC key.
+
+	RSAKey(const X509Certificate& cert);
+		/// Extracts the RSA public key from the given certificate.
+
+	RSAKey(const PKCS12Container& cert);
+		/// Extracts the RSA private key from the given certificate.
+
+	RSAKey(KeyLength keyLength, Exponent exp);
+		/// Creates the RSAKey. Creates a new public/private keypair using the given parameters.
+		/// Can be used to sign data and verify signatures.
+
+	RSAKey(const std::string& publicKeyFile,
+		const std::string& privateKeyFile = "",
+		const std::string& privateKeyPassphrase = "");
+		/// Creates the RSAKey, by reading public and private key from the given files and
+		/// using the given passphrase for the private key.
+		///
+		/// Cannot be used for signing or decryption unless a private key is available.
+		///
+		/// If a private key is specified, you don't need to specify a public key file.
+		/// OpenSSL will auto-create the public key from the private key.
+
+	RSAKey(std::istream* pPublicKeyStream,
+		std::istream* pPrivateKeyStream = 0,
+		const std::string& privateKeyPassphrase = "");
+		/// Creates the RSAKey, by reading public and private key from the given streams and
+		/// using the given passphrase for the private key.
+		///
+		/// Cannot be used for signing or decryption unless a private key is available.
+		///
+		/// If a private key is specified, you don't need to specify a public key file.
+		/// OpenSSL will auto-create the public key from the private key.
+
+	~RSAKey();
+		/// Destroys the RSAKey.
+
+	RSAKeyImpl::ByteVec modulus() const;
+		/// Returns the RSA modulus.
+
+	RSAKeyImpl::ByteVec encryptionExponent() const;
+		/// Returns the RSA encryption exponent.
+
+	RSAKeyImpl::ByteVec decryptionExponent() const;
+		/// Returns the RSA decryption exponent.
+
+	RSAKeyImpl::Ptr impl() const;
+		/// Returns the impl object.
+	
+private:
+	RSAKeyImpl::Ptr _pImpl;
+};
+
+
+//
+// inlines
+//
+inline RSAKeyImpl::Ptr RSAKey::impl() const
+{
+	return _pImpl;
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_RSAKey_INCLUDED
\ No newline at end of file
diff --git a/Poco/Crypto/RSAKeyImpl.h b/Poco/Crypto/RSAKeyImpl.h
new file mode 100644
index 0000000..0358816
--- /dev/null
+++ b/Poco/Crypto/RSAKeyImpl.h
@@ -0,0 +1,141 @@
+//
+// RSAKeyImpl.h
+//
+// Library: Crypto
+// Package: RSA
+// Module:  RSAKeyImpl
+//
+// Definition of the RSAKeyImpl class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_RSAKeyImplImpl_INCLUDED
+#define Crypto_RSAKeyImplImpl_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/EVPPKey.h"
+#include "Poco/Crypto/KeyPairImpl.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <istream>
+#include <ostream>
+#include <vector>
+
+
+struct bignum_st;
+struct rsa_st;
+typedef struct bignum_st BIGNUM;
+typedef struct rsa_st RSA;
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class X509Certificate;
+class PKCS12Container;
+
+
+class RSAKeyImpl: public KeyPairImpl
+	/// class RSAKeyImpl
+{
+public:
+	typedef Poco::AutoPtr<RSAKeyImpl> Ptr;
+	typedef std::vector<unsigned char> ByteVec;
+
+	RSAKeyImpl(const EVPPKey& key);
+		/// Constructs ECKeyImpl by extracting the EC key.
+
+	RSAKeyImpl(const X509Certificate& cert);
+		/// Extracts the RSA public key from the given certificate.
+
+	RSAKeyImpl(const PKCS12Container& cert);
+		/// Extracts the EC private key from the given certificate.
+
+	RSAKeyImpl(int keyLength, unsigned long exponent);
+		/// Creates the RSAKey. Creates a new public/private keypair using the given parameters.
+		/// Can be used to sign data and verify signatures.
+
+	RSAKeyImpl(const std::string& publicKeyFile, const std::string& privateKeyFile, const std::string& privateKeyPassphrase);
+		/// Creates the RSAKey, by reading public and private key from the given files and
+		/// using the given passphrase for the private key. Can only by used for signing if 
+		/// a private key is available. 
+
+	RSAKeyImpl(std::istream* pPublicKeyStream, std::istream* pPrivateKeyStream, const std::string& privateKeyPassphrase);
+		/// Creates the RSAKey. Can only by used for signing if pPrivKey
+		/// is not null. If a private key file is specified, you don't need to
+		/// specify a public key file. OpenSSL will auto-create it from the private key.
+
+	~RSAKeyImpl();
+		/// Destroys the RSAKeyImpl.
+
+	RSA* getRSA();
+		/// Returns the OpenSSL RSA object.
+
+	const RSA* getRSA() const;
+		/// Returns the OpenSSL RSA object.
+
+	int size() const;
+		/// Returns the RSA modulus size.
+
+	ByteVec modulus() const;
+		/// Returns the RSA modulus.
+
+	ByteVec encryptionExponent() const;
+		/// Returns the RSA encryption exponent.
+
+	ByteVec decryptionExponent() const;
+		/// Returns the RSA decryption exponent.
+
+	void save(const std::string& publicKeyFile,
+		const std::string& privateKeyFile = "",
+		const std::string& privateKeyPassphrase = "") const;
+		/// Exports the public and private keys to the given files. 
+		///
+		/// If an empty filename is specified, the corresponding key
+		/// is not exported.
+
+	void save(std::ostream* pPublicKeyStream,
+		std::ostream* pPrivateKeyStream = 0,
+		const std::string& privateKeyPassphrase = "") const;
+		/// Exports the public and private key to the given streams.
+		///
+		/// If a null pointer is passed for a stream, the corresponding
+		/// key is not exported.
+
+private:
+	RSAKeyImpl();
+
+	void freeRSA();
+	static ByteVec convertToByteVec(const BIGNUM* bn);
+
+	RSA* _pRSA;
+};
+
+
+//
+// inlines
+//
+inline RSA* RSAKeyImpl::getRSA()
+{
+	return _pRSA;
+}
+
+
+inline const RSA* RSAKeyImpl::getRSA() const
+{
+	return _pRSA;
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_RSAKeyImplImpl_INCLUDED
\ No newline at end of file
diff --git a/Poco/Crypto/X509Certificate.h b/Poco/Crypto/X509Certificate.h
new file mode 100644
index 0000000..ccdab1c
--- /dev/null
+++ b/Poco/Crypto/X509Certificate.h
@@ -0,0 +1,245 @@
+//
+// X509Certificate.h
+//
+// Library: Crypto
+// Package: Certificate
+// Module:  X509Certificate
+//
+// Definition of the X509Certificate class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Crypto_X509Certificate_INCLUDED
+#define Crypto_X509Certificate_INCLUDED
+
+
+#include "Poco/Crypto/Crypto.h"
+#include "Poco/Crypto/OpenSSLInitializer.h"
+#include "Poco/DateTime.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+#include <set>
+#include <istream>
+#include <openssl/ssl.h>
+
+
+namespace Poco {
+namespace Crypto {
+
+
+class Crypto_API X509Certificate
+	/// This class represents a X509 Certificate.
+{
+public:
+	typedef std::vector<X509Certificate> List;
+
+	enum NID
+		/// Name identifier for extracting information from
+		/// a certificate subject's or issuer's distinguished name.
+	{
+		NID_COMMON_NAME = 13,
+		NID_COUNTRY = 14,
+		NID_LOCALITY_NAME = 15,
+		NID_STATE_OR_PROVINCE = 16,
+		NID_ORGANIZATION_NAME = 17,
+		NID_ORGANIZATION_UNIT_NAME = 18,
+		NID_PKCS9_EMAIL_ADDRESS = 48,
+		NID_SERIAL_NUMBER = 105
+	};
+
+	explicit X509Certificate(std::istream& istr);
+		/// Creates the X509Certificate object by reading
+		/// a certificate in PEM format from a stream.
+
+	explicit X509Certificate(const std::string& path);
+		/// Creates the X509Certificate object by reading
+		/// a certificate in PEM format from a file.
+
+	explicit X509Certificate(X509* pCert);
+		/// Creates the X509Certificate from an existing
+		/// OpenSSL certificate. Ownership is taken of
+		/// the certificate.
+
+	X509Certificate(X509* pCert, bool shared);
+		/// Creates the X509Certificate from an existing
+		/// OpenSSL certificate. Ownership is taken of
+		/// the certificate. If shared is true, the
+		/// certificate's reference count is incremented.
+
+	X509Certificate(const X509Certificate& cert);
+		/// Creates the certificate by copying another one.
+
+	X509Certificate& operator = (const X509Certificate& cert);
+		/// Assigns a certificate.
+
+	void swap(X509Certificate& cert);
+		/// Exchanges the certificate with another one.
+
+	~X509Certificate();
+		/// Destroys the X509Certificate.
+
+	long version() const;
+		/// Returns the version of the certificate.
+
+	const std::string& serialNumber() const;
+		/// Returns the certificate serial number as a
+		/// string in decimal encoding.
+
+	const std::string& issuerName() const;
+		/// Returns the certificate issuer's distinguished name.
+
+	std::string issuerName(NID nid) const;
+		/// Extracts the information specified by the given
+		/// NID (name identifier) from the certificate issuer's
+		/// distinguished name.
+
+	const std::string& subjectName() const;
+		/// Returns the certificate subject's distinguished name.
+
+	std::string subjectName(NID nid) const;
+		/// Extracts the information specified by the given
+		/// NID (name identifier) from the certificate subject's
+		/// distinguished name.
+
+	std::string commonName() const;
+		/// Returns the common name stored in the certificate
+		/// subject's distinguished name.
+
+	void extractNames(std::string& commonName, std::set<std::string>& domainNames) const;
+		/// Extracts the common name and the alias domain names from the
+		/// certificate.
+
+	Poco::DateTime validFrom() const;
+		/// Returns the date and time the certificate is valid from.
+
+	Poco::DateTime expiresOn() const;
+		/// Returns the date and time the certificate expires.
+
+	void save(std::ostream& stream) const;
+		/// Writes the certificate to the given stream.
+		/// The certificate is written in PEM format.
+
+	void save(const std::string& path) const;
+		/// Writes the certificate to the file given by path.
+		/// The certificate is written in PEM format.
+
+	bool issuedBy(const X509Certificate& issuerCertificate) const;
+		/// Checks whether the certificate has been issued by
+		/// the issuer given by issuerCertificate. This can be
+		/// used to validate a certificate chain.
+		///
+		/// Verifies if the certificate has been signed with the
+		/// issuer's private key, using the public key from the issuer
+		/// certificate.
+		///
+		/// Returns true if verification against the issuer certificate
+		/// was successful, false otherwise.
+
+	bool equals(const X509Certificate& otherCertificate) const;
+		/// Checks whether the certificate is equal to
+		/// the other certificate, by comparing the hashes
+		/// of both certificates.
+		///
+		/// Returns true if both certificates are identical,
+		/// otherwise false.
+
+	const X509* certificate() const;
+		/// Returns the underlying OpenSSL certificate.
+
+	X509* dup() const;
+		/// Duplicates and returns the underlying OpenSSL certificate. Note that
+		/// the caller assumes responsibility for the lifecycle of the created
+		/// certificate.
+
+	std::string signatureAlgorithm() const;
+		/// Returns the certificate signature algorithm long name.
+
+	void print(std::ostream& out) const;
+		/// Prints the certificate information to ostream.
+
+	static List readPEM(const std::string& pemFileName);
+		/// Reads and returns a list of certificates from
+		/// the specified PEM file.
+
+	static void writePEM(const std::string& pemFileName, const List& list);
+		/// Writes the list of certificates to the specified PEM file.
+
+protected:
+	void load(std::istream& stream);
+		/// Loads the certificate from the given stream. The
+		/// certificate must be in PEM format.
+
+	void load(const std::string& path);
+		/// Loads the certificate from the given file. The
+		/// certificate must be in PEM format.
+
+	void init();
+		/// Extracts issuer and subject name from the certificate.
+
+private:
+	enum
+	{
+		NAME_BUFFER_SIZE = 256
+	};
+
+	std::string _issuerName;
+	std::string _subjectName;
+	std::string _serialNumber;
+	X509*       _pCert;
+	OpenSSLInitializer _openSSLInitializer;
+};
+
+
+//
+// inlines
+//
+
+
+inline long X509Certificate::version() const
+{
+	// This is defined by standards (X.509 et al) to be
+	// one less than the certificate version.
+	// So, eg. a version 3 certificate will return 2.
+	return X509_get_version(_pCert) + 1;
+}
+
+
+inline const std::string& X509Certificate::serialNumber() const
+{
+	return _serialNumber;
+}
+
+
+inline const std::string& X509Certificate::issuerName() const
+{
+	return _issuerName;
+}
+
+
+inline const std::string& X509Certificate::subjectName() const
+{
+	return _subjectName;
+}
+
+
+inline const X509* X509Certificate::certificate() const
+{
+	return _pCert;
+}
+
+
+inline X509* X509Certificate::dup() const
+{
+	return X509_dup(_pCert);
+}
+
+
+} } // namespace Poco::Crypto
+
+
+#endif // Crypto_X509Certificate_INCLUDED
diff --git a/Poco/DOM/AbstractContainerNode.h b/Poco/DOM/AbstractContainerNode.h
new file mode 100644
index 0000000..60dc958
--- /dev/null
+++ b/Poco/DOM/AbstractContainerNode.h
@@ -0,0 +1,78 @@
+//
+// AbstractContainerNode.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the AbstractContainerNode class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_AbstractContainerNode_INCLUDED
+#define DOM_AbstractContainerNode_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractNode.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API AbstractContainerNode: public AbstractNode
+	/// AbstractContainerNode is an implementation of Node
+	/// that stores and manages child nodes.
+	///
+	/// Child nodes are organized in a single linked list.
+{
+public:
+	// Node
+	Node* firstChild() const;
+	Node* lastChild() const;
+	Node* insertBefore(Node* newChild, Node* refChild);
+	Node* replaceChild(Node* newChild, Node* oldChild);
+	Node* removeChild(Node* oldChild);
+	Node* appendChild(Node* newChild);
+	bool hasChildNodes() const;
+	bool hasAttributes() const;
+	Node* getNodeByPath(const XMLString& path) const;
+	Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const;
+
+protected:
+	AbstractContainerNode(Document* pOwnerDocument);
+	AbstractContainerNode(Document* pOwnerDocument, const AbstractContainerNode& node);
+	~AbstractContainerNode();
+
+	void dispatchNodeRemovedFromDocument();
+	void dispatchNodeInsertedIntoDocument();
+	
+	static const Node* findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap);
+	static const Node* findElement(const XMLString& name, const Node* pNode, const NSMap* pNSMap);
+	static const Node* findElement(int index, const Node* pNode, const NSMap* pNSMap);
+	static const Node* findElement(const XMLString& attr, const XMLString& value, const Node* pNode, const NSMap* pNSMap);
+	static const Attr* findAttribute(const XMLString& name, const Node* pNode, const NSMap* pNSMap);
+	bool hasAttributeValue(const XMLString& name, const XMLString& value, const NSMap* pNSMap) const;
+	static bool namesAreEqual(const Node* pNode1, const Node* pNode2, const NSMap* pNSMap);
+	static bool namesAreEqual(const Node* pNode, const XMLString& name, const NSMap* pNSMap);
+
+	static const XMLString WILDCARD;
+
+private:
+	AbstractNode* _pFirstChild;
+
+	friend class AbstractNode;
+	friend class NodeAppender;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_AbstractContainerNode_INCLUDED
diff --git a/Poco/DOM/AbstractNode.h b/Poco/DOM/AbstractNode.h
new file mode 100644
index 0000000..cedcc73
--- /dev/null
+++ b/Poco/DOM/AbstractNode.h
@@ -0,0 +1,125 @@
+//
+// AbstractNode.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the AbstractNode class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_AbstractNode_INCLUDED
+#define DOM_AbstractNode_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/Node.h"
+#include "Poco/DOM/MutationEvent.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class AbstractContainerNode;
+class Attr;
+class EventDispatcher;
+
+
+class XML_API AbstractNode: public Node
+	/// AbstractNode provides a basic implementation
+	/// of the Node interface for all types of nodes
+	/// that do not contain other nodes.
+{
+public:
+	// Node
+	const XMLString& nodeName() const;
+	const XMLString& getNodeValue() const;
+	void setNodeValue(const XMLString& value);
+	Node* parentNode() const;
+	NodeList* childNodes() const;
+	Node* firstChild() const;
+	Node* lastChild() const;
+	Node* previousSibling() const;
+	Node* nextSibling() const;
+	NamedNodeMap* attributes() const;
+	Document* ownerDocument() const;
+	Node* insertBefore(Node* newChild, Node* refChild);
+	Node* replaceChild(Node* newChild, Node* oldChild);
+	Node* removeChild(Node* oldChild);
+	Node* appendChild(Node* newChild);
+	bool hasChildNodes() const;
+	Node* cloneNode(bool deep) const;
+	void normalize();
+	bool isSupported(const XMLString& feature, const XMLString& version) const;
+	const XMLString& namespaceURI() const;
+	XMLString prefix() const;
+	const XMLString& localName() const;
+	bool hasAttributes() const;
+
+	// EventTarget
+	void addEventListener(const XMLString& type, EventListener* listener, bool useCapture);
+	void removeEventListener(const XMLString& type, EventListener* listener, bool useCapture);
+	bool dispatchEvent(Event* evt);
+
+	// Extensions
+	XMLString innerText() const;
+	Node* getNodeByPath(const XMLString& path) const;
+	Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const;
+
+	virtual void autoRelease();
+
+protected:
+	AbstractNode(Document* pOwnerDocument);
+	AbstractNode(Document* pOwnerDocument, const AbstractNode& node);
+	~AbstractNode();
+
+	virtual Node* copyNode(bool deep, Document* pOwnerDocument) const = 0;
+
+	virtual bool events() const;
+	virtual bool eventsSuspended() const;
+	void captureEvent(Event* evt);
+	void bubbleEvent(Event* evt);
+	void dispatchSubtreeModified();
+	void dispatchNodeInserted();
+	void dispatchNodeRemoved();
+	virtual void dispatchNodeRemovedFromDocument();
+	virtual void dispatchNodeInsertedIntoDocument();
+	void dispatchAttrModified(Attr* pAttr, MutationEvent::AttrChangeType changeType, const XMLString& prevValue, const XMLString& newValue);
+	void dispatchCharacterDataModified(const XMLString& prevValue, const XMLString& newValue);
+	void setOwnerDocument(Document* pOwnerDocument);
+
+	static const XMLString EMPTY_STRING;
+
+private:
+	AbstractNode();
+
+	AbstractContainerNode* _pParent;
+	AbstractNode*          _pNext;
+	Document*              _pOwner;
+	EventDispatcher*       _pEventDispatcher;
+
+	static const XMLString NODE_NAME;
+
+	friend class AbstractContainerNode;
+	friend class Document;
+	friend class DocumentFragment;
+	friend class Element;
+	friend class Attr;
+	friend class CharacterData;
+	friend class DOMBuilder;
+	friend class NodeAppender;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_AbstractNode_INCLUDED
diff --git a/Poco/DOM/Attr.h b/Poco/DOM/Attr.h
new file mode 100644
index 0000000..13ace7e
--- /dev/null
+++ b/Poco/DOM/Attr.h
@@ -0,0 +1,180 @@
+//
+// Attr.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Attr class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Attr_INCLUDED
+#define DOM_Attr_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractNode.h"
+#include "Poco/DOM/Element.h"
+#include "Poco/XML/Name.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Attr: public AbstractNode
+	/// The Attr interface represents an attribute in an Element object. Typically
+	/// the allowable values for the attribute are defined in a document type definition.
+	/// 
+	/// Attr objects inherit the Node interface, but since they are not actually
+	/// child nodes of the element they describe, the DOM does not consider them
+	/// part of the document tree. Thus, the Node attributes parentNode, previousSibling,
+	/// and nextSibling have a null value for Attr objects. The DOM takes the view
+	/// that attributes are properties of elements rather than having a separate
+	/// identity from the elements they are associated with; this should make it
+	/// more efficient to implement such features as default attributes associated
+	/// with all elements of a given type. Furthermore, Attr nodes may not be immediate
+	/// children of a DocumentFragment. However, they can be associated with Element
+	/// nodes contained within a DocumentFragment. In short, users and implementors
+	/// of the DOM need to be aware that Attr nodes have some things in common with
+	/// other objects inheriting the Node interface, but they also are quite distinct.
+	/// 
+	/// The attribute's effective value is determined as follows: if this attribute
+	/// has been explicitly assigned any value, that value is the attribute's effective
+	/// value; otherwise, if there is a declaration for this attribute, and that
+	/// declaration includes a default value, then that default value is the attribute's
+	/// effective value; otherwise, the attribute does not exist on this element
+	/// in the structure model until it has been explicitly added. Note that the
+	/// nodeValue attribute on the Attr instance can also be used to retrieve the
+	/// string version of the attribute's value(s).
+	/// 
+	/// In XML, where the value of an attribute can contain entity references, the
+	/// child nodes of the Attr node provide a representation in which entity references
+	/// are not expanded. These child nodes may be either Text or EntityReference
+	/// nodes. Because the attribute type may be unknown, there are no tokenized
+	/// attribute values.
+{
+public:
+	const XMLString& name() const;
+		/// Returns the name of this attribute.
+
+	bool specified() const;
+		/// If this attribute was explicitly given a value in the original document,
+		/// this is true; otherwise, it is false. Note that the implementation is in
+		/// charge of this attribute, not the user. If the user changes the value of
+		/// the attribute (even if it ends up having the same value as the default value)
+		/// then the specified flag is automatically flipped to true. To re-specify
+		/// the attribute as the default value from the DTD, the user must delete the
+		/// attribute. The implementation will then make a new attribute available with
+		/// specified set to false and the default value (if one exists).
+		/// In summary:
+		/// 
+		///     * If the attribute has an assigned value in the document then specified
+		///       is true, and the value is the assigned value.
+		///     * If the attribute has no assigned value in the document and has a default
+		///       value in the DTD, then specified is false, and the value is the default
+		///       value in the DTD.
+		///     * If the attribute has no assigned value in the document and has a value
+		///       of #IMPLIED in the DTD, then the attribute does not appear in the structure
+		///       model of the document.
+		///     * If the attribute is not associated to any element (i.e. because it
+		///       was just created or was obtained from some removal or cloning operation)
+		///       specified is true.
+
+	const XMLString& value() const;
+		/// Returns the value of the attribute as a string. Character
+		/// and general entity references are replaced with their values. See also the
+		/// method getAttribute on the Element interface.
+
+	const XMLString& getValue() const;
+		/// Returns the value of the attribute as a string. Character
+		/// and general entity references are replaced with their values. See also the
+		/// method getAttribute on the Element interface.
+
+	void setValue(const XMLString& value);
+		/// Sets the value of the attribute as a string.
+		/// This creates a Text node with the unparsed contents of the string.
+		/// I.e. any characters that an XML processor would recognize as markup are
+		/// instead treated as literal text. See also the method setAttribute on the
+		/// Element interface.
+
+	// DOM Level 2
+	Element* ownerElement() const;
+		/// The Element node this attribute is attached to or null 
+		/// if this attribute is not in use.
+
+	// Node
+	Node* parentNode() const;
+	const XMLString& nodeName() const;
+	const XMLString& getNodeValue() const;
+	void setNodeValue(const XMLString& value);
+	unsigned short nodeType() const;
+	Node* previousSibling() const;
+	const XMLString& namespaceURI() const;
+	XMLString prefix() const;
+	const XMLString& localName() const;
+
+	// Non-standard extensions
+	XMLString innerText() const;
+
+protected:
+	Attr(Document* pOwnerDocument, Element* pOwnerElement, const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const XMLString& value, bool specified = true);
+	Attr(Document* pOwnerDocument, const Attr& attr);
+	~Attr();
+	
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	const Name& _name;
+	XMLString   _value;
+	bool        _specified;
+
+	friend class Document;
+	friend class Element;
+	friend class DOMBuilder;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Attr::name() const
+{
+	return _name.qname();
+}
+
+
+inline const XMLString& Attr::value() const
+{
+	return _value;
+}
+
+
+inline const XMLString& Attr::getValue() const
+{
+	return _value;
+}
+
+
+inline bool Attr::specified() const
+{
+	return _specified;
+}
+
+
+inline Element* Attr::ownerElement() const
+{
+	return static_cast<Element*>(_pParent);
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Attr_INCLUDED
diff --git a/Poco/DOM/AttrMap.h b/Poco/DOM/AttrMap.h
new file mode 100644
index 0000000..41f34fd
--- /dev/null
+++ b/Poco/DOM/AttrMap.h
@@ -0,0 +1,65 @@
+//
+// AttrMap.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the AttrMap class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_AttrMap_INCLUDED
+#define DOM_AttrMap_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/NamedNodeMap.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Element;
+
+
+class XML_API AttrMap: public NamedNodeMap
+	// This implementation of NamedNodeMap is
+	// returned by Element::attributes()
+{
+public:
+	Node* getNamedItem(const XMLString& name) const;
+	Node* setNamedItem(Node* arg);
+	Node* removeNamedItem(const XMLString& name);
+	Node* item(unsigned long index) const;
+	unsigned long length() const;
+
+	Node* getNamedItemNS(const XMLString& namespaceURI, const XMLString& localName) const;
+	Node* setNamedItemNS(Node* arg);
+	Node* removeNamedItemNS(const XMLString& namespaceURI, const XMLString& localName);
+
+	void autoRelease();
+
+protected:
+	AttrMap(Element* pElement);
+	~AttrMap();
+
+private:
+	AttrMap();
+
+	Element* _pElement;
+	
+	friend class Element;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_AttrMap_INCLUDED
diff --git a/Poco/DOM/AutoPtr.h b/Poco/DOM/AutoPtr.h
new file mode 100644
index 0000000..85f83d4
--- /dev/null
+++ b/Poco/DOM/AutoPtr.h
@@ -0,0 +1,35 @@
+//
+// AutoPtr.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Import Poco::AutoPtr into the XML namespace.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMAutoPtr_INCLUDED
+#define DOM_DOMAutoPtr_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+using Poco::AutoPtr;
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMAutoPtr_INCLUDED
diff --git a/Poco/DOM/CDATASection.h b/Poco/DOM/CDATASection.h
new file mode 100644
index 0000000..7a0e82b
--- /dev/null
+++ b/Poco/DOM/CDATASection.h
@@ -0,0 +1,84 @@
+//
+// CDATASection.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM CDATASection class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_CDATASection_INCLUDED
+#define DOM_CDATASection_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/Text.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API CDATASection: public Text
+	/// CDATA sections are used to escape blocks of text containing characters that
+	/// would otherwise be regarded as markup. The only delimiter that is recognized
+	/// in a CDATA section is the "]]>" string that ends the CDATA section. CDATA
+	/// sections cannot be nested. Their primary purpose is for including material
+	/// such as XML fragments, without needing to escape all the delimiters.
+	/// 
+	/// The DOMString attribute of the Text node holds the text that is contained
+	/// by the CDATA section. Note that this may contain characters that need to
+	/// be escaped outside of CDATA sections and that, depending on the character
+	/// encoding ("charset") chosen for serialization, it may be impossible to write
+	/// out some characters as part of a CDATA section.
+	/// 
+	/// The CDATASection interface inherits from the CharacterData interface through
+	/// the Text interface. Adjacent CDATASection nodes are not merged by use of
+	/// the normalize method on the Element interface.
+	/// 
+	/// Note: Because no markup is recognized within a CDATASection, character numeric
+	/// references cannot be used as an escape mechanism when serializing. Therefore,
+	/// action needs to be taken when serializing a CDATASection with a character
+	/// encoding where some of the contained characters cannot be represented. Failure
+	/// to do so would not produce well-formed XML.
+	/// One potential solution in the serialization process is to end the CDATA
+	/// section before the character, output the character using a character reference
+	/// or entity reference, and open a new CDATA section for any further characters
+	/// in the text node. Note, however, that some code conversion libraries at
+	/// the time of writing do not return an error or exception when a character
+	/// is missing from the encoding, making the task of ensuring that data is not
+	/// corrupted on serialization more difficult.
+{
+public:
+	// Text
+	Text* splitText(unsigned long offset);
+
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	CDATASection(Document* pOwnerDocument, const XMLString& data);
+	CDATASection(Document* pOwnerDocument, const CDATASection& sec);
+	~CDATASection();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	static const XMLString NODE_NAME;
+	
+	friend class Document;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_CDATASection_INCLUDED
diff --git a/Poco/DOM/CharacterData.h b/Poco/DOM/CharacterData.h
new file mode 100644
index 0000000..af5697d
--- /dev/null
+++ b/Poco/DOM/CharacterData.h
@@ -0,0 +1,123 @@
+//
+// CharacterData.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM CharacterData class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_CharacterData_INCLUDED
+#define DOM_CharacterData_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractNode.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API CharacterData: public AbstractNode
+	/// The CharacterData interface extends Node with a set of attributes and methods
+	/// for accessing character data in the DOM. For clarity this set is defined
+	/// here rather than on each object that uses these attributes and methods.
+	/// No DOM objects correspond directly to CharacterData, though Text and others
+	/// do inherit the interface from it. All offsets in this interface start from 0.
+	/// 
+	/// Text strings in the DOM are represented in either UTF-8 (if XML_UNICODE_WCHAR_T is
+	/// not defined) or in UTF-16 (if XML_UNICODE_WCHAR_T is defined).
+	/// Indexing on character data is done in XMLChar units.
+{
+public:
+	const XMLString& data() const;
+		/// Returns the character data of the node that 
+		/// implements the interface.
+	
+	const XMLString& getData() const;
+		/// Returns the character data of the node that 
+		/// implements the interface.
+
+	void setData(const XMLString& data);
+		/// Sets the character data of the node that
+		/// implements the interface.
+
+	unsigned long length() const;
+		/// Returns the number of XMLChars that are available
+		/// through getData and substringData. This may have the
+		/// value zero.
+
+	XMLString substringData(unsigned long offset, unsigned long count) const;
+		/// Extracts a range of data from the node.
+		/// If offset and count exceeds the length, then all
+		/// the characters to the end of the data are returned.
+
+	void appendData(const XMLString& arg);
+		/// Append the string to the end of the character data
+		/// of the node.
+
+	void insertData(unsigned long offset, const XMLString& arg);
+		/// Insert a string at the specified character offset.
+
+	void deleteData(unsigned long offset, unsigned long count);
+		/// Remove a range of characters from the node.
+
+	void replaceData(unsigned long offset, unsigned long count, const XMLString& arg);
+		/// Replace the characters starting at the specified character
+		/// offset with the specified string.
+
+	// Non-standard extensions
+	XMLString trimmedData() const;
+		/// Returns the character data of that node with
+		/// all surrounding whitespace removed.
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+	// Node
+	const XMLString& getNodeValue() const;
+	void setNodeValue(const XMLString& value);
+
+protected:
+	CharacterData(Document* pOwnerDocument, const XMLString& data);
+	CharacterData(Document* pOwnerDocument, const CharacterData& data);
+	~CharacterData();
+
+private:
+	XMLString _data;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& CharacterData::data() const
+{
+	return _data;
+}
+
+
+inline const XMLString& CharacterData::getData() const
+{
+	return _data;
+}
+
+
+inline unsigned long CharacterData::length() const
+{
+	return (unsigned long) _data.length();
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_CharacterData_INCLUDED
diff --git a/Poco/DOM/ChildNodesList.h b/Poco/DOM/ChildNodesList.h
new file mode 100644
index 0000000..aa7ece1
--- /dev/null
+++ b/Poco/DOM/ChildNodesList.h
@@ -0,0 +1,55 @@
+//
+// ChildNodesList.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the ChildNodesList class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_ChildNodesList_INCLUDED
+#define DOM_ChildNodesList_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/NodeList.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API ChildNodesList: public NodeList
+	// This implementation of NodeList is returned
+	// by Node::getChildNodes().
+{
+public:
+	Node* item(unsigned long index) const;
+	unsigned long length() const;
+
+	void autoRelease();
+
+protected:
+	ChildNodesList(const Node* pParent);
+	~ChildNodesList();
+	
+private:
+	ChildNodesList();
+
+	const Node* _pParent;
+	
+	friend class AbstractNode;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_ChildNodesList_INCLUDED
diff --git a/Poco/DOM/Comment.h b/Poco/DOM/Comment.h
new file mode 100644
index 0000000..d1de793
--- /dev/null
+++ b/Poco/DOM/Comment.h
@@ -0,0 +1,58 @@
+//
+// Comment.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Comment class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Comment_INCLUDED
+#define DOM_Comment_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/CharacterData.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Comment: public CharacterData
+	/// This interface inherits from CharacterData and represents the content of
+	/// a comment, i.e., all the characters between the starting '<!--' and ending
+	/// '-->'. Note that this is the definition of a comment in XML, and, in practice,
+	/// HTML, although some HTML tools may implement the full SGML comment structure.
+{
+public:
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	Comment(Document* pOwnerDocument, const XMLString& data);
+	Comment(Document* pOwnerDocument, const Comment& comment);
+	~Comment();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	static const XMLString NODE_NAME;
+	
+	friend class Document;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Comment_INCLUDED
diff --git a/Poco/DOM/DOMBuilder.h b/Poco/DOM/DOMBuilder.h
new file mode 100644
index 0000000..ad91da4
--- /dev/null
+++ b/Poco/DOM/DOMBuilder.h
@@ -0,0 +1,112 @@
+//
+// DOMBuilder.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMBuilder
+//
+// Definition of the DOMBuilder class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMBuilder_INCLUDED
+#define DOM_DOMBuilder_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/ContentHandler.h"
+#include "Poco/SAX/LexicalHandler.h"
+#include "Poco/SAX/DTDHandler.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XMLReader;
+class Document;
+class InputSource;
+class AbstractNode;
+class AbstractContainerNode;
+class NamePool;
+
+
+class XML_API DOMBuilder: protected DTDHandler, protected ContentHandler, protected LexicalHandler
+	/// This class builds a tree representation of an
+	/// XML document, according to the W3C Document Object Model, Level 1 and 2
+	/// specifications.
+	///
+	/// The actual XML parsing is done by an XMLReader, which
+	/// must be supplied to the DOMBuilder.
+{
+public:
+	DOMBuilder(XMLReader& xmlReader, NamePool* pNamePool = 0);
+		/// Creates a DOMBuilder using the given XMLReader. 
+		/// If a NamePool is given, it becomes the Document's NamePool.
+
+	virtual ~DOMBuilder();
+		/// Destroys the DOMBuilder.
+
+	virtual Document* parse(const XMLString& uri);
+		/// Parse an XML document from a location identified by an URI.
+
+	virtual Document* parse(InputSource* pInputSource);
+		/// Parse an XML document from a location identified by an InputSource.
+
+	virtual Document* parseMemoryNP(const char* xml, std::size_t size);
+		/// Parses an XML document from memory.
+
+protected:
+	// DTDHandler
+	void notationDecl(const XMLString& name, const XMLString* publicId, const XMLString* systemId);
+	void unparsedEntityDecl(const XMLString& name, const XMLString* publicId, const XMLString& systemId, const XMLString& notationName);
+
+	// ContentHandler
+	void setDocumentLocator(const Locator* loc);
+	void startDocument();
+	void endDocument();
+	void startElement(const XMLString& uri, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+	void endElement(const XMLString& uri, const XMLString& localName, const XMLString& qname);
+	void characters(const XMLChar ch[], int start, int length);
+	void ignorableWhitespace(const XMLChar ch[], int start, int length);
+	void processingInstruction(const XMLString& target, const XMLString& data);
+	void startPrefixMapping(const XMLString& prefix, const XMLString& uri);
+	void endPrefixMapping(const XMLString& prefix);
+	void skippedEntity(const XMLString& name);
+
+	// LexicalHandler
+	void startDTD(const XMLString& name, const XMLString& publicId, const XMLString& systemId);
+	void endDTD();
+	void startEntity(const XMLString& name);
+	void endEntity(const XMLString& name);
+	void startCDATA();
+	void endCDATA();
+	void comment(const XMLChar ch[], int start, int length); 
+
+	void appendNode(AbstractNode* pNode);
+	
+	void setupParse();
+
+private:
+	static const XMLString EMPTY_STRING;
+
+	XMLReader&             _xmlReader;
+	NamePool*              _pNamePool;
+	Document*              _pDocument;
+	AbstractContainerNode* _pParent;
+	AbstractNode*          _pPrevious;
+	bool                   _inCDATA;
+	bool                   _namespaces;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMBuilder_INCLUDED
diff --git a/Poco/DOM/DOMException.h b/Poco/DOM/DOMException.h
new file mode 100644
index 0000000..7c7c3ae
--- /dev/null
+++ b/Poco/DOM/DOMException.h
@@ -0,0 +1,112 @@
+//
+// DOMException.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM DOMException class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMException_INCLUDED
+#define DOM_DOMException_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLException.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API DOMException: public XMLException
+	/// DOM operations only raise exceptions in "exceptional" circumstances, i.e.,
+	/// when an operation is impossible to perform (either for logical reasons,
+	/// because data is lost, or because the implementation has become unstable).
+	/// In general, DOM methods return specific error values in ordinary processing
+	/// situations, such as out-of-bound errors when using NodeList.
+	/// 
+	/// Implementations should raise other exceptions under other circumstances.
+	/// For example, implementations should raise an implementation-dependent exception
+	/// if a null argument is passed when null was not expected.
+{
+public:
+	enum
+	{
+		INDEX_SIZE_ERR = 1,          /// index or size is negative or greater than allowed value
+		DOMSTRING_SIZE_ERR,          /// the specified range of text does not fit into a DOMString (not used)
+		HIERARCHY_REQUEST_ERR,       /// a node is inserted somewhere it doesn't belong
+		WRONG_DOCUMENT_ERR,          /// a node is used in a different document than the one that created it
+		INVALID_CHARACTER_ERR,       /// an invalid character is specified (not used)
+		NO_DATA_ALLOWED_ERR,         /// data is specified for a node which does not support data
+		NO_MODIFICATION_ALLOWED_ERR, /// an attempt is made to modify an object where modifications are not allowed
+		NOT_FOUND_ERR,               /// an attempt was made to reference a node in a context where it does not exist
+		NOT_SUPPORTED_ERR,           /// the implementation does not support the type of object requested
+		INUSE_ATTRIBUTE_ERR,         /// an attempt is made to add an attribute that is already in use elsewhere
+		INVALID_STATE_ERR,           /// a parameter or an operation is not supported by the underlying object
+		SYNTAX_ERR,                  /// an invalid or illegal string is specified
+		INVALID_MODIFICATION_ERR,    /// an attempt is made to modify the type of the underlying object
+		NAMESPACE_ERR,               /// an attempt is made to create or change an object in a way which is incorrect with regard to namespaces
+		INVALID_ACCESS_ERR,          /// an attempt is made to use an object that is not, or is no longer, usable
+		
+		_NUMBER_OF_MESSAGES
+	};
+
+	DOMException(unsigned short code);
+		/// Creates a DOMException with the given error code.
+		
+	DOMException(const DOMException& exc);
+		/// Creates a DOMException by copying another one.
+		
+	~DOMException() throw();
+		/// Destroys the DOMException.
+		
+	DOMException& operator = (const DOMException& exc);
+
+	const char* name() const throw();
+		/// Returns a static string describing the exception.
+
+	const char* className() const throw();
+		/// Returns the name of the exception class.
+
+	Poco::Exception* clone() const;
+		/// Creates an exact copy of the exception.
+		
+	void rethrow() const;
+		/// (Re)Throws the exception.
+
+	unsigned short code() const;
+		/// Returns the DOM exception code.
+
+protected:
+	static const std::string& message(unsigned short code);
+	
+private:
+	DOMException();
+	
+	unsigned short _code;
+	
+	static const std::string MESSAGES[_NUMBER_OF_MESSAGES];
+};
+
+
+//
+// inlines
+//
+inline unsigned short DOMException::code() const
+{
+	return _code;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMException_INCLUDED
diff --git a/Poco/DOM/DOMImplementation.h b/Poco/DOM/DOMImplementation.h
new file mode 100644
index 0000000..0c2d7af
--- /dev/null
+++ b/Poco/DOM/DOMImplementation.h
@@ -0,0 +1,82 @@
+//
+// DOMImplementation.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM DOMImplementation class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMImplementation_INCLUDED
+#define DOM_DOMImplementation_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class DocumentType;
+class Document;
+class NamePool;
+
+
+class XML_API DOMImplementation
+	/// The DOMImplementation interface provides a number of methods for
+	/// performing operations that are independent of any particular instance
+	/// of the document object model.
+	/// In this implementation, DOMImplementation is implemented as a singleton.
+{
+public:
+	DOMImplementation();
+		/// Creates the DOMImplementation.
+		
+	~DOMImplementation();
+		/// Destroys the DOMImplementation.
+
+	bool hasFeature(const XMLString& feature, const XMLString& version) const;
+		/// Tests if the DOM implementation implements a specific feature.
+		///
+		/// The only supported features are "XML", version "1.0" and "Core", 
+		/// "Events", "MutationEvents" and "Traversal", version "2.0".
+	
+	// DOM Level 2
+	DocumentType* createDocumentType(const XMLString& name, const XMLString& publicId, const XMLString& systemId) const;
+		/// Creates an empty DocumentType node. Entity declarations and notations 
+		/// are not made available. Entity reference expansions and default attribute 
+		/// additions do not occur.
+
+	Document* createDocument(const XMLString& namespaceURI, const XMLString& qualifiedName, DocumentType* doctype) const;
+		/// Creates an XML Document object of the specified type with its document element.
+		///
+		/// Note: You can also create a Document directly using the new operator.
+
+	static const DOMImplementation& instance();
+		/// Returns a reference to the default DOMImplementation
+		/// object.
+		
+private:
+	static const XMLString FEATURE_XML;
+	static const XMLString FEATURE_CORE;
+	static const XMLString FEATURE_EVENTS;
+	static const XMLString FEATURE_MUTATIONEVENTS;
+	static const XMLString FEATURE_TRAVERSAL;
+	static const XMLString VERSION_1_0;
+	static const XMLString VERSION_2_0;	
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMImplementation_INCLUDED
diff --git a/Poco/DOM/DOMObject.h b/Poco/DOM/DOMObject.h
new file mode 100644
index 0000000..40b29fb
--- /dev/null
+++ b/Poco/DOM/DOMObject.h
@@ -0,0 +1,103 @@
+//
+// DOMObject.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOMObject class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMObject_INCLUDED
+#define DOM_DOMObject_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API DOMObject
+	/// The base class for all objects in the Document Object Model.
+	///
+	/// DOMObject defines the rules for memory management
+	/// in this implementation of the DOM. Violation of these
+	/// rules, which are outlined in the following, results
+	/// in memory leaks or dangling pointers.
+	///
+	/// Every object created by new or by a factory
+	/// method (for example, Document::create*) must be released
+	/// with a call to release() or autoRelease() when it
+	/// is no longer needed.
+	///
+	/// Every object created by cloning or importing another
+	/// object must be released.
+	/// For every call to duplicate() there must be a matching
+	/// call to release().
+	/// An object obtained via any other way must not be
+	/// released, except ownership of it has been explicitly
+	/// taken with a call to duplicate().
+	///
+	/// While DOMObjects are safe for use in multithreaded programs,
+	/// a DOMObject or one of its subclasses must not be accessed
+	/// from multiple threads simultaneously.
+{
+public:
+	DOMObject();
+		/// Creates the DOMObject.
+		/// The object's reference count is initialized to one.
+
+	void duplicate() const;
+		/// Increases the object's reference count.
+
+	void release() const;
+		/// Decreases the object's reference count.
+		/// If the reference count reaches zero,
+		/// the object is deleted.
+		
+	virtual void autoRelease() = 0;
+		/// Adds the object to an appropriate
+		/// AutoReleasePool, which is usually the
+		/// AutoReleasePool managed by the Document
+		/// to which this object belongs.
+
+protected:
+	virtual ~DOMObject();
+		/// Destroys the DOMObject.
+
+private:
+	DOMObject(const DOMObject&);
+	DOMObject& operator = (const DOMObject&);
+	
+	mutable int _rc;
+};
+
+
+//
+// inlines
+//
+inline void DOMObject::duplicate() const
+{
+	++_rc;
+}
+
+
+inline void DOMObject::release() const
+{
+	if (--_rc == 0)
+		delete this;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMObject_INCLUDED
diff --git a/Poco/DOM/DOMParser.h b/Poco/DOM/DOMParser.h
new file mode 100644
index 0000000..69d0f5a
--- /dev/null
+++ b/Poco/DOM/DOMParser.h
@@ -0,0 +1,114 @@
+//
+// DOMParser.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMParser
+//
+// Definition of the DOMParser class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMParser_INCLUDED
+#define DOM_DOMParser_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/SAXParser.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class NamePool;
+class Document;
+class InputSource;
+class EntityResolver;
+
+
+class XML_API DOMParser
+	/// This is a convenience class that combines a
+	/// DOMBuilder with a SAXParser, with the optional
+	/// support of a WhitespaceFilter.
+{
+public:
+	explicit DOMParser(NamePool* pNamePool = 0);
+		/// Creates a new DOMParser. 
+		/// If a NamePool is given, it becomes the Document's NamePool.
+		
+	explicit DOMParser(unsigned long namePoolSize);
+		/// Creates a new DOMParser, using the given NamePool size.
+		///
+		/// The given namePoolSize should be a suitable prime number, 
+		/// e.g. 251, 509, 1021 or 4093, depending on the expected
+		/// size of the document.
+
+	~DOMParser();
+		/// Destroys the DOMParser.
+
+	void setEncoding(const XMLString& encoding);
+		/// Sets the encoding used by the parser if no
+		/// encoding is specified in the XML document.
+		
+	const XMLString& getEncoding() const;
+		/// Returns the name of the encoding used by
+		/// the parser if no encoding is specified in
+		/// the XML document.
+
+	void addEncoding(const XMLString& name, Poco::TextEncoding* pEncoding);
+		/// Adds an encoding to the parser.
+
+	void setFeature(const XMLString& name, bool state);
+		/// Set the state of a feature.
+		///
+		/// If a feature is not recognized by the DOMParser, it is
+		/// passed on to the underlying XMLReader.
+		///
+		/// The only currently supported feature is
+		/// http://www.appinf.com/features/no-whitespace-in-element-content
+		/// which, when activated, causes the WhitespaceFilter to
+		/// be used.
+
+	bool getFeature(const XMLString& name) const;
+		/// Look up the value of a feature.
+		///
+		/// If a feature is not recognized by the DOMParser, the
+		/// DOMParser queries the underlying SAXParser for the feature.
+
+	Document* parse(const XMLString& uri);
+		/// Parse an XML document from a location identified by an URI.
+
+	Document* parse(InputSource* pInputSource);
+		/// Parse an XML document from a location identified by an InputSource.
+
+	Document* parseString(const std::string& xml);
+		/// Parse an XML document from a string.
+
+	Document* parseMemory(const char* xml, std::size_t size);
+		/// Parse an XML document from memory.
+
+	EntityResolver* getEntityResolver() const;
+		/// Returns the entity resolver used by the underlying SAXParser.
+
+	void setEntityResolver(EntityResolver* pEntityResolver);
+		/// Sets the entity resolver on the underlying SAXParser.
+
+	static const XMLString FEATURE_FILTER_WHITESPACE;
+	
+private:
+	SAXParser _saxParser;
+	NamePool* _pNamePool;
+	bool      _filterWhitespace;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMParser_INCLUDED
diff --git a/Poco/DOM/DOMSerializer.h b/Poco/DOM/DOMSerializer.h
new file mode 100644
index 0000000..b535105
--- /dev/null
+++ b/Poco/DOM/DOMSerializer.h
@@ -0,0 +1,122 @@
+//
+// DOMSerializer.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMSerializer
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMSerializer_INCLUDED
+#define DOM_DOMSerializer_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/XMLReader.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+class Element;
+class Text;
+class Comment;
+class ProcessingInstruction;
+class Entity;
+class CDATASection;
+class Notation;
+class Document;
+class DocumentType;
+class DocumentFragment;
+class DeclHandler;
+class LexicalHandler;
+
+
+class XML_API DOMSerializer: public XMLReader
+	/// The DOMSerializer serializes a DOM document
+	/// into a sequence of SAX events which are
+	/// reported to the registered SAX event
+	/// handlers.
+	///
+	/// The DOMWriter uses a DOMSerializer with an
+	/// XMLWriter to serialize a DOM document into
+	/// textual XML.
+{
+public:
+	DOMSerializer();
+		/// Creates the DOMSerializer.
+		
+	~DOMSerializer();
+		/// Destroys the DOMSerializer.
+		
+	void serialize(const Node* pNode);
+		/// Serializes a DOM node and its children
+		/// into a sequence of SAX events, which are
+		/// reported to the registered SAX event
+		/// handlers.
+
+	// XMLReader
+	void setEntityResolver(EntityResolver* pResolver);
+	EntityResolver* getEntityResolver() const;
+	void setDTDHandler(DTDHandler* pDTDHandler);
+	DTDHandler* getDTDHandler() const;
+	void setContentHandler(ContentHandler* pContentHandler);
+	ContentHandler* getContentHandler() const;
+	void setErrorHandler(ErrorHandler* pErrorHandler);
+	ErrorHandler* getErrorHandler() const;
+
+	void setFeature(const XMLString& featureId, bool state);
+	bool getFeature(const XMLString& featureId) const;
+	void setProperty(const XMLString& propertyId, const XMLString& value);
+	void setProperty(const XMLString& propertyId, void* value);
+	void* getProperty(const XMLString& propertyId) const;
+
+protected:
+	void parse(InputSource* pSource);
+		/// The DOMSerializer cannot parse an InputSource,
+		/// so this method simply throws an XMLException when invoked.
+		
+	void parse(const XMLString& systemId);
+		/// The DOMSerializer cannot parse from a system identifier,
+		/// so this method simply throws an XMLException when invoked.
+
+	void parseMemoryNP(const char* xml, std::size_t size);
+		/// The DOMSerializer cannot parse from a system identifier,
+		/// so this method simply throws an XMLException when invoked.
+
+	void iterate(const Node* pNode) const;
+	void handleNode(const Node* pNode) const;
+	void handleElement(const Element* pElement) const;
+	void handleCharacterData(const Text* pText) const;
+	void handleComment(const Comment* pComment) const;
+	void handlePI(const ProcessingInstruction* pPI) const;
+	void handleCDATASection(const CDATASection* pCDATA) const;
+	void handleDocument(const Document* pDocument) const;
+	void handleDocumentType(const DocumentType* pDocumentType) const;
+	void handleFragment(const DocumentFragment* pFragment) const;
+	void handleNotation(const Notation* pNotation) const;
+	void handleEntity(const Entity* pEntity) const;
+
+private:
+	EntityResolver* _pEntityResolver;
+	DTDHandler*     _pDTDHandler;
+	ContentHandler* _pContentHandler;
+	ErrorHandler*   _pErrorHandler;
+	DeclHandler*    _pDeclHandler;
+	LexicalHandler* _pLexicalHandler;
+	
+	static const XMLString CDATA;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMSerializer_INCLUDED
diff --git a/Poco/DOM/DOMWriter.h b/Poco/DOM/DOMWriter.h
new file mode 100644
index 0000000..5a5132d
--- /dev/null
+++ b/Poco/DOM/DOMWriter.h
@@ -0,0 +1,127 @@
+//
+// DOMWriter.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMWriter
+//
+// Definition of class DOMWriter.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DOMWriter_INCLUDED
+#define DOM_DOMWriter_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/XML/XMLStream.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+class Document;
+
+
+class XML_API DOMWriter
+	/// The DOMWriter uses a DOMSerializer with an
+	/// XMLWriter to serialize a DOM document into
+	/// textual XML.
+{
+public:
+	DOMWriter();
+		/// Creates a DOMWriter.
+		
+	~DOMWriter();
+		/// Destroys a DOMWriter.
+
+	void setEncoding(const std::string& encodingName, Poco::TextEncoding& textEncoding);
+		/// Sets the encoding, which will be reflected in the written XML declaration.
+
+	const std::string& getEncoding() const;
+		/// Returns the encoding name set with setEncoding.
+
+	void setOptions(int options);
+		/// Sets options for the internal XMLWriter.
+		///
+		/// See class XMLWriter for available options.
+
+	int getOptions() const;
+		/// Returns the options for the internal XMLWriter.
+
+	void setNewLine(const std::string& newLine);
+		/// Sets the line ending characters for the internal
+		/// XMLWriter. See XMLWriter::setNewLine() for a list
+		/// of supported values. 
+
+	const std::string& getNewLine() const;
+		/// Returns the line ending characters used by the
+		/// internal XMLWriter.
+
+	void setIndent(const std::string& indent);
+		/// Sets the string used for one indentation step.
+		///
+		/// The default is a single TAB character.
+		/// The given string should only contain TAB or SPACE
+		/// characters (e.g., a single TAB character, or
+		/// two to four SPACE characters).
+		
+	const std::string& getIndent() const;
+		/// Returns the string used for one indentation step.
+
+	void writeNode(XMLByteOutputStream& ostr, const Node* pNode);
+		/// Writes the XML for the given node to the specified stream.
+
+	void writeNode(const std::string& systemId, const Node* pNode);
+		/// Writes the XML for the given node to the file specified in systemId,
+		/// using a standard file output stream (Poco::FileOutputStream).
+
+private:
+	std::string         _encodingName;
+	Poco::TextEncoding* _pTextEncoding;
+	int                 _options;
+	std::string         _newLine;
+	std::string         _indent;
+};
+
+
+//
+// inlines
+//
+inline const std::string& DOMWriter::getEncoding() const
+{
+	return _encodingName;
+}
+
+
+inline int DOMWriter::getOptions() const
+{
+	return _options;
+}
+
+
+inline const std::string& DOMWriter::getNewLine() const
+{
+	return _newLine;
+}
+
+
+inline const std::string& DOMWriter::getIndent() const
+{
+	return _indent;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DOMWriter_INCLUDED
diff --git a/Poco/DOM/DTDMap.h b/Poco/DOM/DTDMap.h
new file mode 100644
index 0000000..2a475c3
--- /dev/null
+++ b/Poco/DOM/DTDMap.h
@@ -0,0 +1,67 @@
+//
+// DTDMap.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DTDMap class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DTDMap_INCLUDED
+#define DOM_DTDMap_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/NamedNodeMap.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class DocumentType;
+
+
+class XML_API DTDMap: public NamedNodeMap
+	/// This implementation of NamedNodeMap
+	/// is returned by DocumentType::entities()
+	/// and DocumentType::notations(). 
+{
+public:
+	Node* getNamedItem(const XMLString& name) const;
+	Node* setNamedItem(Node* arg);
+	Node* removeNamedItem(const XMLString& name);
+	Node* item(unsigned long index) const;
+	unsigned long length() const;
+
+	Node* getNamedItemNS(const XMLString& namespaceURI, const XMLString& localName) const;
+	Node* setNamedItemNS(Node* arg);
+	Node* removeNamedItemNS(const XMLString& namespaceURI, const XMLString& localName);
+
+	void autoRelease();
+
+protected:
+	DTDMap(const DocumentType* pDocumentType, unsigned short type);
+	~DTDMap();
+
+private:
+	DTDMap();
+	
+	const DocumentType* _pDocumentType;
+	unsigned short _type;
+	
+	friend class DocumentType;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DTDMap_INCLUDED
diff --git a/Poco/DOM/Document.h b/Poco/DOM/Document.h
new file mode 100644
index 0000000..e66c0e6
--- /dev/null
+++ b/Poco/DOM/Document.h
@@ -0,0 +1,285 @@
+//
+// Document.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Document class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Document_INCLUDED
+#define DOM_Document_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractContainerNode.h"
+#include "Poco/DOM/DocumentEvent.h"
+#include "Poco/DOM/Element.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/XML/NamePool.h"
+#include "Poco/AutoReleasePool.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class NamePool;
+class DocumentType;
+class DOMImplementation;
+class DocumentFragment;
+class Text;
+class Comment;
+class CDATASection;
+class ProcessingInstruction;
+class Attr;
+class EntityReference;
+class NodeList;
+class Entity;
+class Notation;
+
+
+class XML_API Document: public AbstractContainerNode, public DocumentEvent
+	/// The Document interface represents the entire HTML or XML document. Conceptually, 
+	/// it is the root of the document tree, and provides the primary access to the 
+	/// document's data.
+	///
+	/// Since elements, text nodes, comments, processing instructions, etc. cannot exist 
+	/// outside the context of a Document, the Document interface also contains the 
+	/// factory methods needed to create these objects. The Node objects created have a 
+	/// ownerDocument attribute which associates them with the Document within whose 
+	/// context they were created.
+{
+public:
+	typedef Poco::AutoReleasePool<DOMObject> AutoReleasePool;
+
+	explicit Document(NamePool* pNamePool = 0);
+		/// Creates a new document. If pNamePool == 0, the document
+		/// creates its own name pool, otherwise it uses the given name pool.
+		/// Sharing a name pool makes sense for documents containing instances
+		/// of the same schema, thus reducing memory usage.
+		
+	explicit Document(unsigned long namePoolSize);
+		/// Creates a new document using a name pool with the given size, which
+		/// should be a prime number (e.g., 251, 509, 1021, 4093).
+
+	Document(DocumentType* pDocumentType, NamePool* pNamePool = 0);
+		/// Creates a new document. If pNamePool == 0, the document
+		/// creates its own name pool, otherwise it uses the given name pool.
+		/// Sharing a name pool makes sense for documents containing instances
+		/// of the same schema, thus reducing memory usage.
+
+	Document(DocumentType* pDocumentType, unsigned long namePoolSize);
+		/// Creates a new document using a name pool with the given size, which
+		/// should be a prime number (e.g., 251, 509, 1021, 4093).
+
+	NamePool& namePool();
+		/// Returns a pointer to the documents Name Pool.
+
+	AutoReleasePool& autoReleasePool();
+		/// Returns a pointer to the documents Auto Release Pool.
+
+	void collectGarbage();
+		/// Releases all objects in the Auto Release Pool.
+
+	void suspendEvents();
+		/// Suspends all events until resumeEvents() is called.
+
+	void resumeEvents();
+		/// Resumes all events suspended with suspendEvent();
+
+	bool eventsSuspended() const;
+		/// Returns true if events are suspended.
+
+	bool events() const;
+		/// Returns true if events are not suspended.
+
+	const DocumentType* doctype() const;
+		/// The Document Type Declaration (see DocumentType) associated with this document.
+		/// For HTML documents as well as XML documents without a document type declaration
+		/// this returns null. The DOM Level 1 does not support editing the Document
+		/// Type Declaration. docType cannot be altered in any way, including through
+		/// the use of methods inherited from the Node interface, such as insertNode
+		/// or removeNode.
+
+	const DOMImplementation& implementation() const;
+		/// The DOMImplementation object that handles this document. A DOM application
+		/// may use objects from multiple implementations.
+
+	Element* documentElement() const;
+		/// This is a convenience attribute that allows direct access to the child node
+		/// that is the root element of the document. For HTML documents, this is the
+		/// element with the tagName "HTML".
+
+	Element* createElement(const XMLString& tagName) const;
+		/// Creates an element of the type specified. Note that the instance returned
+		/// implements the Element interface, so attributes can be specified directly
+		/// on the returned object.
+		///
+		/// In addition, if there are known attributes with default values, Attr nodes
+		/// representing them are automatically created and attached to the element.
+
+	DocumentFragment* createDocumentFragment() const;
+		/// Creates an empty DocumentFragment object.
+
+	Text* createTextNode(const XMLString& data) const;
+		/// Creates a text node given the specified string.
+
+	Comment* createComment(const XMLString& data) const;
+		/// Creates a comment node given the specified string.
+
+	CDATASection* createCDATASection(const XMLString& data) const;
+		/// Creates a CDATASection node whose value is the specified string.
+
+	ProcessingInstruction* createProcessingInstruction(const XMLString& target, const XMLString& data) const;
+		/// Creates a ProcessingInstruction node given the specified target and data strings.
+
+	Attr* createAttribute(const XMLString& name) const;	
+		/// Creates an Attr of the given name. Note that the Attr instance can then
+		/// be set on an Element using the setAttributeNode method.	
+
+	EntityReference* createEntityReference(const XMLString& name) const;
+		/// Creates an EntityReference object. In addition, if the referenced entity
+		/// is known, the child list of the EntityReference node is made the same as
+		/// that of the corresponding Entity node.
+
+	NodeList* getElementsByTagName(const XMLString& name) const;
+		/// Returns a NodeList of all Elements with a given tag name in the order
+		/// in which they would be encountered in a preorder traversal of the
+		/// document tree.
+		///
+		/// The returned NodeList must be released with a call to release()
+		/// when no longer needed.
+
+	// DOM Level 2
+	Node* importNode(Node* importedNode, bool deep);
+		/// Imports a node from another document to this document. The returned node
+		/// has no parent; (parentNode is null). The source node is not altered or removed
+		/// from the original document; this method creates a new copy of the source
+		/// node.
+		/// For all nodes, importing a node creates a node object owned by the importing
+		/// document, with attribute values identical to the source node's nodeName
+		/// and nodeType, plus the attributes related to namespaces (prefix, localName,
+		/// and namespaceURI). As in the cloneNode operation on a Node, the source node
+		/// is not altered.
+		/// Additional information is copied as appropriate to the nodeType, attempting
+		/// to mirror the behavior expected if a fragment of XML or HTML source was
+		/// copied from one document to another, recognizing that the two documents
+		/// may have different DTDs in the XML case.
+
+	Element* createElementNS(const XMLString& namespaceURI, const XMLString& qualifiedName) const;
+		/// Creates an element of the given qualified name and namespace URI.
+
+	Attr* createAttributeNS(const XMLString& namespaceURI, const XMLString& qualifiedName) const;
+		/// Creates an attribute of the given qualified name and namespace URI.
+
+	NodeList* getElementsByTagNameNS(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns a NodeList of all the Elements with a given local name and 
+		/// namespace URI in the order in which they are encountered in a 
+		/// preorder traversal of the Document tree.
+
+	Element* getElementById(const XMLString& elementId) const;
+		/// Returns the Element whose ID is given by elementId. If no such 
+		/// element exists, returns null. Behavior is not defined if more
+		/// than one element has this ID. 
+		///
+		/// Note: The DOM implementation must have information that says 
+		/// which attributes are of type ID. Attributes with the name "ID"
+		/// are not of type ID unless so defined. Implementations that do 
+		/// not know whether attributes are of type ID or not are expected to
+		/// return null. This implementation therefore returns null.
+		///
+		/// See also the non-standard two argument variant of getElementById()
+		/// and getElementByIdNS().
+
+	// DocumentEvent
+	Event* createEvent(const XMLString& eventType) const;
+
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+	// EventTarget
+	bool dispatchEvent(Event* evt);
+	
+	// Extensions
+	Entity* createEntity(const XMLString& name, const XMLString& publicId, const XMLString& systemId, const XMLString& notationName) const;
+		/// Creates an Entity with the given name, publicId, systemId and notationName.
+		///
+		/// This method is not part of the W3C Document Object Model.
+
+	Notation* createNotation(const XMLString& name, const XMLString& publicId, const XMLString& systemId) const;
+		/// Creates a Notation with the given name, publicId and systemId.
+		///
+		/// This method is not part of the W3C Document Object Model.
+
+	Element* getElementById(const XMLString& elementId, const XMLString& idAttribute) const;
+		/// Returns the first Element whose ID attribute (given in idAttribute)
+		/// has the given elementId. If no such element exists, returns null. 
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+	Element* getElementByIdNS(const XMLString& elementId, const XMLString& idAttributeURI, const XMLString& idAttributeLocalName) const;
+		/// Returns the first Element whose ID attribute (given in idAttributeURI and idAttributeLocalName)
+		/// has the given elementId. If no such element exists, returns null. 
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+protected:
+	~Document();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+	
+	DocumentType* getDoctype();
+	void setDoctype(DocumentType* pDoctype);
+
+private:
+	DocumentType*   _pDocumentType;
+	NamePool*       _pNamePool;
+	AutoReleasePool _autoReleasePool;
+	int             _eventSuspendLevel;
+
+	static const XMLString NODE_NAME;
+	
+	friend class DOMBuilder;
+};
+
+
+//
+// inlines
+//
+inline NamePool& Document::namePool()
+{
+	return *_pNamePool;
+}
+
+
+inline Document::AutoReleasePool& Document::autoReleasePool()
+{
+	return _autoReleasePool;
+}
+
+
+inline const DocumentType* Document::doctype() const
+{
+	return _pDocumentType;
+}
+
+
+inline DocumentType* Document::getDoctype()
+{
+	return _pDocumentType;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Document_INCLUDED
diff --git a/Poco/DOM/DocumentEvent.h b/Poco/DOM/DocumentEvent.h
new file mode 100644
index 0000000..14bcf27
--- /dev/null
+++ b/Poco/DOM/DocumentEvent.h
@@ -0,0 +1,65 @@
+//
+// DocumentEvent.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM DocumentEvent interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DocumentEvent_INCLUDED
+#define DOM_DocumentEvent_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Event;
+
+
+class XML_API DocumentEvent
+	/// The DocumentEvent interface provides a mechanism by which the user can create
+	/// an Event of a type supported by the implementation. It is expected that
+	/// the DocumentEvent interface will be implemented on the same object which
+	/// implements the Document interface in an implementation which supports the
+	/// Event model.
+{
+public:
+	virtual Event* createEvent(const XMLString& eventType) const = 0;
+		/// Creates an event of the specified type.
+		///
+		/// The eventType parameter specifies the type of Event interface to be created.
+		/// If the Event interface specified is supported by the implementation this
+		/// method will return a new Event of the interface type requested. If the Event
+		/// is to be dispatched via the dispatchEvent method the appropriate event init
+		/// method must be called after creation in order to initialize the Event's
+		/// values. As an example, a user wishing to synthesize some kind of UIEvent
+		/// would call createEvent with the parameter "UIEvents". The initUIEvent method
+		/// could then be called on the newly created UIEvent to set the specific type
+		/// of UIEvent to be dispatched and set its context information.
+		/// The createEvent method is used in creating Events when it is either inconvenient
+		/// or unnecessary for the user to create an Event themselves. In cases where
+		/// the implementation provided Event is insufficient, users may supply their
+		/// own Event implementations for use with the dispatchEvent method.
+
+protected:
+	virtual ~DocumentEvent();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DocumentEvent_INCLUDED
diff --git a/Poco/DOM/DocumentFragment.h b/Poco/DOM/DocumentFragment.h
new file mode 100644
index 0000000..105a217
--- /dev/null
+++ b/Poco/DOM/DocumentFragment.h
@@ -0,0 +1,84 @@
+//
+// DocumentFragment.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM DocumentFragment class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DocumentFragment_INCLUDED
+#define DOM_DocumentFragment_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractContainerNode.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API DocumentFragment: public AbstractContainerNode
+	/// DocumentFragment is a "lightweight" or "minimal" Document object. It is
+	/// very common to want to be able to extract a portion of a document's tree
+	/// or to create a new fragment of a document. Imagine implementing a user command
+	/// like cut or rearranging a document by moving fragments around. It is desirable
+	/// to have an object which can hold such fragments and it is quite natural
+	/// to use a Node for this purpose. While it is true that a Document object
+	/// could fulfill this role, a Document object can potentially be a heavyweight
+	/// object, depending on the underlying implementation. What is really needed
+	/// for this is a very lightweight object. DocumentFragment is such an object.
+	/// 
+	/// Furthermore, various operations -- such as inserting nodes as children of
+	/// another Node -- may take DocumentFragment objects as arguments; this results
+	/// in all the child nodes of the DocumentFragment being moved to the child
+	/// list of this node.
+	/// 
+	/// The children of a DocumentFragment node are zero or more nodes representing
+	/// the tops of any sub-trees defining the structure of the document. DocumentFragment
+	/// nodes do not need to be well-formed XML documents (although they do need
+	/// to follow the rules imposed upon well-formed XML parsed entities, which
+	/// can have multiple top nodes). For example, a DocumentFragment might have
+	/// only one child and that child node could be a Text node. Such a structure
+	/// model represents neither an HTML document nor a well-formed XML document.
+	/// 
+	/// When a DocumentFragment is inserted into a Document (or indeed any other
+	/// Node that may take children) the children of the DocumentFragment and not
+	/// the DocumentFragment itself are inserted into the Node. This makes the DocumentFragment
+	/// very useful when the user wishes to create nodes that are siblings; the
+	/// DocumentFragment acts as the parent of these nodes so that the user can
+	/// use the standard methods from the Node interface, such as insertBefore and
+	/// appendChild.
+{
+public:
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	DocumentFragment(Document* pOwnerDocument);
+	DocumentFragment(Document* pOwnerDocument, const DocumentFragment& fragment);
+	~DocumentFragment();
+	
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	static const XMLString NODE_NAME;
+	
+	friend class Document;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DocumentFragment_INCLUDED
diff --git a/Poco/DOM/DocumentType.h b/Poco/DOM/DocumentType.h
new file mode 100644
index 0000000..3d89097
--- /dev/null
+++ b/Poco/DOM/DocumentType.h
@@ -0,0 +1,125 @@
+//
+// DocumentType.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM DocumentType class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_DocumentType_INCLUDED
+#define DOM_DocumentType_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractContainerNode.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class NamedNodeMap;
+
+
+class XML_API DocumentType: public AbstractContainerNode
+	/// Each Document has a doctype attribute whose value is either null or a DocumentType
+	/// object. The DocumentType interface in the DOM Level 1 Core provides an
+	/// interface to the list of entities that are defined for the document, and
+	/// little else because the effect of namespaces and the various XML scheme
+	/// efforts on DTD representation are not clearly understood as of this writing.
+	/// 
+	/// The DOM Level 1 doesn't support editing DocumentType nodes.
+{
+public:
+	const XMLString& name() const;
+		/// The name of the DTD; i.e., the name immediately following the 
+		/// DOCTYPE keyword.
+
+	NamedNodeMap* entities() const;
+		/// A NamedNodeMap containing the general entities,
+		/// both external and internal, declared in the DTD.
+		/// Duplicates are discarded.
+		///
+		/// Note: In this implementation, only the
+		/// external entities are reported.
+		/// Every node in this map also implements the
+		/// Entity interface.
+		/// 
+		/// The returned NamedNodeMap must be released with a call
+		/// to release() when no longer needed.
+
+	NamedNodeMap* notations() const;
+		/// A NamedNodeMap containing the notations declared in the DTD. Duplicates
+		/// are discarded. Every node in this map also implements the Notation interface.
+		/// The DOM Level 1 does not support editing notations, therefore notations
+		/// cannot be altered in any way.
+		/// 
+		/// The returned NamedNodeMap must be released with a call
+		/// to release() when no longer needed.
+
+	// DOM Level 2
+	const XMLString& publicId() const;
+		/// Returns the public identifier of the external DTD subset.
+
+	const XMLString& systemId() const;
+		/// Returns the system identifier of the external DTD subset.
+
+	const XMLString& internalSubset() const;
+		/// Returns the internal DTD subset. This implementation
+		/// returns an empty string.
+
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	DocumentType(Document* pOwner, const XMLString& name, const XMLString& publicId, const XMLString& systemId);
+	DocumentType(Document* pOwner, const DocumentType& dt);
+	~DocumentType();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	XMLString _name;
+	XMLString _publicId;
+	XMLString _systemId;
+	
+	friend class DOMImplementation;
+	friend class Document;
+	friend class DOMBuilder;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& DocumentType::name() const
+{
+	return _name;
+}
+
+
+inline const XMLString& DocumentType::publicId() const
+{
+	return _publicId;
+}
+
+
+inline const XMLString& DocumentType::systemId() const
+{
+	return _systemId;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_DocumentType_INCLUDED
diff --git a/Poco/DOM/Element.h b/Poco/DOM/Element.h
new file mode 100644
index 0000000..90217ba
--- /dev/null
+++ b/Poco/DOM/Element.h
@@ -0,0 +1,219 @@
+//
+// Element.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Element class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Element_INCLUDED
+#define DOM_Element_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractContainerNode.h"
+#include "Poco/XML/Name.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Attr;
+class NodeList;
+class Document;
+
+
+class XML_API Element: public AbstractContainerNode
+	/// The Element interface represents an element in an XML document.
+	/// Elements may have attributes associated with them; since the Element interface
+	/// inherits from Node, the generic Node interface attribute attributes may
+	/// be used to retrieve the set of all attributes for an element. There are
+	/// methods on the Element interface to retrieve either an Attr object by name
+	/// or an attribute value by name. In XML, where an attribute value may contain
+	/// entity references, an Attr object should be retrieved to examine the possibly
+	/// fairly complex sub-tree representing the attribute value. 
+{
+public:
+	const XMLString& tagName() const;
+		/// Returns the name of the element.
+		///
+		/// For example, in
+		/// 
+		///     <elementExample id="demo"> 
+        ///         ... 
+		///     </elementExample>
+		///
+		/// tagName has the value "elementExample". Note that this is case-preserving in XML, 
+		/// as are all of the operations of the DOM.
+
+	const XMLString& getAttribute(const XMLString& name) const;
+		/// Retrieves an attribute value by name.
+		///
+		/// Returns the attribute's value, if the attribute
+		/// exists, or an empty string otherwise.
+
+	void setAttribute(const XMLString& name, const XMLString& value);
+		/// Adds a new attribute. If an attribute with that name is already present
+		/// in the element, its value is changed to be that of the value parameter.
+		/// This value is a simple string; it is not parsed as it is being set. So any
+		/// markup (such as syntax to be recognized as an entity reference) is treated
+		/// as literal text, and needs to be appropriately escaped by the implementation
+		/// when it is written out.
+ 
+	void removeAttribute(const XMLString& name);
+		/// Removes an attribute by name.
+
+	Attr* getAttributeNode(const XMLString& name) const;
+		/// Retrieves an Attr node by name.
+
+	Attr* setAttributeNode(Attr* newAttr);
+		/// Adds a new attribute. If an attribute with that name is already
+		/// present in the element, it is replaced by the new one.
+
+	Attr* addAttributeNodeNP(Attr* oldAttr, Attr* newAttr);
+		/// For internal use only.
+		/// Adds a new attribute after oldAttr.
+		/// If oldAttr is 0, newAttr is set as first attribute.
+		/// Returns newAttr.
+		/// Does not fire any events.
+
+	Attr* removeAttributeNode(Attr* oldAttr);
+		/// Removes the specified attribute.
+
+	NodeList* getElementsByTagName(const XMLString& name) const;
+		/// Returns a NodeList of all descendant elements with a given tag
+		/// name, in the order in which they would be encountered in a
+		/// preorder traversal of the Element tree.
+		///
+		/// The special name "*" matches all tags.
+		///
+		/// The returned NodeList must be released with a call
+		/// to release() when no longer needed.
+
+	void normalize();
+		/// Puts all Text nodes in the full depth of the sub-tree underneath this Element,
+		/// including attribute nodes, into a "normal" form where only markup (e.g.,
+		/// tags, comments, processing instructions, CDATA sections, and entity references)
+		/// separates Text nodes, i.e., there are no adjacent Text nodes. This can be
+		/// used to ensure that the DOM view of a document is the same as if it were
+		/// saved and re-loaded, and is useful when operations (such as XPointer
+		/// lookups) that depend on a particular document tree structure are to be used.
+		/// 
+		/// Note: In cases where the document contains CDATASections, the normalize
+		/// operation alone may not be sufficient, since XPointers do not differentiate
+		/// between Text nodes and CDATASection nodes.
+
+	// DOM Level 2
+	const XMLString& getAttributeNS(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Retrieves an attribute value by name.
+		///
+		/// Returns the attribute's value, if the attribute
+		/// exists, or an empty string otherwise.
+
+	void setAttributeNS(const XMLString& namespaceURI, const XMLString& qualifiedName, const XMLString& value);
+		/// Adds a new attribute. If an attribute with that name
+		/// is already present in the element, its value is changed
+		/// to be that of the value parameter.
+
+	void removeAttributeNS(const XMLString& namespaceURI, const XMLString& localName);
+		/// Removes an attribute by name.
+
+	Attr* getAttributeNodeNS(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Retrieves an Attr node by name.
+
+	Attr* setAttributeNodeNS(Attr* newAttr);
+		/// Adds a new attribute. If an attribute with that name is already
+		/// present in the element, it is replaced by the new one.
+
+	bool hasAttribute(const XMLString& name) const;
+		/// Returns true if and only if the element has the specified attribute.
+
+	bool hasAttributeNS(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns true if and only if the element has the specified attribute.
+
+	NodeList* getElementsByTagNameNS(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns a NodeList of all the descendant Elements with a given local name and namespace URI 
+		/// in the order in which they are encountered in a preorder traversal of this Element tree.
+		///
+		/// The special value "*" matches all namespaces, or local names respectively.
+		///
+		/// The returned NodeList must be released with a call
+		/// to release() when no longer needed.
+
+	const XMLString& namespaceURI() const;
+	XMLString prefix() const;
+	const XMLString& localName() const;
+	bool hasAttributes() const;
+	XMLString innerText() const;
+
+	Element* getChildElement(const XMLString& name) const;
+		/// Returns the first child element with the given name, or null
+		/// if such an element does not exist.
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+	Element* getChildElementNS(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns the first child element with the given namespaceURI and localName,
+		/// or null if such an element does not exist.
+		///
+		/// This method is an extension to the W3C Document Object Model.
+	
+	Element* getElementById(const XMLString& elementId, const XMLString& idAttribute) const;
+		/// Returns the first Element whose ID attribute (given in idAttribute)
+		/// has the given elementId. If no such element exists, returns null. 
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+	Element* getElementByIdNS(const XMLString& elementId, const XMLString& idAttributeURI, const XMLString& idAttributeLocalName) const;
+		/// Returns the first Element whose ID attribute (given in idAttributeURI and idAttributeLocalName)
+		/// has the given elementId. If no such element exists, returns null. 
+		///
+		/// This method is an extension to the W3C Document Object Model.
+	
+	// Node
+	const XMLString& nodeName() const;
+	NamedNodeMap* attributes() const;
+	unsigned short nodeType() const;
+
+protected:
+	Element(Document* pOwnerDocument, const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname);
+	Element(Document* pOwnerDocument, const Element& elem);
+	~Element();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+	void dispatchNodeRemovedFromDocument();
+	void dispatchNodeInsertedIntoDocument();
+
+private:
+	const Name& _name;
+	Attr*       _pFirstAttr;
+
+	friend class Attr;
+	friend class Document;
+	friend class AttrMap;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Element::tagName() const
+{
+	return _name.qname();
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Element_INCLUDED
diff --git a/Poco/DOM/ElementsByTagNameList.h b/Poco/DOM/ElementsByTagNameList.h
new file mode 100644
index 0000000..98af2e8
--- /dev/null
+++ b/Poco/DOM/ElementsByTagNameList.h
@@ -0,0 +1,86 @@
+//
+// ElementsByTagNameList.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the ElementsByTagNameList and ElementsByTagNameListNS classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_ElementsByTagNameList_INCLUDED
+#define DOM_ElementsByTagNameList_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/NodeList.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API ElementsByTagNameList: public NodeList
+	// This implementation of NodeList is returned
+	// by Document::getElementsByTagName() and
+	// Element::getElementsByTagName().
+{
+public:
+	Node* item(unsigned long index) const;
+	unsigned long length() const;
+	void autoRelease();
+
+protected:
+	ElementsByTagNameList(const Node* pParent, const XMLString& name);
+	~ElementsByTagNameList();
+
+	Node* find(const Node* pParent, unsigned long index) const;
+
+	const Node* _pParent;
+	XMLString   _name;
+	mutable unsigned long _count;
+	
+	friend class AbstractContainerNode;
+	friend class Element;
+	friend class Document;
+};
+
+
+class XML_API ElementsByTagNameListNS: public NodeList
+	// This implementation of NodeList is returned
+	// by Document::getElementsByTagNameNS() and
+	// Element::getElementsByTagNameNS().
+{
+public:
+	virtual Node* item(unsigned long index) const;
+	virtual unsigned long length() const;
+	virtual void autoRelease();
+
+protected:
+	ElementsByTagNameListNS(const Node* pParent, const XMLString& namespaceURI, const XMLString& localName);
+	~ElementsByTagNameListNS();
+
+	Node* find(const Node* pParent, unsigned long index) const;
+
+	const Node* _pParent;
+	XMLString   _localName;
+	XMLString   _namespaceURI;
+	mutable unsigned long _count;
+	
+	friend class AbstractContainerNode;
+	friend class Element;
+	friend class Document;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_ElementsByTagNameList_INCLUDED
diff --git a/Poco/DOM/Entity.h b/Poco/DOM/Entity.h
new file mode 100644
index 0000000..40c21f5
--- /dev/null
+++ b/Poco/DOM/Entity.h
@@ -0,0 +1,126 @@
+//
+// Entity.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Entity class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Entity_INCLUDED
+#define DOM_Entity_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractContainerNode.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Entity: public AbstractContainerNode
+	/// This interface represents an entity, either parsed or unparsed, in an XML
+	/// document. Note that this models the entity itself not the entity declaration.
+	/// Entity declaration modeling has been left for a later Level of the DOM
+	/// specification.
+	/// 
+	/// The nodeName attribute that is inherited from Node contains the name of
+	/// the entity.
+	/// 
+	/// An XML processor may choose to completely expand entities before the structure
+	/// model is passed to the DOM; in this case there will be no EntityReference
+	/// nodes in the document tree.
+	/// 
+	/// XML does not mandate that a non-validating XML processor read and process
+	/// entity declarations made in the external subset or declared in external
+	/// parameter entities. This means that parsed entities declared in the external
+	/// subset need not be expanded by some classes of applications, and that the
+	/// replacement value of the entity may not be available. When the replacement
+	/// value is available, the corresponding Entity node's child list represents
+	/// the structure of that replacement text. Otherwise, the child list is empty.
+	/// 
+	/// The resolution of the children of the Entity (the replacement value) may
+	/// be lazily evaluated; actions by the user (such as calling the childNodes
+	/// method on the Entity Node) are assumed to trigger the evaluation.
+	/// 
+	/// The DOM Level 1 does not support editing Entity nodes; if a user wants to
+	/// make changes to the contents of an Entity, every related EntityReference
+	/// node has to be replaced in the structure model by a clone of the Entity's
+	/// contents, and then the desired changes must be made to each of those clones
+	/// instead. Entity nodes and all their descendants are readonly.
+	/// 
+	/// An Entity node does not have any parent.
+{
+public:
+	const XMLString& publicId() const;
+		/// Returns the public identifier associated with
+		/// the entity, if specified. If the public identifier
+		/// was not specified, this is the empty string.
+
+	const XMLString& systemId() const;
+		/// Returns the system identifier associated with
+		/// the entity, if specified. If the system identifier
+		/// was not specified, this is the empty string.
+
+	const XMLString& notationName() const;
+		/// Returns, for unparsed entities, the name of the
+		/// notation for the entity. For parsed entities, this
+		/// is the empty string.
+
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	Entity(Document* pOwnerDocument, const XMLString& name, const XMLString& publicId, const XMLString& systemId, const XMLString& notationName);
+	Entity(Document* pOwnerDocument, const Entity& entity);
+	~Entity();
+	
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	static const XMLString NODE_NAME;
+
+	XMLString _name;
+	XMLString _publicId;
+	XMLString _systemId;
+	XMLString _notationName;
+
+	friend class Document;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Entity::publicId() const
+{
+	return _publicId;
+}
+
+
+inline const XMLString& Entity::systemId() const
+{
+	return _systemId;
+}
+
+
+inline const XMLString& Entity::notationName() const
+{
+	return _notationName;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Entity_INCLUDED
diff --git a/Poco/DOM/EntityReference.h b/Poco/DOM/EntityReference.h
new file mode 100644
index 0000000..5ecd044
--- /dev/null
+++ b/Poco/DOM/EntityReference.h
@@ -0,0 +1,73 @@
+//
+// EntityReference.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM EntityReference class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_EntityReference_INCLUDED
+#define DOM_EntityReference_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractNode.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API EntityReference: public AbstractNode
+	/// EntityReference objects may be inserted into the structure model when an
+	/// entity reference is in the source document, or when the user wishes to insert
+	/// an entity reference. Note that character references and references to predefined
+	/// entities are considered to be expanded by the HTML or XML processor so that
+	/// characters are represented by their Unicode equivalent rather than by an
+	/// entity reference. Moreover, the XML processor may completely expand references
+	/// to entities while building the structure model, instead of providing EntityReference
+	/// objects. If it does provide such objects, then for a given EntityReference
+	/// node, it may be that there is no Entity node representing the referenced
+	/// entity. If such an Entity exists, then the child list of the EntityReference
+	/// node is the same as that of the Entity node.
+	/// 
+	/// As for Entity nodes, EntityReference nodes and all their descendants are
+	/// readonly.
+	/// 
+	/// The resolution of the children of the EntityReference (the replacement value
+	/// of the referenced Entity) may be lazily evaluated; actions by the user (such
+	/// as calling the childNodes method on the EntityReference node) are assumed
+	/// to trigger the evaluation.
+{
+public:
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	EntityReference(Document* pOwnerDocument, const XMLString& name);
+	EntityReference(Document* pOwnerDocument, const EntityReference& ref);
+	~EntityReference();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	XMLString _name;
+	
+	friend class Document;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_EntityReference_INCLUDED
diff --git a/Poco/DOM/Event.h b/Poco/DOM/Event.h
new file mode 100644
index 0000000..5396aa3
--- /dev/null
+++ b/Poco/DOM/Event.h
@@ -0,0 +1,209 @@
+//
+// Event.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMEvents
+//
+// Definition of the DOM Event class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Event_INCLUDED
+#define DOM_Event_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/DOM/DOMObject.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class EventTarget;
+class Document;
+
+
+class XML_API Event: public DOMObject
+	/// The Event interface is used to provide contextual information about an event
+	/// to the handler processing the event. An object which implements the Event
+	/// interface is generally passed as the first parameter to an event handler.
+	/// More specific context information is passed to event handlers by deriving
+	/// additional interfaces from Event which contain information directly relating
+	/// to the type of event they accompany. These derived interfaces are also implemented
+	/// by the object passed to the event listener.
+{
+public:
+	enum PhaseType
+	{
+		CAPTURING_PHASE = 1, /// The event is currently being evaluated at the target EventTarget. 
+		AT_TARGET       = 2, /// The current event phase is the bubbling phase. 
+		BUBBLING_PHASE  = 3  /// The current event phase is the capturing phase. 
+	};
+
+	const XMLString& type() const;
+		/// The name of the event (case-insensitive). The name must be an XML name.
+
+	EventTarget* target() const;
+		/// Used to indicate the EventTarget to which the event was originally dispatched.
+
+	EventTarget* currentTarget() const;
+		/// Used to indicate the EventTarget whose EventListeners are currently being 
+		/// processed. This is particularly useful during capturing and bubbling.
+
+	PhaseType eventPhase() const;
+		/// Used to indicate which phase of event flow is currently being evaluated.
+
+	bool bubbles() const;
+		/// Used to indicate whether or not an event is a bubbling event. 
+		/// If the event can bubble the value is true, else the value is false.
+
+	bool cancelable() const;
+		/// Used to indicate whether or not an event can have its default action 
+		/// prevented. If the default action can be prevented the value is
+		/// true, else the value is false.
+
+	Poco::UInt64 timeStamp() const;
+		/// Used to specify the time (in milliseconds relative to the epoch) at 
+		/// which the event was created. Due to the fact that some
+		/// systems may not provide this information the value of timeStamp may 
+		/// be not available for all events. When not available, a
+		/// value of 0 will be returned. Examples of epoch time are the time of the 
+		/// system start or 0:0:0 UTC 1st January 1970.
+		/// This implementation always returns 0.
+
+	void stopPropagation();
+		/// The stopPropagation method is used prevent further propagation of an 
+		/// event during event flow. If this method is called by
+		/// any EventListener the event will cease propagating through the tree. 
+		/// The event will complete dispatch to all listeners on the
+		/// current EventTarget before event flow stops. This method may be used 
+		/// during any stage of event flow. 
+
+	void preventDefault();
+		/// If an event is cancelable, the preventDefault method is used to signify 
+		/// that the event is to be canceled, meaning any default
+		/// action normally taken by the implementation as a result of 
+		/// the event will not occur. If, during any stage of event flow, the
+		/// preventDefault method is called the event is canceled. Any default 
+		/// action associated with the event will not occur. Calling
+		/// this method for a non-cancelable event has no effect. Once 
+		/// preventDefault has been called it will remain in effect throughout
+		/// the remainder of the event's propagation. This method may be 
+		/// used during any stage of event flow. 
+
+	void initEvent(const XMLString& eventType, bool canBubble, bool isCancelable);
+		/// The initEvent method is used to initialize the value of an 
+		/// Event created through the DocumentEvent interface. This method
+		/// may only be called before the Event has been dispatched via the 
+		/// dispatchEvent method, though it may be called multiple
+		/// times during that phase if necessary. If called multiple 
+		/// times the final invocation takes precedence. If called from 
+		/// a subclass of Event interface only the values specified in the 
+		/// initEvent method are modified, all other attributes are left unchanged. 
+
+	void autoRelease();
+
+protected:
+	Event(Document* pOwnerDocument, const XMLString& type);
+	Event(Document* pOwnerDocument, const XMLString& type, EventTarget* pTarget, bool canBubble, bool isCancelable);
+	~Event();
+
+	bool isCanceled() const;
+		/// returns true if and only if the event has been cancelled.
+
+	bool isStopped() const;
+		/// returns true if and only if propagation of the event has been stopped.
+
+	void setTarget(EventTarget* pTarget);
+		/// sets the target
+
+	void setCurrentPhase(PhaseType phase);
+		/// sets the current phase
+
+	void setCurrentTarget(EventTarget* pTarget);
+		/// sets the current target
+
+private:
+	Document*    _pOwner;
+	XMLString    _type;
+	EventTarget* _pTarget;
+	EventTarget* _pCurrentTarget;
+	PhaseType    _currentPhase;
+	bool         _bubbles;
+	bool         _cancelable;
+	bool         _canceled;
+	bool         _stopped;
+	
+	friend class AbstractNode;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Event::type() const
+{
+	return _type;
+}
+
+
+inline EventTarget* Event::target() const
+{
+	return _pTarget;
+}
+
+
+inline EventTarget* Event::currentTarget() const
+{
+	return _pCurrentTarget;
+}
+
+
+inline Event::PhaseType Event::eventPhase() const
+{
+	return _currentPhase;
+}
+
+
+inline bool Event::bubbles() const
+{
+	return _bubbles;
+}
+
+
+inline bool Event::cancelable() const
+{
+	return _cancelable;
+}
+
+
+inline Poco::UInt64 Event::timeStamp() const
+{
+	return 0;
+}
+
+
+inline bool Event::isCanceled() const
+{
+	return _canceled;
+}
+
+
+inline bool Event::isStopped() const
+{
+	return _stopped;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Event_INCLUDED
diff --git a/Poco/DOM/EventDispatcher.h b/Poco/DOM/EventDispatcher.h
new file mode 100644
index 0000000..4e825df
--- /dev/null
+++ b/Poco/DOM/EventDispatcher.h
@@ -0,0 +1,97 @@
+//
+// EventDispatcher.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMEvents
+//
+// Definition of the EventDispatcher class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_EventDispatcher_INCLUDED
+#define DOM_EventDispatcher_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include <list>
+
+
+namespace Poco {
+namespace XML {
+
+
+class Event;
+class EventListener;
+
+
+class XML_API EventDispatcher
+	/// This helper class manages event listener subscriptions
+	/// and event dispatching for AbstractNode.
+	///
+	/// The EventListener list is managed in such a way that
+	/// event listeners can be added and removed even
+	/// from within an EventListener, while events are being
+	/// dispatched.
+{
+public:
+	EventDispatcher();
+		/// Creates the EventDispatcher.
+		
+	~EventDispatcher();
+		/// Destroys the EventDispatcher.
+		
+	void addEventListener(const XMLString& type, EventListener* listener, bool useCapture);
+		/// Adds an EventListener to the internal list.
+		
+	void removeEventListener(const XMLString& type, EventListener* listener, bool useCapture);
+		/// Removes an EventListener from the internal list.
+		///
+		/// If a dispatch is currently in progress, the list
+		/// entry is only marked for deletion.
+		/// If no dispatch is currently in progress, all EventListeners
+		/// marked for deletion are removed from the list.
+
+	void dispatchEvent(Event* evt);
+		/// Dispatches the event.
+		///
+		/// Also removes all EventListeners marked for deletion from the 
+		/// event dispatcher list.
+		
+	void captureEvent(Event* evt);
+		/// Dispatches the event in its capturing phase.
+		///
+		/// Also removes all EventListeners marked for deletion from the 
+		/// event dispatcher list.
+		
+	void bubbleEvent(Event* evt);
+		/// Dispatches the event in its bubbling phase.
+		///
+		/// Also removes all EventListeners marked for deletion from the 
+		/// event dispatcher list.
+
+private:
+	struct EventListenerItem
+	{
+		XMLString      type;
+		EventListener* pListener;
+		bool           useCapture;
+	};
+
+	typedef std::list<EventListenerItem> EventListenerList;
+	
+	int               _inDispatch;
+	EventListenerList _listeners;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_EventDispatcher_INCLUDED
diff --git a/Poco/DOM/EventException.h b/Poco/DOM/EventException.h
new file mode 100644
index 0000000..a1fa1ab
--- /dev/null
+++ b/Poco/DOM/EventException.h
@@ -0,0 +1,81 @@
+//
+// EventException.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMEvents
+//
+// Definition of the DOM EventException class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_EventException_INCLUDED
+#define DOM_EventException_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLException.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API EventException: public XMLException
+	/// Event operations may throw an EventException as 
+	/// specified in their method descriptions.
+{
+public:
+	enum
+	{
+		UNSPECIFIED_EVENT_TYPE_ERR = 0  /// If the Event's type was not specified by initializing the 
+		                                /// event before the method was called. Specification of the Event's
+                                        /// type as null or an empty string will also trigger this exception. 
+	};
+
+	EventException(int code);
+		/// Creates an EventException with the given error code.
+
+	EventException(const EventException& exc);
+		/// Creates an EventException by copying another one.
+
+	~EventException() throw();
+		/// Destroys the EventException.
+
+	EventException& operator = (const EventException& exc);
+
+	const char* name() const throw();
+		/// Returns a static string describing the exception.
+
+	const char* className() const throw();
+		/// Returns the name of the exception class.
+
+	unsigned short code() const;
+		/// Returns the Event exception code.
+
+protected:
+	Poco::Exception* clone() const;
+	
+private:
+	EventException();
+};
+
+
+//
+// inlines
+//
+inline unsigned short EventException::code() const
+{
+	return UNSPECIFIED_EVENT_TYPE_ERR;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_EventException_INCLUDED
diff --git a/Poco/DOM/EventListener.h b/Poco/DOM/EventListener.h
new file mode 100644
index 0000000..f0951b1
--- /dev/null
+++ b/Poco/DOM/EventListener.h
@@ -0,0 +1,57 @@
+//
+// EventListener.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMEvents
+//
+// Definition of the DOM EventListener interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_EventListener_INCLUDED
+#define DOM_EventListener_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Event;
+
+
+class XML_API EventListener
+	/// The EventListener interface is the primary method for handling events. Users
+	/// implement the EventListener interface and register their listener on an
+	/// EventTarget using the AddEventListener method. The users should also remove
+	/// their EventListener from its EventTarget after they have completed using
+	/// the listener.
+	/// 
+	/// When a Node is copied using the cloneNode method the EventListeners attached
+	/// to the source Node are not attached to the copied Node. If the user wishes
+	/// the same EventListeners to be added to the newly created copy the user must
+	/// add them manually.
+{
+public:
+	virtual void handleEvent(Event* evt) = 0;
+		/// This method is called whenever an event occurs of the 
+		/// type for which the EventListener interface was registered.
+
+protected:
+	virtual ~EventListener();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_EventListener_INCLUDED
diff --git a/Poco/DOM/EventTarget.h b/Poco/DOM/EventTarget.h
new file mode 100644
index 0000000..466d215
--- /dev/null
+++ b/Poco/DOM/EventTarget.h
@@ -0,0 +1,76 @@
+//
+// EventTarget.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMEvents
+//
+// Definition of the DOM EventTarget interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_EventTarget_INCLUDED
+#define DOM_EventTarget_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/DOMObject.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class EventListener;
+class Event;
+
+
+class XML_API EventTarget: public DOMObject
+	/// The EventTarget interface is implemented by all Nodes in an implementation
+	/// which supports the DOM Event Model. Therefore, this interface can be obtained
+	/// by using binding-specific casting methods on an instance of the Node interface.
+	/// The interface allows registration and removal of EventListeners on an EventTarget
+	/// and dispatch of events to that EventTarget.
+{
+public:
+	virtual void addEventListener(const XMLString& type, EventListener* listener, bool useCapture) = 0;
+		/// This method allows the registration of event listeners on 
+		/// the event target. If an EventListener is added to an
+		/// EventTarget while it is processing an event, it will not 
+		/// be triggered by the current actions but may be triggered
+		/// during a later stage of event flow, such as the bubbling phase.
+		/// If multiple identical EventListeners are registered on the same 
+		/// EventTarget with the same parameters the duplicate instances are 
+		/// discarded. They do not cause the EventListener to be called twice and since they are
+		/// discarded they do not need to be removed with the removeEventListener method. 	
+	
+	virtual void removeEventListener(const XMLString& type, EventListener* listener, bool useCapture) = 0;
+		/// This method allows the removal of event listeners from the event 
+		/// target. If an EventListener is removed from an EventTarget while it is 
+		/// processing an event, it will not be triggered by the current actions. 
+		/// EventListeners can never be invoked after being removed.
+		/// Calling removeEventListener with arguments which do not identify 
+		/// any currently registered EventListener on the EventTarget has no effect. 
+
+	virtual bool dispatchEvent(Event* evt) = 0;
+		/// This method allows the dispatch of events into the implementations 
+		/// event model. Events dispatched in this manner will have the same capturing and 
+		/// bubbling behavior as events dispatched directly by the
+		/// implementation. The target of the event is the EventTarget on 
+		/// which dispatchEvent is called. 
+
+protected:
+	virtual ~EventTarget();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_EventTarget_INCLUDED
diff --git a/Poco/DOM/MutationEvent.h b/Poco/DOM/MutationEvent.h
new file mode 100644
index 0000000..33a8521
--- /dev/null
+++ b/Poco/DOM/MutationEvent.h
@@ -0,0 +1,143 @@
+//
+// MutationEvent.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOMEvents
+//
+// Definition of the DOM MutationEvent class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_MutationEvent_INCLUDED
+#define DOM_MutationEvent_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/Event.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+
+
+class XML_API MutationEvent: public Event
+	/// The MutationEvent interface provides specific contextual 
+	/// information associated with Mutation events.
+{
+public:
+	enum AttrChangeType
+	{
+		MODIFICATION = 1, /// The Attr was modified in place.
+		ADDITION     = 2, /// The Attr was just added. 
+		REMOVAL      = 3  /// The Attr was just removed. 
+	};
+
+	Node* relatedNode() const;
+		/// relatedNode is used to identify a secondary node related to a mutation 
+		/// event. For example, if a mutation event is dispatched
+		/// to a node indicating that its parent has changed, the relatedNode is the 
+		/// changed parent. If an event is instead dispatched to a
+		/// subtree indicating a node was changed within it, the relatedNode is 
+		/// the changed node. In the case of the DOMAttrModified
+		/// event it indicates the Attr node which was modified, added, or removed.
+
+	const XMLString& prevValue() const;
+		/// prevValue indicates the previous value of the Attr node in DOMAttrModified 
+		/// events, and of the CharacterData node in DOMCharDataModified events.
+
+	const XMLString& newValue() const;
+		/// newValue indicates the new value of the Attr node in DOMAttrModified 
+		/// events, and of the CharacterData node in DOMCharDataModified events.
+
+	const XMLString& attrName() const;
+		/// attrName indicates the name of the changed Attr node in a DOMAttrModified event.
+
+	AttrChangeType attrChange() const;
+		/// attrChange indicates the type of change which triggered the 
+		/// DOMAttrModified event. The values can be MODIFICATION,
+		/// ADDITION, or REMOVAL.
+
+	void initMutationEvent(const XMLString& type, bool canBubble, bool cancelable, Node* relatedNode, 
+	                       const XMLString& prevValue, const XMLString& newValue, const XMLString& attrName, AttrChangeType change);
+		/// The initMutationEvent method is used to initialize the value of a 
+		/// MutationEvent created through the DocumentEvent
+		/// interface. This method may only be called before the MutationEvent 
+		/// has been dispatched via the dispatchEvent method,
+		/// though it may be called multiple times during that phase if 
+		/// necessary. If called multiple times, the final invocation takes
+		/// precedence.
+
+	// Event Types
+	static const XMLString DOMSubtreeModified;
+	static const XMLString DOMNodeInserted;
+	static const XMLString DOMNodeRemoved;
+	static const XMLString DOMNodeRemovedFromDocument;
+	static const XMLString DOMNodeInsertedIntoDocument;
+	static const XMLString DOMAttrModified;
+	static const XMLString DOMCharacterDataModified;
+
+protected:
+	MutationEvent(Document* pOwnerDocument, const XMLString& type);
+	MutationEvent(Document* pOwnerDocument, const XMLString& type, EventTarget* pTarget, bool canBubble, bool cancelable, Node* relatedNode);
+	MutationEvent(Document* pOwnerDocument, const XMLString& type, EventTarget* pTarget, bool canBubble, bool cancelable, Node* relatedNode, 
+				  const XMLString& prevValue, const XMLString& newValue, const XMLString& attrName, AttrChangeType change);
+	~MutationEvent();
+
+private:
+	XMLString      _prevValue;
+	XMLString      _newValue;
+	XMLString      _attrName;
+	AttrChangeType _change;
+	Node*          _pRelatedNode;
+
+	friend class AbstractNode;
+	friend class Document;
+};
+
+
+//
+// inlines
+//
+inline Node* MutationEvent::relatedNode() const
+{
+	return _pRelatedNode;
+}
+
+
+inline const XMLString& MutationEvent::prevValue() const
+{
+	return _prevValue;
+}
+
+
+inline const XMLString& MutationEvent::newValue() const
+{
+	return _newValue;
+}
+
+
+inline const XMLString& MutationEvent::attrName() const
+{
+	return _attrName;
+}
+
+
+inline MutationEvent::AttrChangeType MutationEvent::attrChange() const
+{
+	return _change;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_MutationEvent_INCLUDED
diff --git a/Poco/DOM/NamedNodeMap.h b/Poco/DOM/NamedNodeMap.h
new file mode 100644
index 0000000..7b42ca8
--- /dev/null
+++ b/Poco/DOM/NamedNodeMap.h
@@ -0,0 +1,93 @@
+//
+// NamedNodeMap.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM NamedNodeMap interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_NamedNodeMap_INCLUDED
+#define DOM_NamedNodeMap_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/DOMObject.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+
+
+class XML_API NamedNodeMap: public DOMObject
+	/// Objects implementing the NamedNodeMap interface are used to represent collections
+	/// of nodes that can be accessed by name. Note that NamedNodeMap does not inherit
+	/// from NodeList; NamedNodeMaps are not maintained in any particular order.
+	/// Objects contained in an object implementing NamedNodeMap may also be accessed
+	/// by an ordinal index, but this is simply to allow convenient enumeration
+	/// of the contents of a NamedNodeMap, and does not imply that the DOM specifies
+	/// an order to these Nodes.
+	///
+	/// NamedNodeMap objects in the DOM are live.
+	///
+	/// A NamedNodeMap returned from a method must be released with a call to 
+	/// release() when no longer needed.
+{
+public:
+	virtual Node* getNamedItem(const XMLString& name) const = 0;
+		/// Retrieves a node specified by name.
+
+	virtual Node* setNamedItem(Node* arg) = 0;
+		/// Adds a node using its nodeName attribute. If a node with that name is already
+		/// present in this map, it is replaced by the new one.
+		/// As the nodeName attribute is used to derive the name which the node must
+		/// be stored under, multiple nodes of certain types (those that have a "special"
+		/// string value) cannot be stored as the names would clash. This is seen as
+		/// preferable to allowing nodes to be aliased.
+
+	virtual Node* removeNamedItem(const XMLString& name) = 0;
+		/// Removes a node specified by name. When this map contains the attributes
+		/// attached to an element, if the removed attribute is known to have a default
+		/// value, an attribute immediately appears containing the default value.
+
+	virtual Node* item(unsigned long index) const = 0;
+		/// Returns the index'th item in the map. If index is greater
+		/// than or equal to the number of nodes in the map, this
+		/// returns null.
+
+	virtual unsigned long length() const = 0;
+		/// Returns the number of nodes in the map. The range of valid
+		/// child node indices is 0 to length - 1 inclusive.
+	
+	// DOM Level 2
+	virtual Node* getNamedItemNS(const XMLString& namespaceURI, const XMLString& localName) const = 0;
+		/// Retrieves a node specified by name.
+
+	virtual Node* setNamedItemNS(Node* arg) = 0;
+		/// Adds a node using its nodeName attribute.
+		/// If a node with that namespace URI and that local name is already 
+		/// present in this map, it is replaced by the new one.
+
+	virtual Node* removeNamedItemNS(const XMLString& namespaceURI, const XMLString& localName) = 0;
+		/// Removes a node specified by name.
+	
+protected:
+	virtual ~NamedNodeMap();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_NamedNodeMap_INCLUDED
diff --git a/Poco/DOM/Node.h b/Poco/DOM/Node.h
new file mode 100644
index 0000000..f6a3c4a
--- /dev/null
+++ b/Poco/DOM/Node.h
@@ -0,0 +1,285 @@
+//
+// Node.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Node interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Node_INCLUDED
+#define DOM_Node_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/EventTarget.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/SAX/NamespaceSupport.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class NamedNodeMap;
+class Document;
+class NodeList;
+
+
+class XML_API Node: public EventTarget
+	/// The Node interface is the primary datatype for the entire Document Object
+	/// Model. It represents a single node in the document tree. While all objects
+	/// implementing the Node interface expose methods for dealing with children,
+	/// not all objects implementing the Node interface may have children. For
+	/// example, Text nodes may not have children, and adding children to such
+	/// nodes results in a DOMException being raised.
+	/// 
+	/// The attributes nodeName, nodeValue and attributes are included as a mechanism
+	/// to get at node information without casting down to the specific derived
+	/// interface. In cases where there is no obvious mapping of these attributes
+	/// for a specific nodeType (e.g., nodeValue for an Element or attributes for
+	/// a Comment), this returns null. Note that the specialized interfaces may
+	/// contain additional and more convenient mechanisms to get and set the relevant
+	/// information.
+	///
+	/// This implementation differs in some ways from the W3C DOM recommendations.
+	/// For example, the DOM specifies that some methods can return null strings.
+	/// Instead of null strings, this implementation always returns empty strings.
+{
+public:
+	enum
+	{
+		ELEMENT_NODE = 1,             /// The node is an Element.
+		ATTRIBUTE_NODE,               /// The node is an Attr.
+		TEXT_NODE,                    /// The node is a Text node.
+		CDATA_SECTION_NODE,           /// The node is a CDATASection.
+		ENTITY_REFERENCE_NODE,        /// The node is an EntityReference.
+		ENTITY_NODE,                  /// The node is an Entity.
+		PROCESSING_INSTRUCTION_NODE,  /// The node is a ProcessingInstruction.
+		COMMENT_NODE,                 /// The node is a Comment.
+		DOCUMENT_NODE,                /// The node is a Document.
+		DOCUMENT_TYPE_NODE,           /// The node is a DocumentType.
+		DOCUMENT_FRAGMENT_NODE,       /// The node is a DocumentFragment.
+		NOTATION_NODE                 /// The node is a Notation.
+	};
+
+	virtual const XMLString& nodeName() const = 0;
+		/// Returns the name of this node, depending on its type.
+
+	const XMLString& nodeValue() const;
+		/// Returns the value of this node, depending on its type.
+
+	virtual const XMLString& getNodeValue() const = 0;
+		/// Returns the value of this node, depending on its type.
+
+	virtual void setNodeValue(const XMLString& value) = 0;
+		/// Sets the value of this node. Throws an exception
+		/// if the node is read-only.
+
+	virtual unsigned short nodeType() const = 0;
+		/// Returns a code representing the type of the underlying object.
+
+	virtual Node* parentNode() const = 0;
+		/// The parent of this node. All nodes, except Attr, Document, DocumentFragment,
+		/// Entity, and Notation may have a parent. However, if a node has just been
+		/// created and not yet added to the tree, or if it has been removed from the
+		/// tree, this is null.
+
+	virtual NodeList* childNodes() const = 0;
+		/// Returns a NodeList containing all children of this node.
+		///
+		/// The returned NodeList must be released with a call
+		/// to release() when no longer needed.
+
+	virtual Node* firstChild() const = 0;
+		/// Returns the first child of this node. If there is no such
+		/// node, this returns null.
+
+	virtual Node* lastChild() const = 0;
+		/// Returns the last child of this node. If there is no such
+		/// node, this returns null.
+
+	virtual Node* previousSibling() const = 0;
+		/// Returns the node immediately preceding this node. If there
+		/// is no such node, this returns null.
+
+	virtual Node* nextSibling() const = 0;
+		/// Returns the node immediately following this node. If there
+		/// is no such node, this returns null.
+
+	virtual NamedNodeMap* attributes() const = 0;
+		/// Returns a NamedNodeMap containing the attributes of this
+		/// node (if it is an Element) or null otherwise.
+		/// 
+		/// The returned NamedNodeMap must be released with a call
+		/// to release() when no longer needed.
+
+	virtual Document* ownerDocument() const = 0;
+		/// Returns the Document object associated with this node.
+		/// This is also the Document object used to create new nodes.
+		/// When this node is a Document, this is null.
+
+	virtual Node* insertBefore(Node* newChild, Node* refChild) = 0;
+		/// Inserts the node newChild before the existing child node refChild.
+		///
+		/// If refChild is null, insert newChild at the end of the list of children.
+		/// If newChild is a DocumentFragment object, all of its children are
+		/// inserted in the same order, before refChild. If the newChild is already
+		/// in the tree, it is first removed.
+
+	virtual Node* replaceChild(Node* newChild, Node* oldChild) = 0;
+		/// Replaces the child node oldChild with newChild in the list of children,
+		/// and returns the oldChild node.
+		/// If newChild is a DocumentFragment object, oldChild is replaced by all of
+		/// the DocumentFragment children, which are inserted in the same order. If
+		/// the newChild is already in the tree, it is first removed.
+
+	virtual Node* removeChild(Node* oldChild) = 0;
+		/// Removes the child node indicated by oldChild from the list of children
+		/// and returns it. 
+
+	virtual Node* appendChild(Node* newChild) = 0;
+		/// Appends the node newChild to the end of the list of children of this node.
+		/// If newChild is already in the tree, it is first removed.
+
+	virtual bool hasChildNodes() const = 0;
+		/// This is a convenience method to allow easy determination of whether a 
+		/// node has any children.
+		/// Returns true if the node has any children, false otherwise.
+
+	virtual Node* cloneNode(bool deep) const = 0;
+		/// Returns a duplicate of this node, i.e., serves as a generic copy constructor
+		/// for nodes. The duplicate node has no parent; (parentNode is null.).
+		/// Cloning an Element copies all attributes and their values, including those
+		/// generated by the XML processor to represent defaulted attributes, but this
+		/// method does not copy any text it contains unless it is a deep clone, since
+		/// the text is contained in a child Text node. Cloning an Attribute directly,
+		/// as opposed to be cloned as part of an Element cloning operation, returns
+		/// a specified attribute (specified is true). Cloning any other type of node
+		/// simply returns a copy of this node.
+		/// Note that cloning an immutable subtree results in a mutable copy, but the
+		/// children of an EntityReference clone are readonly. In addition, clones of
+		/// unspecified Attr nodes are specified. And, cloning Document, DocumentType,
+		/// Entity, and Notation nodes is implementation dependent.
+	
+	// DOM Level 2
+	virtual void normalize() = 0;
+		/// Puts all Text nodes in the full depth of the sub-tree underneath this Node,
+		/// including attribute nodes, into a "normal" form where only structure (e.g.,
+		/// elements, comments, processing instructions, CDATA sections, and entity
+		/// references) separates Text nodes, i.e., there are neither adjacent Text
+		/// nodes nor empty Text nodes. This can be used to ensure that the DOM view
+		/// of a document is the same as if it were saved and re-loaded, and is useful
+		/// when operations (such as XPointer lookups) that depend on a particular
+		/// document tree structure are to be used.
+		/// 
+		/// Note: In cases where the document contains CDATASections, the normalize
+		/// operation alone may not be sufficient, since XPointers do not differentiate
+		/// between Text nodes and CDATASection nodes.
+
+	virtual bool isSupported(const XMLString& feature, const XMLString& version) const = 0;
+		/// Tests whether the DOM implementation implements a specific 
+		/// feature and that feature is supported by this node.
+
+	virtual const XMLString& namespaceURI() const = 0;
+		/// Returns the namespace URI of the node.
+		/// This is not a computed value that is the result of a namespace lookup based on an 
+		/// examination of the namespace declarations in scope. It is merely the namespace URI 
+		/// given at creation time.
+		///
+		/// For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a 
+		/// DOM Level 1 method, such as createElement from the Document interface, this is always the
+		/// empty string.
+
+	virtual XMLString prefix() const = 0;
+		/// Returns the namespace prefix from the qualified name of the node.
+
+	virtual const XMLString& localName() const = 0;
+		/// Returns the local name of the node.
+
+	virtual bool hasAttributes() const = 0;
+		/// Returns whether this node (if it is an element) has any attributes.
+		
+	// Extensions
+	typedef Poco::XML::NamespaceSupport NSMap;
+
+	virtual XMLString innerText() const = 0;
+		/// Returns a string containing the concatenated values of the node
+		/// and all its child nodes. 
+		///
+		/// This method is not part of the W3C Document Object Model.
+		
+	virtual Node* getNodeByPath(const XMLString& path) const = 0;
+		/// Searches a node (element or attribute) based on a simplified XPath 
+		/// expression.
+		///
+		/// Only simple XPath expressions are supported. These are the slash
+		/// notation for specifying paths to elements, and the square bracket
+		/// expression for finding elements by their index, by attribute value, 
+		/// or finding attributes by names.
+		///
+		/// The slash at the beginning is optional, the evaluation always starts
+		/// at this element. A double-slash at the beginning recursively searches 
+		/// the entire subtree for the first element.
+		///
+		/// Examples:
+		///     elem1/elem2/elem3
+		///     /elem1/elem2/elem3
+		///     /elem1/elem2[1]
+		///     /elem1/elem2[@attr1]
+		///     /elem1/elem2[@attr1='value']
+		///     //elem2[@attr1='value']
+		///     //[@attr1='value']
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+	virtual Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const = 0;
+		/// Searches a node (element or attribute) based on a simplified XPath 
+		/// expression. The given NSMap must contain mappings from namespace
+		/// prefixes to namespace URIs for all namespace prefixes used in 
+		/// the path expression.
+		///
+		/// Only simple XPath expressions are supported. These are the slash
+		/// notation for specifying paths to elements, and the square bracket
+		/// expression for finding elements by their index, by attribute value, 
+		/// or finding attributes by names.
+		///
+		/// The slash at the beginning is optional, the evaluation always starts
+		/// at this element. A double-slash at the beginning recursively searches 
+		/// the entire subtree for the first element.
+		///
+		/// Examples:
+		///     /ns1:elem1/ns2:elem2/ns2:elem3
+		///     /ns1:elem1/ns2:elem2[1]
+		///     /ns1:elem1/ns2:elem2[@attr1]
+		///     /ns1:elem1/ns2:elem2[@attr1='value']
+		///     //ns2:elem2[@ns1:attr1='value']
+		///     //[@ns1:attr1='value']
+		///
+		/// This method is an extension to the W3C Document Object Model.
+
+protected:
+	virtual ~Node();
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Node::nodeValue() const
+{
+	return getNodeValue();
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Node_INCLUDED
diff --git a/Poco/DOM/NodeAppender.h b/Poco/DOM/NodeAppender.h
new file mode 100644
index 0000000..2d36be2
--- /dev/null
+++ b/Poco/DOM/NodeAppender.h
@@ -0,0 +1,81 @@
+//
+// NodeAppender.h
+//
+// Library: XML
+// Package: DOM
+// Module:  NodeAppender
+//
+// Definition of the NodeAppender class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_NodeAppender_INCLUDED
+#define DOM_NodeAppender_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/Node.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class AbstractNode;
+class Element;
+
+
+class XML_API NodeAppender
+	/// The NodeAppender class provides a very fast way to
+	/// build larger DOM documents.
+	///
+	/// In the DOM, child nodes are usually appended to a parent
+	/// node using the appendChild() method. For nodes containing
+	/// more than a few children, this method can be quite slow,
+	/// due to the way it's implemented, and because of the 
+	/// requirements of the DOM specification.
+	///
+	/// While the NodeAppender is being used on an Element, no
+	/// children-modifying methods of that Element must be used.
+	///
+	/// This class is not part of the DOM specification.
+{
+public:
+	NodeAppender(Element* parent);
+		/// Creates the NodeAppender for the given parent node,
+		/// which must be an Element.
+
+	~NodeAppender();
+		/// Destroys the NodeAppender.
+
+	void appendChild(Node* newChild);
+		/// Appends the node newChild to the end of the list of children of
+		/// the parent node specified in the constructor.
+		/// If the newChild is already in the tree, it is first removed.
+		///
+		/// NewChild can be a DocumentFragment. In this case, all children
+		/// of the fragment become children of the parent element.
+		///
+		/// In order to speed up the function, no DOM events
+		/// are fired.
+
+private:
+	NodeAppender();
+	NodeAppender(const NodeAppender&);
+	NodeAppender& operator = (const NodeAppender&);
+	
+	Element*      _pParent;
+	AbstractNode* _pLast;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // #include "Poco/XML/XML.h"
+
diff --git a/Poco/DOM/NodeFilter.h b/Poco/DOM/NodeFilter.h
new file mode 100644
index 0000000..ae8677b
--- /dev/null
+++ b/Poco/DOM/NodeFilter.h
@@ -0,0 +1,146 @@
+//
+// NodeFilter.h
+//
+// Library: XML
+// Package: DOM
+// Module:  NodeFilter
+//
+// Definition of the DOM NodeFilter interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_NodeFilter_INCLUDED
+#define DOM_NodeFilter_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+
+
+class XML_API NodeFilter
+	/// Filters are objects that know how to "filter out" nodes. If a NodeIterator
+	/// or TreeWalker is given a NodeFilter, it applies the filter before it returns
+	/// the next node. If the filter says to accept the node, the traversal logic
+	/// returns it; otherwise, traversal looks for the next node and pretends that
+	/// the node that was rejected was not there.
+	/// 
+	/// The DOM does not provide any filters. NodeFilter is just an interface that
+	/// users can implement to provide their own filters.
+	/// 
+	/// NodeFilters do not need to know how to traverse from node to node, nor do
+	/// they need to know anything about the data structure that is being traversed.
+	/// This makes it very easy to write filters, since the only thing they have
+	/// to know how to do is evaluate a single node. One filter may be used with
+	/// a number of different kinds of traversals, encouraging code reuse.
+{
+public:
+	enum
+	{
+		FILTER_ACCEPT = 1,
+			/// Accept the node. Navigation methods defined for NodeIterator or TreeWalker will return this node.
+
+		FILTER_REJECT = 2,
+			/// Reject the node. Navigation methods defined for NodeIterator or TreeWalker
+			/// will not return this node. For TreeWalker, the children of this node will
+			/// also be rejected. NodeIterators treat this as a synonym for FILTER_SKIP.
+
+		FILTER_SKIP   = 3
+			/// Skip this single node. Navigation methods defined for NodeIterator or TreeWalker
+			/// will not return this node. For both NodeIterator and TreeWalker, the children
+			/// of this node will still be considered.
+	};
+	
+	enum WhatToShow
+		/// These are the available values for the whatToShow parameter used in TreeWalkers
+		/// and NodeIterators. They are the same as the set of possible types for Node,
+		/// and their values are derived by using a bit position corresponding to the
+		/// value of nodeType for the equivalent node type. If a bit in whatToShow is
+		/// set false, that will be taken as a request to skip over this type of node;
+		/// the behavior in that case is similar to that of FILTER_SKIP.
+		/// 
+		/// Note that if node types greater than 32 are ever introduced, they may not
+		/// be individually testable via whatToShow. If that need should arise, it can
+		/// be handled by selecting SHOW_ALL together with an appropriate NodeFilter.
+	{
+		SHOW_ALL                    = 0xFFFFFFFF,
+			/// Show all Nodes.
+	
+		SHOW_ELEMENT                = 0x00000001,
+			/// Show Element nodes.
+
+		SHOW_ATTRIBUTE              = 0x00000002, 
+			/// Show Attr nodes. This is meaningful only when creating an iterator or tree-walker
+			/// with an attribute node as its root; in this case, it means that the attribute
+			/// node will appear in the first position of the iteration or traversal. Since
+			/// attributes are never children of other nodes, they do not appear when traversing
+			/// over the document tree.
+
+		SHOW_TEXT                   = 0x00000004,
+			/// Show Text nodes.
+
+		SHOW_CDATA_SECTION          = 0x00000008,
+			/// Show CDATASection nodes.
+
+		SHOW_ENTITY_REFERENCE       = 0x00000010,
+			/// Show EntityReference nodes.
+
+		SHOW_ENTITY                 = 0x00000020,
+			/// Show Entity nodes. This is meaningful only when creating an iterator or
+			/// tree-walker with an Entity node as its root; in this case, it means that
+			/// the Entity node will appear in the first position of the traversal. Since
+			/// entities are not part of the document tree, they do not appear when traversing
+			/// over the document tree.
+
+		SHOW_PROCESSING_INSTRUCTION = 0x00000040,
+			/// Show ProcessingInstruction nodes.
+
+		SHOW_COMMENT                = 0x00000080,
+			/// Show Comment nodes.
+
+		SHOW_DOCUMENT               = 0x00000100,
+			/// Show Document nodes.
+
+		SHOW_DOCUMENT_TYPE          = 0x00000200,
+			/// Show DocumentType nodes.
+
+		SHOW_DOCUMENT_FRAGMENT      = 0x00000400,
+			/// Show DocumentFragment nodes.
+
+		SHOW_NOTATION               = 0x00000800
+			/// Show Notation nodes. This is meaningful only when creating an iterator or
+			/// tree-walker with a Notation node as its root; in this case, it means that
+			/// the Notation node will appear in the first position of the traversal. Since
+			/// notations are not part of the document tree, they do not appear when traversing
+			/// over the document tree.
+	};
+	
+	virtual short acceptNode(Node* node) = 0;
+		/// Test whether a specified node is visible in the logical view of a TreeWalker
+		/// or NodeIterator. This function will be called by the implementation of TreeWalker
+		/// and NodeIterator; it is not normally called directly from user code. (Though
+		/// you could do so if you wanted to use the same filter to guide your own application
+		/// logic.)
+		///
+		/// Returns FILTER_ACCEPT, FILTER_REJECT or FILTER_SKIP.
+		
+protected:
+	virtual ~NodeFilter();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_NodeFilter_INCLUDED
diff --git a/Poco/DOM/NodeIterator.h b/Poco/DOM/NodeIterator.h
new file mode 100644
index 0000000..1f8e9a0
--- /dev/null
+++ b/Poco/DOM/NodeIterator.h
@@ -0,0 +1,167 @@
+//
+// NodeIterator.h
+//
+// Library: XML
+// Package: DOM
+// Module:  NodeIterator
+//
+// Definition of the DOM NodeIterator class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_NodeIterator_INCLUDED
+#define DOM_NodeIterator_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+class NodeFilter;
+
+
+class XML_API NodeIterator
+	/// Iterators are used to step through a set of nodes, e.g. the set of nodes
+	/// in a NodeList, the document subtree governed by a particular Node, the results
+	/// of a query, or any other set of nodes. The set of nodes to be iterated is
+	/// determined by the implementation of the NodeIterator. DOM Level 2 specifies
+	/// a single NodeIterator implementation for document-order traversal of a document
+	/// subtree.
+	///
+	/// A NodeIterator can be directly instantiated using one of its constructors -
+	/// the DocumentTraversal interface is not needed and therefore not implemented.
+	/// Unlike most other DOM classes, NodeIterator supports value semantics.
+	///
+	/// If the NodeIterator's current node is removed from the document, the
+	/// result of calling any of the movement methods is undefined. This behavior does
+	/// not conform to the DOM Level 2 Traversal specification.
+{
+public:
+	NodeIterator(Node* root, unsigned long whatToShow, NodeFilter* pFilter = 0);
+		/// Creates a NodeIterator over the subtree rooted at the specified node.
+		
+	NodeIterator(const NodeIterator& iterator);
+		/// Creates a NodeIterator by copying another NodeIterator.
+		
+	NodeIterator& operator = (const NodeIterator& iterator);
+		/// Assignment operator.
+		
+	~NodeIterator();
+		/// Destroys the NodeIterator.
+
+	Node* root() const;
+		/// The root node of the NodeIterator, as specified when it was created.
+
+	unsigned long whatToShow() const;
+		/// This attribute determines which node types are presented via the iterator. 
+		/// The available set of constants is defined in the NodeFilter interface. 
+		/// Nodes not accepted by whatToShow will be skipped, but their children may 
+		/// still be considered. Note that this skip takes precedence over the filter, 
+		/// if any.
+
+	NodeFilter* filter() const;
+		/// The NodeFilter used to screen nodes.
+
+	bool expandEntityReferences() const;
+		/// The value of this flag determines whether the children of entity reference
+		/// nodes are visible to the iterator. If false, they and their descendants
+		/// will be rejected. Note that this rejection takes precedence over whatToShow
+		/// and the filter. Also note that this is currently the only situation where
+		/// NodeIterators may reject a complete subtree rather than skipping individual
+		/// nodes.
+		/// 
+		/// To produce a view of the document that has entity references expanded and
+		/// does not expose the entity reference node itself, use the whatToShow flags
+		/// to hide the entity reference node and set expandEntityReferences to true
+		/// when creating the iterator. To produce a view of the document that has entity
+		/// reference nodes but no entity expansion, use the whatToShow flags to show
+		/// the entity reference node and set expandEntityReferences to false.
+		///
+		/// This implementation does not support entity reference expansion and
+		/// thus always returns false.
+
+	Node* nextNode();
+		/// Returns the next node in the set and advances the position of the iterator
+		/// in the set. After a NodeIterator is created, the first call to nextNode()
+		/// returns the first node in the set.
+
+	Node* previousNode();
+		/// Returns the previous node in the set and moves the position of the NodeIterator
+		/// backwards in the set.
+
+	Node* currentNodeNP() const;
+		/// Returns the current node in the set.
+		///
+		/// Leaves the NodeIterator unchanged.
+		///
+		/// Warning: This is a proprietary extension to the DOM Level 2 NodeIterator
+		/// interface.
+
+	void detach();
+		/// Detaches the NodeIterator from the set which it iterated over, releasing
+		/// any computational resources and placing the iterator in the INVALID state.
+		/// After detach has been invoked, calls to nextNode or previousNode will raise
+		/// the exception INVALID_STATE_ERR.
+
+protected:
+	bool accept(Node* pNode) const;
+	Node* next() const;
+	Node* previous() const;
+	Node* last();
+
+private:
+	NodeIterator();
+	
+	Node*         _pRoot;
+	unsigned long _whatToShow;
+	NodeFilter*   _pFilter;
+	Node*         _pCurrent;
+};
+
+
+//
+// inlines
+//
+inline Node* NodeIterator::root() const
+{
+	return _pRoot;
+}
+
+
+inline Node* NodeIterator::currentNodeNP() const
+{
+	return _pCurrent;
+}
+
+
+inline unsigned long NodeIterator::whatToShow() const
+{
+	return _whatToShow;
+}
+
+
+inline NodeFilter* NodeIterator::filter() const
+{
+	return _pFilter;
+}
+
+
+inline bool NodeIterator::expandEntityReferences() const
+{
+	return false;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_NodeIterator_INCLUDED
diff --git a/Poco/DOM/NodeList.h b/Poco/DOM/NodeList.h
new file mode 100644
index 0000000..1f8c12f
--- /dev/null
+++ b/Poco/DOM/NodeList.h
@@ -0,0 +1,61 @@
+//
+// NodeList.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM NodeList interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_NodeList_INCLUDED
+#define DOM_NodeList_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/DOMObject.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+
+
+class XML_API NodeList: public DOMObject
+	/// The NodeList interface provides the abstraction of an ordered
+	/// collection of nodes, without defining or constraining how this
+	/// collection is implemented.
+	///
+	/// The items in the NodeList are accessible via an integral index, 
+	/// starting from 0.
+	///
+	/// A NodeList returned from a method must be released with a call to 
+	/// release() when no longer needed.
+{
+public:
+	virtual Node* item(unsigned long index) const = 0;
+		/// Returns the index'th item in the collection. If index is
+		/// greater than or equal to the number of nodes in the list,
+		/// this returns null.
+
+	virtual unsigned long length() const = 0;
+		/// Returns the number of nodes in the list. The range of valid
+		/// node indices is 0 to length - 1 inclusive.
+	
+protected:
+	virtual ~NodeList();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_NodeList_INCLUDED
diff --git a/Poco/DOM/Notation.h b/Poco/DOM/Notation.h
new file mode 100644
index 0000000..c9824b0
--- /dev/null
+++ b/Poco/DOM/Notation.h
@@ -0,0 +1,93 @@
+//
+// Notation.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Notation class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Notation_INCLUDED
+#define DOM_Notation_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractNode.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Notation: public AbstractNode
+	/// This interface represents a notation declared in the DTD. A notation either
+	/// declares, by name, the format of an unparsed entity (see section 4.7 of
+	/// the XML 1.0 specification <http://www.w3.org/TR/2004/REC-xml-20040204/>), 
+	/// or is used for formal declaration of processing
+	/// instruction targets (see section 2.6 of the XML 1.0 specification).
+	/// The nodeName attribute inherited from Node is set to the declared name of
+	/// the notation.
+	/// 
+	/// The DOM Level 1 does not support editing Notation nodes; they are therefore
+	/// readonly.
+	/// 
+	/// A Notation node does not have any parent.
+{
+public:
+	const XMLString& publicId() const;
+		/// Returns the public identifier of this notation.
+		/// If not specified, this is an empty string (and not null,
+		/// as in the DOM specification).
+
+	const XMLString& systemId() const;
+		/// Returns the system identifier of this notation.
+		/// If not specified, this is an empty string (and not null,
+		/// as in the DOM specification).
+
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+protected:
+	Notation(Document* pOwnerDocument, const XMLString& name, const XMLString& publicId, const XMLString& systemId);
+	Notation(Document* pOwnerDocument, const Notation& notation);
+	~Notation();
+	
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	XMLString _name;
+	XMLString _publicId;
+	XMLString _systemId;
+	
+	friend class Document;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Notation::publicId() const
+{
+	return _publicId;
+}
+
+
+inline const XMLString& Notation::systemId() const
+{
+	return _systemId;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Notation_INCLUDED
diff --git a/Poco/DOM/ProcessingInstruction.h b/Poco/DOM/ProcessingInstruction.h
new file mode 100644
index 0000000..ab600ca
--- /dev/null
+++ b/Poco/DOM/ProcessingInstruction.h
@@ -0,0 +1,99 @@
+//
+// ProcessingInstruction.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM ProcessingInstruction class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_ProcessingInstruction_INCLUDED
+#define DOM_ProcessingInstruction_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/AbstractNode.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API ProcessingInstruction: public AbstractNode
+	/// The ProcessingInstruction interface represents a "processing instruction",
+	/// used in XML as a way to keep processor-specific information in the text
+	/// of the document.
+{
+public:
+	const XMLString& target() const;
+		/// Returns the target of this processing instruction.
+		/// XML defines this as being the first token following
+		/// the markup that begins the processing instruction.
+
+	const XMLString& data() const;
+		/// Returns the content of this processing instruction. This is from the first non 
+		/// white space character after the target to the character immediately preceding
+		/// the ?>.
+
+	const XMLString& getData() const;
+		/// Returns the content of this processing instruction. This is from the first non 
+		/// white space character after the target to the character immediately preceding
+		/// the ?>.
+
+	void setData(const XMLString& data);
+		/// Sets the content of this processing instruction.
+
+	// Node
+	const XMLString& nodeName() const;
+	const XMLString& getNodeValue() const;
+	void setNodeValue(const XMLString& data);
+	unsigned short nodeType() const;
+
+protected:
+	ProcessingInstruction(Document* pOwnerDocument, const XMLString& target, const XMLString& data);
+	ProcessingInstruction(Document* pOwnerDocument, const ProcessingInstruction& processingInstruction);
+	~ProcessingInstruction();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	XMLString _target;
+	XMLString _data;
+	
+	friend class Document;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& ProcessingInstruction::target() const
+{
+	return _target;
+}
+
+
+inline const XMLString& ProcessingInstruction::data() const
+{
+	return _data;
+}
+
+
+inline const XMLString& ProcessingInstruction::getData() const
+{
+	return _data;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_ProcessingInstruction_INCLUDED
diff --git a/Poco/DOM/Text.h b/Poco/DOM/Text.h
new file mode 100644
index 0000000..3a7931a
--- /dev/null
+++ b/Poco/DOM/Text.h
@@ -0,0 +1,79 @@
+//
+// Text.h
+//
+// Library: XML
+// Package: DOM
+// Module:  DOM
+//
+// Definition of the DOM Text class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_Text_INCLUDED
+#define DOM_Text_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/DOM/CharacterData.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Text: public CharacterData
+	/// The Text interface inherits from CharacterData and represents the textual
+	/// content (termed character data in XML) of an Element or Attr. If there is
+	/// no markup inside an element's content, the text is contained in a single
+	/// object implementing the Text interface that is the only child of the element.
+	/// If there is markup, it is parsed into the information items (elements, comments,
+	/// etc.) and Text nodes that form the list of children of the element.
+	/// 
+	/// When a document is first made available via the DOM, there is only one Text
+	/// node for each block of text. Users may create adjacent Text nodes that represent
+	/// the contents of a given element without any intervening markup, but should
+	/// be aware that there is no way to represent the separations between these
+	/// nodes in XML or HTML, so they will not (in general) persist between DOM
+	/// editing sessions. The normalize() method on Element merges any such adjacent
+	/// Text objects into a single node for each block of text.
+{
+public:
+	Text* splitText(unsigned long offset);
+		/// Breaks this node into two nodes at the specified offset, keeping both in
+		/// the tree as siblings. This node then only contains all the content up to
+		/// the offset point. A new node of the same type, which is inserted as the
+		/// next sibling of this node, contains all the content at and after the offset
+		/// point. When the offset is equal to the length of this node, the new node
+		/// has no data.
+
+	// Node
+	const XMLString& nodeName() const;
+	unsigned short nodeType() const;
+
+	// Non-standard extensions
+	XMLString innerText() const;
+
+protected:
+	Text(Document* pOwnerDocument, const XMLString& data);
+	Text(Document* pOwnerDocument, const Text& text);
+	~Text();
+
+	Node* copyNode(bool deep, Document* pOwnerDocument) const;
+
+private:
+	static const XMLString NODE_NAME;
+	
+	friend class Document;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_Text_INCLUDED
diff --git a/Poco/DOM/TreeWalker.h b/Poco/DOM/TreeWalker.h
new file mode 100644
index 0000000..884b37d
--- /dev/null
+++ b/Poco/DOM/TreeWalker.h
@@ -0,0 +1,211 @@
+//
+// TreeWalker.h
+//
+// Library: XML
+// Package: DOM
+// Module:  TreeWalker
+//
+// Definition of the DOM TreeWalker class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef DOM_TreeWalker_INCLUDED
+#define DOM_TreeWalker_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Node;
+class NodeFilter;
+
+
+class XML_API TreeWalker
+	/// TreeWalker objects are used to navigate a document tree or subtree using
+	/// the view of the document defined by their whatToShow flags and filter (if
+	/// any). Any function which performs navigation using a TreeWalker will automatically
+	/// support any view defined by a TreeWalker.
+	/// 
+	/// Omitting nodes from the logical view of a subtree can result in a structure
+	/// that is substantially different from the same subtree in the complete, unfiltered
+	/// document. Nodes that are siblings in the TreeWalker view may be children
+	/// of different, widely separated nodes in the original view. For instance,
+	/// consider a NodeFilter that skips all nodes except for Text nodes and the
+	/// root node of a document. In the logical view that results, all text nodes
+	/// will be siblings and appear as direct children of the root node, no matter
+	/// how deeply nested the structure of the original document.
+	///
+	/// A TreeWalker can be directly instantiated using one of its constructors -
+	/// the DocumentTraversal interface is not needed and therefore not implemented.
+	/// Unlike most other DOM classes, TreeWalker supports value semantics.
+	///
+	/// If the TreeWalker's current node is removed from the document, the
+	/// result of calling any of the movement methods is undefined. This behavior 
+	/// does not conform to the DOM Level 2 Traversal specification.
+{
+public:
+	TreeWalker(Node* root, unsigned long whatToShow, NodeFilter* pFilter = 0);
+		/// Creates a TreeWalker over the subtree rooted at the specified node.
+		
+	TreeWalker(const TreeWalker& walker);
+		/// Creates a TreeWalker by copying another TreeWalker.
+		
+	TreeWalker& operator = (const TreeWalker& walker);
+		/// Assignment operator.
+	
+	~TreeWalker();
+		/// Destroys the TreeWalker.
+	
+	Node* root() const;
+		/// The root node of the TreeWalker, as specified when it was created.
+
+	unsigned long whatToShow() const;
+		/// This attribute determines which node types are presented via the TreeWalker.
+		/// The available set of constants is defined in the NodeFilter interface. Nodes
+		/// not accepted by whatToShow will be skipped, but their children may still
+		/// be considered. Note that this skip takes precedence over the filter, if
+		/// any.
+
+	NodeFilter* filter() const;
+		/// The NodeFilter used to screen nodes.
+
+	bool expandEntityReferences() const;
+		/// The value of this flag determines whether the children of entity reference
+		/// nodes are visible to the iterator. If false, they and their descendants
+		/// will be rejected. Note that this rejection takes precedence over whatToShow
+		/// and the filter. Also note that this is currently the only situation where
+		/// NodeIterators may reject a complete subtree rather than skipping individual
+		/// nodes.
+		/// 
+		/// To produce a view of the document that has entity references expanded and
+		/// does not expose the entity reference node itself, use the whatToShow flags
+		/// to hide the entity reference node and set expandEntityReferences to true
+		/// when creating the iterator. To produce a view of the document that has entity
+		/// reference nodes but no entity expansion, use the whatToShow flags to show
+		/// the entity reference node and set expandEntityReferences to false.
+		///
+		/// This implementation does not support entity reference expansion and
+		/// thus always returns false.
+
+	Node* currentNode() const;
+		/// The node at which the TreeWalker is currently positioned.
+		/// Alterations to the DOM tree may cause the current node to no longer be accepted
+		/// by the TreeWalker's associated filter. currentNode may also be explicitly
+		/// set to any node, whether or not it is within the subtree specified by the
+		/// root node or would be accepted by the filter and whatToShow flags. Further
+		/// traversal occurs relative to currentNode even if it is not part of the current
+		/// view, by applying the filters in the requested direction; if no traversal
+		/// is possible, currentNode is not changed.
+
+	Node* getCurrentNode() const;
+		/// See currentNode().
+		
+	void setCurrentNode(Node* pNode);
+		/// Sets the current node.
+
+	Node* parentNode();
+		/// Moves to and returns the closest visible ancestor node of the current node.
+		/// If the search for parentNode attempts to step upward from the TreeWalker's
+		/// root node, or if it fails to find a visible ancestor node, this method retains
+		/// the current position and returns null.
+
+	Node* firstChild();
+		/// Moves the TreeWalker to the first visible child of the current node, and
+		/// returns the new node. If the current node has no visible children, returns
+		/// null, and retains the current node.
+
+	Node* lastChild();
+		/// Moves the TreeWalker to the last visible child of the current node, and
+		/// returns the new node. If the current node has no visible children, returns
+		/// null, and retains the current node.
+
+	Node* previousSibling();
+		/// Moves the TreeWalker to the previous sibling of the current node, and returns
+		/// the new node. If the current node has no visible previous sibling, returns
+		/// null, and retains the current node.
+
+	Node* nextSibling();
+		/// Moves the TreeWalker to the next sibling of the current node, and returns
+		/// the new node. If the current node has no visible next sibling, returns null,
+		/// and retains the current node.
+
+	Node* previousNode();
+		/// Moves the TreeWalker to the previous visible node in document order relative
+		/// to the current node, and returns the new node. If the current node has no
+		/// previous node, or if the search for previousNode attempts to step upward
+		/// from the TreeWalker's root node, returns null, and retains the current node.
+
+	Node* nextNode();
+		/// Moves the TreeWalker to the next visible node in document order relative
+		/// to the current node, and returns the new node. If the current node has no
+		/// next node, or if the search for nextNode attempts to step upward from the
+		/// TreeWalker's root node, returns null, and retains the current node.
+
+protected:
+	int accept(Node* pNode) const;
+	Node* next(Node* pNode) const;
+	Node* previous(Node* pNode) const;
+
+private:
+	TreeWalker();
+	
+	Node*         _pRoot;
+	unsigned long _whatToShow;
+	NodeFilter*   _pFilter;
+	Node*         _pCurrent;
+};
+
+
+//
+// inlines
+//
+inline Node* TreeWalker::root() const
+{
+	return _pRoot;
+}
+
+
+inline unsigned long TreeWalker::whatToShow() const
+{
+	return _whatToShow;
+}
+
+
+inline NodeFilter* TreeWalker::filter() const
+{
+	return _pFilter;
+}
+
+
+inline bool TreeWalker::expandEntityReferences() const
+{
+	return false;
+}
+
+
+inline Node* TreeWalker::currentNode() const
+{
+	return _pCurrent;
+}
+
+
+inline Node* TreeWalker::getCurrentNode() const
+{
+	return _pCurrent;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // DOM_TreeWalker_INCLUDED
diff --git a/Poco/Data/AbstractBinder.h b/Poco/Data/AbstractBinder.h
new file mode 100644
index 0000000..d88efba
--- /dev/null
+++ b/Poco/Data/AbstractBinder.h
@@ -0,0 +1,373 @@
+//
+// AbstractBinder.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractBinder
+//
+// Definition of the AbstractBinder class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractBinder_INCLUDED
+#define Data_AbstractBinder_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/DateTime.h"
+#include "Poco/Nullable.h"
+#include "Poco/Any.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/UTFString.h"
+#include <vector>
+#include <deque>
+#include <list>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+typedef NullType NullData;
+
+
+namespace Keywords {
+
+
+static const NullData null = NULL_GENERIC;
+
+
+} // namespace Keywords
+
+
+class Data_API AbstractBinder
+	/// Interface for Binding data types to placeholders.
+{
+public:
+	typedef SharedPtr<AbstractBinder> Ptr;
+
+	enum Direction
+		/// Binding direction for a parameter.
+	{
+		PD_IN,
+		PD_OUT,
+		PD_IN_OUT
+	};
+
+	AbstractBinder();
+		/// Creates the AbstractBinder.
+
+	virtual ~AbstractBinder();
+		/// Destroys the AbstractBinder.
+
+	virtual void bind(std::size_t pos, const Poco::Int8& val, Direction dir = PD_IN) = 0;
+		/// Binds an Int8.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir = PD_IN);
+		/// Binds an Int8 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir = PD_IN);
+		/// Binds an Int8 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir = PD_IN);
+		/// Binds an Int8 list.
+
+	virtual void bind(std::size_t pos, const Poco::UInt8& val, Direction dir = PD_IN) = 0;
+		/// Binds an UInt8.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir = PD_IN);
+		/// Binds an UInt8 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir = PD_IN);
+		/// Binds an UInt8 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir = PD_IN);
+		/// Binds an UInt8 list.
+
+	virtual void bind(std::size_t pos, const Poco::Int16& val, Direction dir = PD_IN) = 0;
+		/// Binds an Int16.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir = PD_IN);
+		/// Binds an Int16 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir = PD_IN);
+		/// Binds an Int16 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir = PD_IN);
+		/// Binds an Int16 list.
+
+	virtual void bind(std::size_t pos, const Poco::UInt16& val, Direction dir = PD_IN) = 0;
+		/// Binds an UInt16.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir = PD_IN);
+		/// Binds an UInt16 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir = PD_IN);
+		/// Binds an UInt16 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir = PD_IN);
+		/// Binds an UInt16 list.
+
+	virtual void bind(std::size_t pos, const Poco::Int32& val, Direction dir = PD_IN) = 0;
+		/// Binds an Int32.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir = PD_IN);
+		/// Binds an Int32 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir = PD_IN);
+		/// Binds an Int32 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir = PD_IN);
+		/// Binds an Int32 list.
+
+	virtual void bind(std::size_t pos, const Poco::UInt32& val, Direction dir = PD_IN) = 0;
+		/// Binds an UInt32.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir = PD_IN);
+		/// Binds an UInt32 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir = PD_IN);
+		/// Binds an UInt32 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir = PD_IN);
+		/// Binds an UInt32 list.
+		
+	virtual void bind(std::size_t pos, const Poco::Int64& val, Direction dir = PD_IN) = 0;
+		/// Binds an Int64.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir = PD_IN);
+		/// Binds an Int64 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir = PD_IN);
+		/// Binds an Int64 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir = PD_IN);
+		/// Binds an Int64 list.
+
+	virtual void bind(std::size_t pos, const Poco::UInt64& val, Direction dir = PD_IN) = 0;
+		/// Binds an UInt64.
+
+	virtual void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir = PD_IN);
+		/// Binds an UInt64 vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir = PD_IN);
+		/// Binds an UInt64 deque.
+
+	virtual void bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir = PD_IN);
+		/// Binds an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	virtual void bind(std::size_t pos, const long& val, Direction dir = PD_IN) = 0;
+		/// Binds a long.
+
+	virtual void bind(std::size_t pos, const unsigned long& val, Direction dir = PD_IN) = 0;
+		/// Binds an unsiged long.
+
+	virtual void bind(std::size_t pos, const std::vector<long>& val, Direction dir = PD_IN);
+		/// Binds a long vector.
+
+	virtual void bind(std::size_t pos, const std::deque<long>& val, Direction dir = PD_IN);
+		/// Binds a long deque.
+
+	virtual void bind(std::size_t pos, const std::list<long>& val, Direction dir = PD_IN);
+		/// Binds a long list.
+#endif
+
+	virtual void bind(std::size_t pos, const bool& val, Direction dir = PD_IN) = 0;
+		/// Binds a boolean.
+
+	virtual void bind(std::size_t pos, const std::vector<bool>& val, Direction dir = PD_IN);
+		/// Binds a boolean vector.
+
+	virtual void bind(std::size_t pos, const std::deque<bool>& val, Direction dir = PD_IN);
+		/// Binds a boolean deque.
+
+	virtual void bind(std::size_t pos, const std::list<bool>& val, Direction dir = PD_IN);
+		/// Binds a boolean list.
+
+	virtual void bind(std::size_t pos, const float& val, Direction dir = PD_IN) = 0;
+		/// Binds a float.
+
+	virtual void bind(std::size_t pos, const std::vector<float>& val, Direction dir = PD_IN);
+		/// Binds a float vector.
+
+	virtual void bind(std::size_t pos, const std::deque<float>& val, Direction dir = PD_IN);
+		/// Binds a float deque.
+
+	virtual void bind(std::size_t pos, const std::list<float>& val, Direction dir = PD_IN);
+		/// Binds a float list.
+
+	virtual void bind(std::size_t pos, const double& val, Direction dir = PD_IN) = 0;
+		/// Binds a double.
+
+	virtual void bind(std::size_t pos, const std::vector<double>& val, Direction dir = PD_IN);
+		/// Binds a double vector.
+
+	virtual void bind(std::size_t pos, const std::deque<double>& val, Direction dir = PD_IN);
+		/// Binds a double deque.
+
+	virtual void bind(std::size_t pos, const std::list<double>& val, Direction dir = PD_IN);
+		/// Binds a double list.
+
+	virtual void bind(std::size_t pos, const char& val, Direction dir = PD_IN) = 0;
+		/// Binds a single character.
+
+	virtual void bind(std::size_t pos, const std::vector<char>& val, Direction dir = PD_IN);
+		/// Binds a character vector.
+
+	virtual void bind(std::size_t pos, const std::deque<char>& val, Direction dir = PD_IN);
+		/// Binds a character deque.
+
+	virtual void bind(std::size_t pos, const std::list<char>& val, Direction dir = PD_IN);
+		/// Binds a character list.
+
+	virtual void bind(std::size_t pos, const char* const& pVal, Direction dir = PD_IN) = 0;
+		/// Binds a const char ptr.
+
+	virtual void bind(std::size_t pos, const std::string& val, Direction dir = PD_IN) = 0;
+		/// Binds a string.
+
+	virtual void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir = PD_IN);
+		/// Binds a string vector.
+
+	virtual void bind(std::size_t pos, const std::deque<std::string>& val, Direction dir = PD_IN);
+		/// Binds a string deque.
+
+	virtual void bind(std::size_t pos, const std::list<std::string>& val, Direction dir = PD_IN);
+		/// Binds a string list.
+
+	virtual void bind(std::size_t pos, const UTF16String& val, Direction dir = PD_IN);
+		/// Binds a UTF-16 Unicode string.
+
+	virtual void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir = PD_IN);
+		/// Binds a UTF-16 Unicode string vector.
+
+	virtual void bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir = PD_IN);
+		/// Binds a UTF-16 Unicode string deque.
+
+	virtual void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir = PD_IN);
+		/// Binds a UTF-16 Unicode string list.
+
+	virtual void bind(std::size_t pos, const BLOB& val, Direction dir = PD_IN) = 0;
+		/// Binds a BLOB.
+
+	virtual void bind(std::size_t pos, const CLOB& val, Direction dir = PD_IN) = 0;
+		/// Binds a CLOB.
+
+	virtual void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir = PD_IN);
+		/// Binds a BLOB vector.
+
+	virtual void bind(std::size_t pos, const std::deque<BLOB>& val, Direction dir = PD_IN);
+		/// Binds a BLOB deque.
+
+	virtual void bind(std::size_t pos, const std::list<BLOB>& val, Direction dir = PD_IN);
+		/// Binds a BLOB list.
+
+	virtual void bind(std::size_t pos, const std::vector<CLOB>& val, Direction dir = PD_IN);
+		/// Binds a CLOB vector.
+
+	virtual void bind(std::size_t pos, const std::deque<CLOB>& val, Direction dir = PD_IN);
+		/// Binds a CLOB deque.
+
+	virtual void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir = PD_IN);
+		/// Binds a CLOB list.
+
+	virtual void bind(std::size_t pos, const DateTime& val, Direction dir = PD_IN) = 0;
+		/// Binds a DateTime.
+
+	virtual void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir = PD_IN);
+		/// Binds a DateTime vector.
+
+	virtual void bind(std::size_t pos, const std::deque<DateTime>& val, Direction dir = PD_IN);
+		/// Binds a DateTime deque.
+
+	virtual void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir = PD_IN);
+		/// Binds a DateTime list.
+
+	virtual void bind(std::size_t pos, const Date& val, Direction dir = PD_IN) = 0;
+		/// Binds a Date.
+
+	virtual void bind(std::size_t pos, const std::vector<Date>& val, Direction dir = PD_IN);
+		/// Binds a Date vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Date>& val, Direction dir = PD_IN);
+		/// Binds a Date deque.
+
+	virtual void bind(std::size_t pos, const std::list<Date>& val, Direction dir = PD_IN);
+		/// Binds a Date list.
+
+	virtual void bind(std::size_t pos, const Time& val, Direction dir = PD_IN) = 0;
+		/// Binds a Time.
+
+	virtual void bind(std::size_t pos, const std::vector<Time>& val, Direction dir = PD_IN);
+		/// Binds a Time vector.
+
+	virtual void bind(std::size_t pos, const std::deque<Time>& val, Direction dir = PD_IN);
+		/// Binds a Time deque.
+
+	virtual void bind(std::size_t pos, const std::list<Time>& val, Direction dir = PD_IN);
+		/// Binds a Time list.
+
+	virtual void bind(std::size_t pos, const NullData& val, Direction dir = PD_IN) = 0;
+		/// Binds a null.
+
+	virtual void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir = PD_IN);
+		/// Binds a null vector.
+
+	virtual void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir = PD_IN);
+		/// Binds a null deque.
+
+	virtual void bind(std::size_t pos, const std::list<NullData>& val, Direction dir = PD_IN);
+		/// Binds a null list.
+
+	void bind(std::size_t pos, const Any& val, Direction dir = PD_IN);
+		/// Binds an Any.
+	
+	void bind(std::size_t pos, const Poco::Dynamic::Var& val, Direction dir = PD_IN);
+	/// Binds a Var.
+
+	virtual void reset();
+		/// Resets a binder. No-op by default. Implement for binders that cache data.
+
+	static bool isOutBound(Direction dir);
+		/// Returns true if direction is out bound;
+
+	static bool isInBound(Direction dir);
+		/// Returns true if direction is in bound;
+};
+
+
+//
+// inlines
+//
+inline void AbstractBinder::reset()
+{
+	//no-op
+}
+
+
+inline bool AbstractBinder::isOutBound(Direction dir)
+{
+	return PD_OUT == dir || PD_IN_OUT == dir;
+}
+
+
+inline bool AbstractBinder::isInBound(Direction dir)
+{
+	return PD_IN == dir || PD_IN_OUT == dir;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractBinder_INCLUDED
diff --git a/Poco/Data/AbstractBinding.h b/Poco/Data/AbstractBinding.h
new file mode 100644
index 0000000..1c16da1
--- /dev/null
+++ b/Poco/Data/AbstractBinding.h
@@ -0,0 +1,144 @@
+//
+// AbstractBinding.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractBinding
+//
+// Definition of the AbstractBinding class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractBinding_INCLUDED
+#define Data_AbstractBinding_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractBinder.h"
+#include "Poco/Any.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <vector>
+#include <list>
+#include <deque>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API AbstractBinding
+	/// AbstractBinding connects a value with a placeholder via an AbstractBinder interface.
+{
+public:
+	typedef SharedPtr<AbstractBinding> Ptr;
+	typedef AbstractBinder::Ptr        BinderPtr;
+
+	enum Direction
+	{
+		PD_IN = AbstractBinder::PD_IN,
+		PD_OUT = AbstractBinder::PD_OUT,
+		PD_IN_OUT = AbstractBinder::PD_IN_OUT
+	};
+
+	AbstractBinding(const std::string& name = "", Direction direction = PD_IN, Poco::UInt32 bulkSize = 0);
+		/// Creates the AbstractBinding.
+
+	virtual ~AbstractBinding();
+		/// Destroys the AbstractBinding.
+
+	void setBinder(BinderPtr pBinder);
+		/// Sets the object used for binding; object does NOT take ownership of the pointer.
+
+	BinderPtr getBinder() const;
+		/// Returns the AbstractBinder used for binding data.
+
+	virtual std::size_t numOfColumnsHandled() const = 0;
+		/// Returns the number of columns that the binding handles.
+		///
+		/// The trivial case will be one single column but when
+		/// complex types are used this value can be larger than one.
+
+	virtual std::size_t numOfRowsHandled() const = 0;
+		/// Returns the number of rows that the binding handles.
+		///
+		/// The trivial case will be one single row but 
+		/// for collection data types it can be larger.
+
+	virtual bool canBind() const = 0;
+		/// Returns true if we have enough data to bind
+
+	virtual void bind(std::size_t pos) = 0;
+		/// Binds a value to the given column position
+
+	virtual void reset() = 0;
+		/// Allows a binding to be reused.
+
+	AbstractBinder::Direction getDirection() const;
+		/// Returns the binding direction.
+
+	const std::string& name() const;
+		/// Returns the name for this binding.
+
+	bool isBulk() const;
+		/// Returns true if extraction is bulk.
+
+	Poco::UInt32 bulkSize() const;
+		/// Returns the size of the bulk binding.
+
+private:
+	BinderPtr    _pBinder;
+	std::string  _name;
+	Direction    _direction;
+	Poco::UInt32 _bulkSize;
+};
+
+
+typedef std::vector<AbstractBinding::Ptr> AbstractBindingVec;
+typedef std::deque<AbstractBinding::Ptr>  AbstractBindingDeq;
+typedef std::list<AbstractBinding::Ptr>   AbstractBindingLst;
+
+
+//
+// inlines
+//
+inline AbstractBinder::Ptr AbstractBinding::getBinder() const
+{
+	return _pBinder;
+}
+
+
+inline const std::string& AbstractBinding::name() const
+{
+	return _name;
+}
+
+
+inline AbstractBinder::Direction AbstractBinding::getDirection() const
+{
+	return (AbstractBinder::Direction) _direction;
+}
+
+
+inline bool AbstractBinding::isBulk() const
+{
+	return _bulkSize > 0;
+}
+
+
+inline Poco::UInt32 AbstractBinding::bulkSize() const
+{
+	return _bulkSize;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractBinding_INCLUDED
diff --git a/Poco/Data/AbstractExtraction.h b/Poco/Data/AbstractExtraction.h
new file mode 100644
index 0000000..8960d74
--- /dev/null
+++ b/Poco/Data/AbstractExtraction.h
@@ -0,0 +1,278 @@
+//
+// AbstractExtraction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractExtraction
+//
+// Definition of the AbstractExtraction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractExtraction_INCLUDED
+#define Data_AbstractExtraction_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractExtractor.h"
+#include "Poco/Data/AbstractPreparation.h"
+#include "Poco/Data/Limit.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/UTFString.h"
+#include "Poco/AutoPtr.h"
+#include <vector>
+#include <deque>
+#include <list>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+class AbstractPreparator;
+
+
+class Data_API AbstractExtraction
+	/// AbstractExtraction is the interface class that connects output positions to concrete values
+	/// retrieved via an AbstractExtractor.
+{
+public:
+	typedef SharedPtr<AbstractExtraction> Ptr;
+	typedef SharedPtr<AbstractExtractor>  ExtractorPtr;
+	typedef SharedPtr<AbstractPreparator> PreparatorPtr;
+
+	AbstractExtraction(Poco::UInt32 limit = Limit::LIMIT_UNLIMITED,
+		Poco::UInt32 position = 0, bool bulk = false);
+		/// Creates the AbstractExtraction. A limit value equal to EXTRACT_UNLIMITED (0xffffffffu) 
+		/// means that we extract as much data as possible during one execute.
+		/// Otherwise the limit value is used to partition data extracting to a limited amount of rows.
+
+	virtual ~AbstractExtraction();
+		/// Destroys the AbstractExtraction.
+
+	void setExtractor(ExtractorPtr pExtractor);
+		/// Sets the class used for extracting the data. Does not take ownership of the pointer.
+
+	ExtractorPtr getExtractor() const;
+		/// Retrieves the extractor object
+
+	Poco::UInt32 position() const;
+		/// Returns the extraction position.
+
+	virtual std::size_t numOfColumnsHandled() const = 0;
+		/// Returns the number of columns that the extraction handles.
+		///
+		/// The trivial case will be one single column but when
+		/// complex types are used this value can be larger than one.
+
+	virtual std::size_t numOfRowsHandled() const = 0;
+		/// Returns the number of rows that the extraction handles.
+		///
+		/// The trivial case will be one single row but 
+		/// for collection data types (ie vector) it can be larger.
+
+	virtual std::size_t numOfRowsAllowed() const = 0;
+		/// Returns the upper limit on number of rows that the extraction will handle.
+
+	virtual std::size_t extract(std::size_t pos) = 0;
+		/// Extracts a value from the param, starting at the given column position.
+		/// Returns the number of rows extracted.
+
+	virtual void reset();
+		/// Resets the extractor so that it can be re-used.
+		/// Does nothing in this implementation.
+		/// Implementations should override it for different behavior.
+
+	virtual bool canExtract() const;
+		/// Returns true. Implementations should override it for different behavior.
+
+	virtual AbstractPreparation::Ptr createPreparation(PreparatorPtr& pPrep, std::size_t pos) = 0;
+		/// Creates and returns shared pointer to Preparation object for the extracting object.
+
+	void setLimit(Poco::UInt32 limit);
+		/// Sets the limit.
+
+	Poco::UInt32 getLimit() const;
+		/// Gets the limit.
+
+	virtual bool isNull(std::size_t row) const;
+		/// In implementations, this function returns true if value at row is null, 
+		/// false otherwise. 
+		/// Normal behavior is to replace nulls with default values.
+		/// However, extraction implementations may remember the underlying database
+		/// null values and be able to later provide information about them.
+		/// Here, this function throws NotImplementedException.
+
+	bool isBulk() const;
+		/// Returns true if this is bulk extraction.
+
+	void setEmptyStringIsNull(bool emptyStringIsNull);
+		/// Sets the empty string handling flag.
+
+	bool getEmptyStringIsNull() const;
+		/// Returns the empty string handling flag.
+
+	void setForceEmptyString(bool forceEmptyString);
+		/// Sets the force empty string flag.
+
+	bool getForceEmptyString() const;
+		/// Returns the force empty string flag.
+
+	template <typename T>
+	bool isValueNull(const T& str, bool deflt)
+		/// Utility function to determine the nullness of the value.
+		/// This generic version always returns default value
+		/// (i.e. does nothing). The std::string overload does
+		/// the actual work.
+		///
+	{
+		return deflt;
+	}
+
+	bool isValueNull(const std::string& str, bool deflt);
+		/// Overload for const reference to std::string.
+		///
+		/// Returns true when folowing conditions are met:
+		///
+		/// - string is empty 
+		/// - getEmptyStringIsNull() returns true
+
+	bool isValueNull(const Poco::UTF16String& str, bool deflt);
+		/// Overload for const reference to UTF16String.
+		///
+		/// Returns true when folowing conditions are met:
+		///
+		/// - string is empty 
+		/// - getEmptyStringIsNull() returns true
+
+private:
+	template <typename S>
+	bool isStringNull(const S& str, bool deflt)
+	{
+		if (getForceEmptyString()) return false;
+
+		if (getEmptyStringIsNull() && str.empty())
+			return true;
+
+		return deflt;
+	}
+
+	ExtractorPtr _pExtractor;
+	Poco::UInt32 _limit;
+	Poco::UInt32 _position;
+	bool         _bulk;
+	bool         _emptyStringIsNull;
+	bool         _forceEmptyString;
+};
+
+
+typedef std::vector<AbstractExtraction::Ptr> AbstractExtractionVec;
+typedef std::vector<AbstractExtractionVec>   AbstractExtractionVecVec;
+typedef std::deque<AbstractExtraction::Ptr>  AbstractExtractionDeq;
+typedef std::vector<AbstractExtractionDeq>   AbstractExtractionDeqVec;
+typedef std::list<AbstractExtraction::Ptr>   AbstractExtractionLst;
+typedef std::vector<AbstractExtractionLst>   AbstractExtractionLstVec;
+
+
+//
+// inlines
+//
+inline void AbstractExtraction::setExtractor(ExtractorPtr pExtractor)
+{
+	_pExtractor = pExtractor;
+}
+
+
+inline AbstractExtraction::ExtractorPtr AbstractExtraction::getExtractor() const
+{
+	return _pExtractor;
+}
+
+
+inline void AbstractExtraction::setLimit(Poco::UInt32 limit)
+{
+	_limit = limit;
+}
+
+
+inline Poco::UInt32 AbstractExtraction::getLimit() const
+{
+	return _limit;
+}
+
+
+inline bool AbstractExtraction::isNull(std::size_t row) const
+{
+	throw NotImplementedException("Check for null values not implemented.");
+}
+
+
+inline Poco::UInt32 AbstractExtraction::position() const
+{
+	return _position;
+}
+
+
+inline bool AbstractExtraction::isBulk() const
+{
+	return _bulk;
+}
+
+
+inline void AbstractExtraction::reset()
+{
+}
+
+
+inline bool AbstractExtraction::canExtract() const
+{
+	return true;
+}
+
+
+inline void AbstractExtraction::setEmptyStringIsNull(bool emptyStringIsNull)
+{
+	_emptyStringIsNull = emptyStringIsNull;
+}
+
+
+inline bool AbstractExtraction::getEmptyStringIsNull() const
+{
+	return _emptyStringIsNull;
+}
+
+
+inline void AbstractExtraction::setForceEmptyString(bool forceEmptyString)
+{
+	_forceEmptyString = forceEmptyString;
+}
+
+
+inline bool AbstractExtraction::getForceEmptyString() const
+{
+	return _forceEmptyString;
+}
+
+
+inline bool AbstractExtraction::isValueNull(const std::string& str, bool deflt)
+{
+	return isStringNull(str, deflt);
+}
+
+
+inline bool AbstractExtraction::isValueNull(const Poco::UTF16String& str, bool deflt)
+{
+	return isStringNull(str, deflt);
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractExtraction_INCLUDED
diff --git a/Poco/Data/AbstractExtractor.h b/Poco/Data/AbstractExtractor.h
new file mode 100644
index 0000000..aa973bc
--- /dev/null
+++ b/Poco/Data/AbstractExtractor.h
@@ -0,0 +1,351 @@
+//
+// AbstractExtractor.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractExtractor
+//
+// Definition of the AbstractExtractor class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractExtractor_INCLUDED
+#define Data_AbstractExtractor_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Constants.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/UTFString.h"
+#include <vector>
+#include <deque>
+#include <list>
+#include <string>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class DateTime;
+class Any;
+
+namespace Dynamic {
+class Var;
+}
+
+namespace Data {
+
+
+class Date;
+class Time;
+
+
+class Data_API AbstractExtractor
+	/// Interface used to extract data from a single result row.
+	/// If an extractor receives null it is not allowed to change val!
+{
+public:
+	typedef SharedPtr<AbstractExtractor> Ptr;
+
+	AbstractExtractor();
+		/// Creates the AbstractExtractor.
+
+	virtual ~AbstractExtractor();
+		/// Destroys the AbstractExtractor.
+
+	virtual bool extract(std::size_t pos, Poco::Int8& val) = 0;
+		/// Extracts an Int8. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
+		/// Extracts an Int8 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int8>& val);
+		/// Extracts an Int8 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int8>& val);
+		/// Extracts an Int8 list.
+
+	virtual bool extract(std::size_t pos, Poco::UInt8& val) = 0;
+		/// Extracts an UInt8. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
+		/// Extracts an UInt8 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt8>& val);
+		/// Extracts an UInt8 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt8>& val);
+		/// Extracts an UInt8 list.
+
+	virtual bool extract(std::size_t pos, Poco::Int16& val) = 0;
+		/// Extracts an Int16. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
+		/// Extracts an Int16 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int16>& val);
+		/// Extracts an Int16 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int16>& val);
+		/// Extracts an Int16 list.
+
+	virtual bool extract(std::size_t pos, Poco::UInt16& val) = 0;
+		/// Extracts an UInt16. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
+		/// Extracts an UInt16 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt16>& val);
+		/// Extracts an UInt16 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt16>& val);
+		/// Extracts an UInt16 list.
+
+	virtual bool extract(std::size_t pos, Poco::Int32& val) = 0;
+		/// Extracts an Int32. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
+		/// Extracts an Int32 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int32>& val);
+		/// Extracts an Int32 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int32>& val);
+		/// Extracts an Int32 list.
+
+	virtual bool extract(std::size_t pos, Poco::UInt32& val) = 0;
+		/// Extracts an UInt32. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
+		/// Extracts an UInt32 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt32>& val);
+		/// Extracts an UInt32 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt32>& val);
+		/// Extracts an UInt32 list.
+
+	virtual bool extract(std::size_t pos, Poco::Int64& val) = 0;
+		/// Extracts an Int64. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
+		/// Extracts an Int64 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Int64>& val);
+		/// Extracts an Int64 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Int64>& val);
+		/// Extracts an Int64 list.
+
+	virtual bool extract(std::size_t pos, Poco::UInt64& val) = 0;
+		/// Extracts an UInt64. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
+		/// Extracts an UInt64 vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::UInt64>& val);
+		/// Extracts an UInt64 deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::UInt64>& val);
+		/// Extracts an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	virtual bool extract(std::size_t pos, long& val) = 0;
+		/// Extracts a long. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, unsigned long& val) = 0;
+		/// Extracts an unsigned long. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<long>& val);
+		/// Extracts a long vector.
+
+	virtual bool extract(std::size_t pos, std::deque<long>& val);
+		/// Extracts a long deque.
+
+	virtual bool extract(std::size_t pos, std::list<long>& val);
+		/// Extracts a long list.
+#endif
+
+	virtual bool extract(std::size_t pos, bool& val) = 0;
+		/// Extracts a boolean. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<bool>& val);
+		/// Extracts a boolean vector.
+
+	virtual bool extract(std::size_t pos, std::deque<bool>& val);
+		/// Extracts a boolean deque.
+
+	virtual bool extract(std::size_t pos, std::list<bool>& val);
+		/// Extracts a boolean list.
+
+	virtual bool extract(std::size_t pos, float& val) = 0;
+		/// Extracts a float. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<float>& val);
+		/// Extracts a float vector.
+
+	virtual bool extract(std::size_t pos, std::deque<float>& val);
+		/// Extracts a float deque.
+
+	virtual bool extract(std::size_t pos, std::list<float>& val);
+		/// Extracts a float list.
+
+	virtual bool extract(std::size_t pos, double& val) = 0;
+		/// Extracts a double. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<double>& val);
+		/// Extracts a double vector.
+
+	virtual bool extract(std::size_t pos, std::deque<double>& val);
+		/// Extracts a double deque.
+
+	virtual bool extract(std::size_t pos, std::list<double>& val);
+		/// Extracts a double list.
+
+	virtual bool extract(std::size_t pos, char& val) = 0;
+		/// Extracts a single character. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<char>& val);
+		/// Extracts a character vector.
+
+	virtual bool extract(std::size_t pos, std::deque<char>& val);
+		/// Extracts a character deque.
+
+	virtual bool extract(std::size_t pos, std::list<char>& val);
+		/// Extracts a character list.
+
+	virtual bool extract(std::size_t pos, std::string& val) = 0;
+		/// Extracts a string. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<std::string>& val);
+		/// Extracts a string vector.
+
+	virtual bool extract(std::size_t pos, std::deque<std::string>& val);
+		/// Extracts a string deque.
+
+	virtual bool extract(std::size_t pos, std::list<std::string>& val);
+		/// Extracts a string list.
+
+	virtual bool extract(std::size_t pos, UTF16String& val);
+		/// Extracts a UTF16String. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<UTF16String>& val);
+		/// Extracts a UTF16String vector.
+
+	virtual bool extract(std::size_t pos, std::deque<UTF16String>& val);
+		/// Extracts a UTF16String deque.
+
+	virtual bool extract(std::size_t pos, std::list<UTF16String>& val);
+		/// Extracts a UTF16String list.
+
+	virtual bool extract(std::size_t pos, BLOB& val) = 0;
+		/// Extracts a BLOB. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, CLOB& val) = 0;
+		/// Extracts a CLOB. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<BLOB>& val);
+		/// Extracts a BLOB vector.
+
+	virtual bool extract(std::size_t pos, std::deque<BLOB>& val);
+		/// Extracts a BLOB deque.
+
+	virtual bool extract(std::size_t pos, std::list<BLOB>& val);
+		/// Extracts a BLOB list.
+
+	virtual bool extract(std::size_t pos, std::vector<CLOB>& val);
+		/// Extracts a CLOB vector.
+
+	virtual bool extract(std::size_t pos, std::deque<CLOB>& val);
+		/// Extracts a CLOB deque.
+
+	virtual bool extract(std::size_t pos, std::list<CLOB>& val);
+		/// Extracts a CLOB list.
+
+	virtual bool extract(std::size_t pos, DateTime& val) = 0;
+		/// Extracts a DateTime. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<DateTime>& val);
+		/// Extracts a DateTime vector.
+
+	virtual bool extract(std::size_t pos, std::deque<DateTime>& val);
+		/// Extracts a DateTime deque.
+
+	virtual bool extract(std::size_t pos, std::list<DateTime>& val);
+		/// Extracts a DateTime list.
+
+	virtual bool extract(std::size_t pos, Date& val) = 0;
+		/// Extracts a Date. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Date>& val);
+		/// Extracts a Date vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Date>& val);
+		/// Extracts a Date deque.
+
+	virtual bool extract(std::size_t pos, std::list<Date>& val);
+		/// Extracts a Date list.
+
+	virtual bool extract(std::size_t pos, Time& val) = 0;
+		/// Extracts a Time. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Time>& val);
+		/// Extracts a Time vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Time>& val);
+		/// Extracts a Time deque.
+
+	virtual bool extract(std::size_t pos, std::list<Time>& val);
+		/// Extracts a Time list.
+
+	virtual bool extract(std::size_t pos, Any& val) = 0;
+		/// Extracts an Any. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Any>& val);
+		/// Extracts an Any vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Any>& val);
+		/// Extracts an Any deque.
+
+	virtual bool extract(std::size_t pos, std::list<Any>& val);
+		/// Extracts an Any list.
+
+	virtual bool extract(std::size_t pos, Poco::Dynamic::Var& val) = 0;
+		/// Extracts a Var. Returns false if null was received.
+
+	virtual bool extract(std::size_t pos, std::vector<Poco::Dynamic::Var>& val);
+		/// Extracts a Var vector.
+
+	virtual bool extract(std::size_t pos, std::deque<Poco::Dynamic::Var>& val);
+		/// Extracts a Var deque.
+
+	virtual bool extract(std::size_t pos, std::list<Poco::Dynamic::Var>& val);
+		/// Extracts a Var list.
+
+	virtual bool isNull(std::size_t col, std::size_t row = POCO_DATA_INVALID_ROW) = 0;
+		/// Returns true if the value at [col,row] position is null.
+
+	virtual void reset();
+		/// Resets any information internally cached by the extractor.
+};
+
+
+///
+/// inlines
+///
+inline void AbstractExtractor::reset()
+{
+	//default no-op
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractExtractor_INCLUDED
diff --git a/Poco/Data/AbstractPreparation.h b/Poco/Data/AbstractPreparation.h
new file mode 100644
index 0000000..6d92157
--- /dev/null
+++ b/Poco/Data/AbstractPreparation.h
@@ -0,0 +1,71 @@
+//
+// AbstractPreparation.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractPreparation
+//
+// Definition of the AbstractPreparation class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractPreparation_INCLUDED
+#define Data_AbstractPreparation_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractPreparator.h"
+#include "Poco/SharedPtr.h"
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API AbstractPreparation
+	/// Interface for calling the appropriate AbstractPreparator method
+{
+public:
+	typedef SharedPtr<AbstractPreparation> Ptr;
+	typedef AbstractPreparator::Ptr PreparatorPtr;
+
+	AbstractPreparation(PreparatorPtr pPreparator);
+		/// Creates the AbstractPreparation.
+
+	virtual ~AbstractPreparation();
+		/// Destroys the AbstractPreparation.
+
+	virtual void prepare() = 0;
+		/// Prepares data.
+
+protected:
+	AbstractPreparation();
+	AbstractPreparation(const AbstractPreparation&);
+	AbstractPreparation& operator = (const AbstractPreparation&);
+
+	PreparatorPtr preparation();
+		/// Returns the preparation object
+
+	PreparatorPtr _pPreparator;
+};
+
+
+//
+// inlines
+//
+inline AbstractPreparation::PreparatorPtr AbstractPreparation::preparation()
+{
+	return _pPreparator;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractPreparation_INCLUDED
diff --git a/Poco/Data/AbstractPreparator.h b/Poco/Data/AbstractPreparator.h
new file mode 100644
index 0000000..da086b0
--- /dev/null
+++ b/Poco/Data/AbstractPreparator.h
@@ -0,0 +1,388 @@
+//
+// AbstractPreparator.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractPreparator
+//
+// Definition of the AbstractPreparator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractPreparator_INCLUDED
+#define Data_AbstractPreparator_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/UTFString.h"
+#include <vector>
+#include <deque>
+#include <list>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class DateTime;
+class Any;
+
+namespace Dynamic {
+class Var;
+}
+
+
+namespace Data {
+
+
+class Date;
+class Time;
+
+
+class Data_API AbstractPreparator
+	/// Interface used for database preparation where we first have to register all data types
+	/// (and memory output locations) before extracting data, e.g. ODBC.
+	/// Extract works as two-phase extract: first we call prepare once, then extract n-times.
+	/// There are cases (bulk operations using std::vector storage) when extract is called only once.
+	/// The value passed to a prepare() call is not used by the prepare, serving only as an indication 
+	/// of the data type being prepared, thus all values are passed as const references. 
+	/// Implementing this interface is not mandatory for a connector. Connectors that only extract data 
+	/// after SQL execution (e.g. SQLite) do not need this functionality at all.
+{
+public:
+	typedef SharedPtr<AbstractPreparator> Ptr;
+
+	AbstractPreparator(Poco::UInt32 length = 1u);
+		/// Creates the AbstractPreparator.
+
+	virtual ~AbstractPreparator();
+		/// Destroys the AbstractPreparator.
+
+	virtual void prepare(std::size_t pos, const Poco::Int8&) = 0;
+		/// Prepares an Int8.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::Int8>& val);
+		/// Prepares an Int8 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::Int8>& val);
+		/// Prepares an Int8 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::Int8>& val);
+		/// Prepares an Int8 list.
+
+	virtual void prepare(std::size_t pos, const Poco::UInt8&) = 0;
+		/// Prepares an UInt8.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::UInt8>& val);
+		/// Prepares an UInt8 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::UInt8>& val);
+		/// Prepares an UInt8 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::UInt8>& val);
+		/// Prepares an UInt8 list.
+
+	virtual void prepare(std::size_t pos, const Poco::Int16&) = 0;
+		/// Prepares an Int16.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::Int16>& val);
+		/// Prepares an Int16 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::Int16>& val);
+		/// Prepares an Int16 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::Int16>& val);
+		/// Prepares an Int16 list.
+
+	virtual void prepare(std::size_t pos, const Poco::UInt16&) = 0;
+		/// Prepares an UInt16.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::UInt16>& val);
+		/// Prepares an UInt16 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::UInt16>& val);
+		/// Prepares an UInt16 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::UInt16>& val);
+		/// Prepares an UInt16 list.
+
+	virtual void prepare(std::size_t pos, const Poco::Int32&) = 0;
+		/// Prepares an Int32.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::Int32>& val);
+		/// Prepares an Int32 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::Int32>& val);
+		/// Prepares an Int32 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::Int32>& val);
+		/// Prepares an Int32 list.
+
+	virtual void prepare(std::size_t pos, const Poco::UInt32&) = 0;
+		/// Prepares an UInt32.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::UInt32>& val);
+		/// Prepares an UInt32 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::UInt32>& val);
+		/// Prepares an UInt32 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::UInt32>& val);
+		/// Prepares an UInt32 list.
+
+	virtual void prepare(std::size_t pos, const Poco::Int64&) = 0;
+		/// Prepares an Int64.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::Int64>& val);
+		/// Prepares an Int64 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::Int64>& val);
+		/// Prepares an Int64 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::Int64>& val);
+		/// Prepares an Int64 list.
+
+	virtual void prepare(std::size_t pos, const Poco::UInt64&) = 0;
+		/// Prepares an UInt64.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::UInt64>& val);
+		/// Prepares an UInt64 vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::UInt64>& val);
+		/// Prepares an UInt64 deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::UInt64>& val);
+		/// Prepares an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	virtual void prepare(std::size_t pos, const long&) = 0;
+		/// Prepares a long.
+
+	virtual void prepare(std::size_t pos, const unsigned long&) = 0;
+		/// Prepares an unsigned long.
+
+	virtual void prepare(std::size_t pos, const std::vector<long>& val);
+		/// Prepares a long vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<long>& val);
+		/// Prepares a long deque.
+
+	virtual void prepare(std::size_t pos, const std::list<long>& val);
+		/// Prepares a long list.
+#endif
+
+	virtual void prepare(std::size_t pos, const bool&) = 0;
+		/// Prepares a boolean.
+
+	virtual void prepare(std::size_t pos, const std::vector<bool>& val);
+		/// Prepares a boolean vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<bool>& val);
+		/// Prepares a boolean deque.
+
+	virtual void prepare(std::size_t pos, const std::list<bool>& val);
+		/// Prepares a boolean list.
+
+	virtual void prepare(std::size_t pos, const float&) = 0;
+		/// Prepares a float.
+
+	virtual void prepare(std::size_t pos, const std::vector<float>& val);
+		/// Prepares a float vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<float>& val);
+		/// Prepares a float deque.
+
+	virtual void prepare(std::size_t pos, const std::list<float>& val);
+		/// Prepares a float list.
+
+	virtual void prepare(std::size_t pos, const double&) = 0;
+		/// Prepares a double.
+
+	virtual void prepare(std::size_t pos, const std::vector<double>& val);
+		/// Prepares a double vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<double>& val);
+		/// Prepares a double deque.
+
+	virtual void prepare(std::size_t pos, const std::list<double>& val);
+		/// Prepares a double list.
+
+	virtual void prepare(std::size_t pos, const char&) = 0;
+		/// Prepares a single character.
+
+	virtual void prepare(std::size_t pos, const std::vector<char>& val);
+		/// Prepares a character vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<char>& val);
+		/// Prepares a character deque.
+
+	virtual void prepare(std::size_t pos, const std::list<char>& val);
+		/// Prepares a character list.
+
+	virtual void prepare(std::size_t pos, const std::string&) = 0;
+		/// Prepares a string.
+
+	virtual void prepare(std::size_t pos, const std::vector<std::string>& val);
+		/// Prepares a string vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<std::string>& val);
+		/// Prepares a string deque.
+
+	virtual void prepare(std::size_t pos, const std::list<std::string>& val);
+		/// Prepares a character list.
+
+	virtual void prepare(std::size_t pos, const UTF16String&);
+		/// Prepares a UTF16String.
+
+	virtual void prepare(std::size_t pos, const std::vector<UTF16String>& val);
+		/// Prepares a UTF16String vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<UTF16String>& val);
+		/// Prepares a UTF16String deque.
+
+	virtual void prepare(std::size_t pos, const std::list<UTF16String>& val);
+		/// Prepares a UTF16String list.
+
+	virtual void prepare(std::size_t pos, const BLOB&) = 0;
+		/// Prepares a BLOB.
+
+	virtual void prepare(std::size_t pos, const CLOB&) = 0;
+		/// Prepares a CLOB.
+
+	virtual void prepare(std::size_t pos, const std::vector<BLOB>& val);
+		/// Prepares a BLOB vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<BLOB>& val);
+		/// Prepares a BLOB deque.
+
+	virtual void prepare(std::size_t pos, const std::list<BLOB>& val);
+		/// Prepares a BLOB list.
+
+	virtual void prepare(std::size_t pos, const std::vector<CLOB>& val);
+		/// Prepares a CLOB vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<CLOB>& val);
+		/// Prepares a CLOB deque.
+
+	virtual void prepare(std::size_t pos, const std::list<CLOB>& val);
+		/// Prepares a CLOB list.
+
+	virtual void prepare(std::size_t pos, const DateTime&) = 0;
+		/// Prepares a DateTime.
+
+	virtual void prepare(std::size_t pos, const std::vector<DateTime>& val);
+		/// Prepares a DateTime vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<DateTime>& val);
+		/// Prepares a DateTime deque.
+
+	virtual void prepare(std::size_t pos, const std::list<DateTime>& val);
+		/// Prepares a DateTime list.
+
+	virtual void prepare(std::size_t pos, const Date&) = 0;
+		/// Prepares a Date.
+
+	virtual void prepare(std::size_t pos, const std::vector<Date>& val);
+		/// Prepares a Date vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Date>& val);
+		/// Prepares a Date deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Date>& val);
+		/// Prepares a Date list.
+
+	virtual void prepare(std::size_t pos, const Time&) = 0;
+		/// Prepares a Time.
+
+	virtual void prepare(std::size_t pos, const std::vector<Time>& val);
+		/// Prepares a Time vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Time>& val);
+		/// Prepares a Time deque.
+	
+	virtual void prepare(std::size_t pos, const std::list<Time>& val);
+		/// Prepares a Time list.
+
+	virtual void prepare(std::size_t pos, const Any&) = 0;
+		/// Prepares an Any.
+
+	virtual void prepare(std::size_t pos, const std::vector<Any>& val);
+		/// Prepares an Any vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Any>& val);
+		/// Prepares an Any deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Any>& val);
+		/// Prepares an Any list.
+
+	virtual void prepare(std::size_t pos, const Poco::Dynamic::Var&) = 0;
+		/// Prepares a Var.
+
+	virtual void prepare(std::size_t pos, const std::vector<Poco::Dynamic::Var>& val);
+		/// Prepares a Var vector.
+
+	virtual void prepare(std::size_t pos, const std::deque<Poco::Dynamic::Var>& val);
+		/// Prepares a Var deque.
+
+	virtual void prepare(std::size_t pos, const std::list<Poco::Dynamic::Var>& val);
+		/// Prepares a Var list.
+
+	void setLength(Poco::UInt32 length);
+		/// Sets the length of prepared data.
+		/// Needed only for data lengths greater than 1 (i.e. for
+		/// bulk operations).
+
+	Poco::UInt32 getLength() const;
+		/// Returns the length of prepared data. Defaults to 1.
+		/// The length is greater than one for bulk operations.
+
+	void setBulk(bool bulkPrep = true);
+		/// Sets bulk operation flag (always false at object creation time)
+
+	bool isBulk() const;
+		/// Returns bulk operation flag.
+
+private:
+	Poco::UInt32 _length;
+	bool         _bulk;
+};
+
+
+///
+/// inlines
+///
+inline void AbstractPreparator::setLength(Poco::UInt32 length)
+{
+	_length = length;
+}
+
+
+inline Poco::UInt32 AbstractPreparator::getLength() const
+{
+	return _length;
+}
+
+
+inline void AbstractPreparator::setBulk(bool bulkPrep)
+{
+	_bulk = bulkPrep;
+}
+
+
+inline bool AbstractPreparator::isBulk() const
+{
+	return _bulk;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractPreparator_INCLUDED
diff --git a/Poco/Data/AbstractSessionImpl.h b/Poco/Data/AbstractSessionImpl.h
new file mode 100644
index 0000000..97b4fe1
--- /dev/null
+++ b/Poco/Data/AbstractSessionImpl.h
@@ -0,0 +1,315 @@
+//
+// AbstractSessionImpl.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AbstractSessionImpl
+//
+// Definition of the AbstractSessionImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_AbstractSessionImpl_INCLUDED
+#define Data_AbstractSessionImpl_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/Data/DataException.h"
+#include <map>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <class C>
+class AbstractSessionImpl: public SessionImpl
+	/// A partial implementation of SessionImpl, providing
+	/// features and properties management.
+	///
+	/// To implement a certain feature or property, a subclass
+	/// must provide setter and getter methods and register
+	/// them with addFeature() or addProperty().
+{
+public:
+	typedef void (C::*FeatureSetter)(const std::string&, bool);
+		/// The setter method for a feature.
+		
+	typedef bool (C::*FeatureGetter)(const std::string&);
+		/// The getter method for a feature.
+		
+	typedef void (C::*PropertySetter)(const std::string&, const Poco::Any&);
+		/// The setter method for a property.
+		
+	typedef Poco::Any (C::*PropertyGetter)(const std::string&);
+		/// The getter method for a property.
+
+	AbstractSessionImpl(const std::string& connectionString,
+		std::size_t timeout = LOGIN_TIMEOUT_DEFAULT): SessionImpl(connectionString, timeout),
+			_storage(std::string("deque")),
+			_bulk(false),
+			_emptyStringIsNull(false),
+			_forceEmptyString(false)
+		/// Creates the AbstractSessionImpl.
+		/// 
+		/// Adds "storage" property and sets the default internal storage container 
+		/// type to std::deque.
+		/// The storage is created by statements automatically whenever a query 
+		/// returning results is executed but external storage is provided by the user.
+		/// Storage type can be reconfigured at runtime both globally (for the
+		/// duration of the session) and locally (for a single statement execution only). 
+		/// See StatementImpl for details on how this property is used at runtime.
+		/// 
+		/// Adds "handle" property which, if set by the back end, returns native handle
+		/// for the back end DB.
+		/// 
+		/// Adds "bulk" feature and sets it to false.
+		/// Bulk feature determines whether the session is capable of bulk operations.
+		/// Connectors that are capable of it must set this feature prior to attempting 
+		/// bulk operations.
+		///
+		/// Adds "emptyStringIsNull" feature and sets it to false. This feature should be
+		/// set to true in order to modify the behavior of the databases that distinguish
+		/// between zero-length character strings as nulls. Setting this feature to true 
+		/// shall disregard any difference between empty character strings and nulls,
+		/// causing the framework to treat them the same (i.e. behave like Oracle).		
+		///
+		/// Adds "forceEmptyString" feature and sets it to false. This feature should be set
+		/// to true in order to force the databases that do not distinguish empty strings from
+		/// nulls (e.g. Oracle) to always report empty string.
+		///
+		/// The "emptyStringIsNull" and "forceEmptyString" features are mutually exclusive.
+		/// While these features can not both be true at the same time, they can both be false,
+		/// resulting in default underlying database behavior.
+		///
+	{
+		addProperty("storage", 
+			&AbstractSessionImpl<C>::setStorage, 
+			&AbstractSessionImpl<C>::getStorage);
+
+		addProperty("handle", 
+			&AbstractSessionImpl<C>::setHandle,
+			&AbstractSessionImpl<C>::getHandle);
+
+		addFeature("bulk", 
+			&AbstractSessionImpl<C>::setBulk, 
+			&AbstractSessionImpl<C>::getBulk);
+
+		addFeature("emptyStringIsNull", 
+			&AbstractSessionImpl<C>::setEmptyStringIsNull,
+			&AbstractSessionImpl<C>::getEmptyStringIsNull);
+
+		addFeature("forceEmptyString", 
+			&AbstractSessionImpl<C>::setForceEmptyString,
+			&AbstractSessionImpl<C>::getForceEmptyString);
+	}
+
+	~AbstractSessionImpl()
+		/// Destroys the AbstractSessionImpl.
+	{
+	}
+
+	void setFeature(const std::string& name, bool state)
+		/// Looks a feature up in the features map
+		/// and calls the feature's setter, if there is one.
+	{
+		typename FeatureMap::const_iterator it = _features.find(name);
+		if (it != _features.end())
+		{
+			if (it->second.setter)
+				(static_cast<C*>(this)->*it->second.setter)(name, state);
+			else
+				throw NotImplementedException("set", name);
+		}
+		else throw NotSupportedException(name);
+	}
+	
+	bool getFeature(const std::string& name)
+		/// Looks a feature up in the features map
+		/// and calls the feature's getter, if there is one.
+	{
+		typename FeatureMap::const_iterator it = _features.find(name);
+		if (it != _features.end())
+		{
+			if (it->second.getter)
+				return (static_cast<C*>(this)->*it->second.getter)(name);
+			else
+				throw NotImplementedException("get", name);
+		}
+		else throw NotSupportedException(name);
+	}
+	
+	void setProperty(const std::string& name, const Poco::Any& value)
+		/// Looks a property up in the properties map
+		/// and calls the property's setter, if there is one.
+	{
+		typename PropertyMap::const_iterator it = _properties.find(name);
+		if (it != _properties.end())
+		{
+			if (it->second.setter)
+				(static_cast<C*>(this)->*it->second.setter)(name, value);
+			else
+				throw NotImplementedException("set", name);
+		}
+		else throw NotSupportedException(name);
+	}
+
+	Poco::Any getProperty(const std::string& name)
+		/// Looks a property up in the properties map
+		/// and calls the property's getter, if there is one.
+	{
+		typename PropertyMap::const_iterator it = _properties.find(name);
+		if (it != _properties.end())
+		{
+			if (it->second.getter)
+				return (static_cast<C*>(this)->*it->second.getter)(name);
+			else
+				throw NotImplementedException("set", name);
+		}
+		else throw NotSupportedException(name);
+	}
+	
+	void setStorage(const std::string& value)
+		/// Sets the storage type.
+	{
+		_storage = value;
+	}
+
+	void setStorage(const std::string& name, const Poco::Any& value)
+		/// Sets the storage type.
+	{
+		_storage = Poco::RefAnyCast<std::string>(value);
+	}
+		
+	Poco::Any getStorage(const std::string& name="")
+		/// Returns the storage type
+	{
+		return _storage;
+	}
+
+	void setHandle(const std::string& name, const Poco::Any& handle)
+		/// Sets the native session handle. 
+	{
+		_handle = handle;
+	}
+		
+	Poco::Any getHandle(const std::string& name="")
+		/// Returns the native session handle. 
+	{
+		return _handle;
+	}
+
+	void setBulk(const std::string& name, bool bulk)
+		/// Sets the execution type.
+	{
+		_bulk = bulk;
+	}
+		
+	bool getBulk(const std::string& name="")
+		/// Returns the execution type
+	{
+		return _bulk;
+	}
+
+	void setEmptyStringIsNull(const std::string& name, bool emptyStringIsNull)
+		/// Sets the behavior regarding empty variable length strings.
+		/// Those are treated as NULL by Oracle and as empty string by
+		/// most other databases.
+		/// When this feature is true, empty strings are treated as NULL.
+	{
+		if (emptyStringIsNull && _forceEmptyString)
+			throw InvalidAccessException("Features mutually exclusive");
+
+		_emptyStringIsNull = emptyStringIsNull;
+	}
+		
+	bool getEmptyStringIsNull(const std::string& name="")
+		/// Returns the setting for the behavior regarding empty variable
+		/// length strings. See setEmptyStringIsNull(const std::string&, bool)
+		/// and this class documentation for feature rationale and details.
+	{
+		return _emptyStringIsNull;
+	}
+
+	void setForceEmptyString(const std::string& name, bool forceEmptyString)
+		/// Sets the behavior regarding empty variable length strings.
+		/// Those are treated as NULL by Oracle and as empty string by
+		/// most other databases.
+		/// When this feature is true, both empty strings and NULL values
+		/// are reported as empty strings.
+	{
+		if (forceEmptyString && _emptyStringIsNull)
+			throw InvalidAccessException("Features mutually exclusive");
+
+		_forceEmptyString = forceEmptyString;
+	}
+		
+	bool getForceEmptyString(const std::string& name="")
+		/// Returns the setting for the behavior regarding empty variable
+		/// length strings. See setForceEmptyString(const std::string&, bool)
+		/// and this class documentation for feature rationale and details.
+	{
+		return _forceEmptyString;
+	}
+
+protected:
+	void addFeature(const std::string& name, FeatureSetter setter, FeatureGetter getter)
+		/// Adds a feature to the map of supported features.
+		///
+		/// The setter or getter can be null, in case setting or getting a feature
+		/// is not supported.
+	{
+		Feature feature;
+		feature.setter = setter;
+		feature.getter = getter;
+		_features[name] = feature;
+	}
+		
+	void addProperty(const std::string& name, PropertySetter setter, PropertyGetter getter)
+		/// Adds a property to the map of supported properties.
+		///
+		/// The setter or getter can be null, in case setting or getting a property
+		/// is not supported.
+	{
+		Property property;
+		property.setter = setter;
+		property.getter = getter;
+		_properties[name] = property;
+	}
+
+private:
+	struct Feature
+	{
+		FeatureSetter setter;
+		FeatureGetter getter;
+	};
+	
+	struct Property
+	{
+		PropertySetter setter;
+		PropertyGetter getter;
+	};
+	
+	typedef std::map<std::string, Feature>  FeatureMap;
+	typedef std::map<std::string, Property> PropertyMap;
+	
+	FeatureMap  _features;
+	PropertyMap _properties;
+	std::string _storage;
+	bool        _bulk;
+	bool        _emptyStringIsNull;
+	bool        _forceEmptyString;
+	Poco::Any   _handle;
+};
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AbstractSessionImpl_INCLUDED
diff --git a/Poco/Data/ArchiveStrategy.h b/Poco/Data/ArchiveStrategy.h
new file mode 100644
index 0000000..3b644c5
--- /dev/null
+++ b/Poco/Data/ArchiveStrategy.h
@@ -0,0 +1,222 @@
+//
+// ArchiveStrategy.h
+//
+// Library: Data
+// Package: Logging
+// Module:  ArchiveStrategy
+//
+// Definition of the ArchiveStrategy class and subclasses.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ArchiveStrategy_INCLUDED
+#define Data_ArchiveStrategy_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Session.h"
+#include "Poco/DateTime.h"
+#include "Poco/Timespan.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/SharedPtr.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API ArchiveStrategy
+	/// The ArchiveStrategy is used by SQLChannel to archive log rows.
+{
+public:
+	static const std::string DEFAULT_ARCHIVE_DESTINATION;
+
+	ArchiveStrategy(const std::string& connector, 
+		const std::string& connect, 
+		const std::string& source, 
+		const std::string& destination = DEFAULT_ARCHIVE_DESTINATION);
+		/// Creates archive strategy.
+
+	virtual ~ArchiveStrategy();
+		/// Destroys archive strategy.
+
+	void open();
+		/// Opens the session.
+
+	virtual void archive() = 0;
+		/// Archives the rows.
+
+	const std::string& getSource() const;
+		/// Returns the name of the source table containing rows to be archived.
+
+	void setSource(const std::string& source);
+		/// Sets the name of the source table.
+
+	const std::string& getDestination() const;
+		/// Returns the name of the destination table for rows to be archived.
+
+	void setDestination(const std::string& destination);
+		/// Sets the name of the destination table.
+
+	virtual const std::string& getThreshold() const = 0;
+		/// Returns the archive threshold.
+
+	virtual void setThreshold(const std::string& threshold) = 0;
+		/// Sets the archive threshold.
+
+protected:
+	typedef Poco::SharedPtr<Session>   SessionPtr;
+	typedef Poco::SharedPtr<Statement> StatementPtr;
+
+	Session& session();
+
+	void setCopyStatement();
+	void setDeleteStatement();
+	void setCountStatement();
+
+	Statement& getCopyStatement();
+	Statement& getDeleteStatement();
+	Statement& getCountStatement();
+private:
+	
+	ArchiveStrategy();
+	ArchiveStrategy(const ArchiveStrategy&);
+	ArchiveStrategy& operator = (const ArchiveStrategy&);
+
+	std::string  _connector;
+	std::string  _connect;
+	SessionPtr   _pSession;
+	StatementPtr _pCopyStatement;
+	StatementPtr _pDeleteStatement;
+	StatementPtr _pCountStatement;
+	std::string  _source;
+	std::string  _destination;
+};
+
+
+//
+// inlines
+//
+
+inline const std::string& ArchiveStrategy::getSource() const
+{
+	return _source;
+}
+
+
+inline void ArchiveStrategy::setSource(const std::string& source)
+{
+	_source = source;
+}
+
+
+inline void ArchiveStrategy::setDestination(const std::string& destination)
+{
+	_destination = destination;
+}
+
+
+inline const std::string& ArchiveStrategy::getDestination() const
+{
+	return _destination;
+}
+
+
+inline Session& ArchiveStrategy::session()
+{
+	return *_pSession;
+}
+
+
+inline void ArchiveStrategy::setCopyStatement()
+{
+	_pCopyStatement = new Statement(*_pSession);
+}
+
+
+inline void ArchiveStrategy::setDeleteStatement()
+{
+	_pDeleteStatement = new Statement(*_pSession);
+}
+
+
+inline void ArchiveStrategy::setCountStatement()
+{
+	_pCountStatement = new Statement(*_pSession);
+}
+
+
+inline Statement& ArchiveStrategy::getCopyStatement()
+{
+	return *_pCopyStatement;
+}
+
+
+inline Statement& ArchiveStrategy::getDeleteStatement()
+{
+	return *_pDeleteStatement;
+}
+
+
+inline Statement& ArchiveStrategy::getCountStatement()
+{
+	return *_pCountStatement;
+}
+
+
+
+//
+// ArchiveByAgeStrategy
+//
+class Data_API ArchiveByAgeStrategy: public ArchiveStrategy
+	/// Archives rows scheduled for archiving.
+{
+public:
+	ArchiveByAgeStrategy(const std::string& connector, 
+		const std::string& connect, 
+		const std::string& sourceTable, 
+		const std::string& destinationTable = DEFAULT_ARCHIVE_DESTINATION);
+	
+	~ArchiveByAgeStrategy();
+
+	void archive();
+
+	const std::string& getThreshold() const;
+		/// Returns the archive threshold.
+
+	void setThreshold(const std::string& threshold);
+		/// Sets the archive threshold.
+
+private:
+	ArchiveByAgeStrategy();
+	ArchiveByAgeStrategy(const ArchiveByAgeStrategy&);
+	ArchiveByAgeStrategy& operator = (const ArchiveByAgeStrategy&);
+
+	void initStatements();
+
+	Timespan     _maxAge;
+	std::string  _ageString;
+	DateTime     _archiveDateTime;
+	Poco::Dynamic::Var _archiveCount;
+};
+
+
+//
+// inlines
+//
+
+inline const std::string& ArchiveByAgeStrategy::getThreshold() const
+{
+	return _ageString;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_ArchiveStrategy_INCLUDED
diff --git a/Poco/Data/AutoTransaction.h b/Poco/Data/AutoTransaction.h
new file mode 100644
index 0000000..6d88184
--- /dev/null
+++ b/Poco/Data/AutoTransaction.h
@@ -0,0 +1,35 @@
+//
+// AutoTransaction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  AutoTransaction
+//
+// Forward header for the Transaction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+
+#ifndef Data_AutoTransaction_INCLUDED
+#define Data_AutoTransaction_INCLUDED
+
+
+#include "Poco/Data/Transaction.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+typedef Transaction AutoTransaction;
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_AutoTransaction_INCLUDED
diff --git a/Poco/Data/Binding.h b/Poco/Data/Binding.h
new file mode 100644
index 0000000..464c314
--- /dev/null
+++ b/Poco/Data/Binding.h
@@ -0,0 +1,1496 @@
+//
+// Binding.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Binding
+//
+// Definition of the Binding class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Binding_INCLUDED
+#define Data_Binding_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractBinding.h"
+#include "Poco/Data/DataException.h"
+#include "Poco/Data/TypeHandler.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/MetaProgramming.h"
+#include "Poco/Bugcheck.h"
+#include <vector>
+#include <list>
+#include <deque>
+#include <set>
+#include <map>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <class T>
+class Binding: public AbstractBinding
+	/// Binding maps a value or multiple values (see Binding specializations for STL containers as
+	/// well as type handlers) to database column(s). Values to be bound can be either mapped 
+	/// directly (by reference) or a copy can be created, depending on the value of the copy argument.
+	/// To pass a reference to a variable, it is recommended to pass it to the intermediate
+	/// utility function use(), which will create the proper binding. In cases when a reference 
+	/// is passed to binding, the storage it refers to must be valid at the statement execution time.
+	/// To pass a copy of a variable, constant or string literal, use utility function bind().
+	/// Variables can be passed as either copies or references (i.e. using either use() or bind()).
+	/// Constants, however, can only be passed as copies. this is best achieved using bind() utility 
+	/// function. An attempt to pass a constant by reference shall result in compile-time error.
+{
+public:
+	typedef T                  ValType;
+	typedef SharedPtr<ValType> ValPtr;
+	typedef Binding<ValType>   Type;
+	typedef SharedPtr<Type>    Ptr;
+
+	explicit Binding(T& val,
+		const std::string& name = "", 
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction),
+		_val(val), 
+		_bound(false)
+		/// Creates the Binding using the passed reference as bound value.
+		/// If copy is true, a copy of the value referred to is created.
+	{
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return 1u;
+	}
+
+	bool canBind() const
+	{
+		return !_bound;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		TypeHandler<T>::bind(pos, _val, getBinder(), getDirection());
+		_bound = true;
+	}
+
+	void reset ()
+	{
+		_bound = false;
+		AbstractBinder::Ptr pBinder = getBinder();
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->reset();
+	}
+
+private:
+	const T& _val;
+	bool     _bound;
+};
+
+
+
+template <class T>
+class CopyBinding: public AbstractBinding
+	/// Binding maps a value or multiple values (see Binding specializations for STL containers as
+	/// well as type handlers) to database column(s). Values to be bound can be either mapped 
+	/// directly (by reference) or a copy can be created, depending on the value of the copy argument.
+	/// To pass a reference to a variable, it is recommended to pass it to the intermediate
+	/// utility function use(), which will create the proper binding. In cases when a reference 
+	/// is passed to binding, the storage it refers to must be valid at the statement execution time.
+	/// To pass a copy of a variable, constant or string literal, use utility function bind().
+	/// Variables can be passed as either copies or references (i.e. using either use() or bind()).
+{
+public:
+	typedef T                    ValType;
+	typedef SharedPtr<ValType>   ValPtr;
+	typedef CopyBinding<ValType> Type;
+	typedef SharedPtr<Type>      Ptr;
+
+	explicit CopyBinding(T& val,
+		const std::string& name = "", 
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction),
+		_pVal(new T(val)),
+		_bound(false)
+		/// Creates the Binding using the passed reference as bound value.
+		/// If copy is true, a copy of the value referred to is created.
+	{
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return 1;
+	}
+
+	bool canBind() const
+	{
+		return !_bound;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		TypeHandler<T>::bind(pos, *_pVal, getBinder(), getDirection());
+		_bound = true;
+	}
+
+	void reset ()
+	{
+		_bound = false;
+		AbstractBinder::Ptr pBinder = getBinder();
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->reset();
+	}
+
+private:
+	//typedef typename TypeWrapper<T>::TYPE ValueType;
+	ValPtr _pVal;
+	bool   _bound;
+};
+
+
+template <>
+class Binding<const char*>: public AbstractBinding
+	/// Binding const char* specialization wraps char pointer into string.
+{
+public:
+	typedef const char*          ValType;
+	typedef SharedPtr<ValType>   ValPtr;
+	typedef Binding<const char*> Type;
+	typedef SharedPtr<Type>      Ptr;
+
+	explicit Binding(const char* pVal, 
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(pVal ? pVal : throw NullPointerException() ),
+		_bound(false)
+		/// Creates the Binding by copying the passed string.
+	{
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return 1u;
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return 1u;
+	}
+
+	bool canBind() const
+	{
+		return !_bound;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		TypeHandler<std::string>::bind(pos, _val, getBinder(), getDirection());
+		_bound = true;
+	}
+
+	void reset ()
+	{
+		_bound = false;
+		AbstractBinder::Ptr pBinder = getBinder();
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->reset();
+	}
+
+private:
+	std::string _val;
+	bool        _bound;
+};
+
+
+
+template <>
+class CopyBinding<const char*>: public AbstractBinding
+	/// Binding const char* specialization wraps char pointer into string.
+{
+public:
+	typedef const char*              ValType;
+	typedef SharedPtr<ValType>       ValPtr;
+	typedef CopyBinding<const char*> Type;
+	typedef SharedPtr<Type>          Ptr;
+
+	explicit CopyBinding(const char* pVal, 
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(pVal ? pVal : throw NullPointerException() ),
+		_bound(false)
+		/// Creates the Binding by copying the passed string.
+	{
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return 1u;
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return 1u;
+	}
+
+	bool canBind() const
+	{
+		return !_bound;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		TypeHandler<std::string>::bind(pos, _val, getBinder(), getDirection());
+		_bound = true;
+	}
+
+	void reset ()
+	{
+		_bound = false;
+		AbstractBinder::Ptr pBinder = getBinder();
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->reset();
+	}
+
+private:
+	std::string _val;
+	bool        _bound;
+};
+
+
+template <class T>
+class Binding<std::vector<T> >: public AbstractBinding
+	/// Specialization for std::vector.
+{
+public:
+	typedef std::vector<T>                   ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::vector<T>& val, 
+		const std::string& name = "", 
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction),
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_val.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class T>
+class CopyBinding<std::vector<T> >: public AbstractBinding
+	/// Specialization for std::vector.
+{
+public:
+	
+	typedef std::vector<T>                   ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(std::vector<T>& val, 
+		const std::string& name = "", 
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction),
+		_pVal(new std::vector<T>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr   _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+template <>
+class Binding<std::vector<bool> >: public AbstractBinding
+	/// Specialization for std::vector<bool>.
+	/// This specialization is necessary due to the nature of std::vector<bool>.
+	/// For details, see the standard library implementation of std::vector<bool> 
+	/// or
+	/// S. Meyers: "Effective STL" (Copyright Addison-Wesley 2001),
+	/// Item 18: "Avoid using vector<bool>."
+	/// 
+	/// The workaround employed here is using std::deque<bool> as an
+	/// internal replacement container. 
+	/// 
+	/// IMPORTANT:
+	/// Only IN binding is supported.
+{
+public:
+	typedef std::vector<bool>            ValType;
+	typedef SharedPtr<ValType>           ValPtr;
+	typedef SharedPtr<Binding<ValType> > Ptr;
+	typedef ValType::const_iterator      Iterator;
+
+	explicit Binding(const std::vector<bool>& val, 
+		const std::string& name = "", 
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_deq(_val.begin(), _val.end()),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN != direction)
+			throw BindingException("Only IN direction is legal for std:vector<bool> binding.");
+
+		if (numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return 1u;
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_val.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<bool>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+
+	}
+
+	void reset()
+	{
+		_begin = _deq.begin();
+		_end   = _deq.end();
+	}
+
+private:
+	const std::vector<bool>&         _val;
+	std::deque<bool>                 _deq;
+	std::deque<bool>::const_iterator _begin;
+	std::deque<bool>::const_iterator _end;
+};
+
+
+template <>
+class CopyBinding<std::vector<bool> >: public AbstractBinding
+	/// Specialization for std::vector<bool>.
+	/// This specialization is necessary due to the nature of std::vector<bool>.
+	/// For details, see the standard library implementation of std::vector<bool> 
+	/// or
+	/// S. Meyers: "Effective STL" (Copyright Addison-Wesley 2001),
+	/// Item 18: "Avoid using vector<bool>."
+	/// 
+	/// The workaround employed here is using std::deque<bool> as an
+	/// internal replacement container. 
+	/// 
+	/// IMPORTANT:
+	/// Only IN binding is supported.
+{
+public:
+	typedef std::vector<bool>                ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef ValType::const_iterator          Iterator;
+
+	explicit CopyBinding(const std::vector<bool>& val, 
+		const std::string& name = "", 
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_deq(val.begin(), val.end()),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN != direction)
+			throw BindingException("Only IN direction is legal for std:vector<bool> binding.");
+
+		if (numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return 1u;
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_deq.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<bool>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _deq.begin();
+		_end   = _deq.end();
+	}
+
+private:
+	std::deque<bool>                 _deq;
+	std::deque<bool>::const_iterator _begin;
+	std::deque<bool>::const_iterator _end;
+};
+
+
+template <class T>
+class Binding<std::list<T> >: public AbstractBinding
+	/// Specialization for std::list.
+{
+public:
+	typedef std::list<T>                     ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::list<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _val.size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class T>
+class CopyBinding<std::list<T> >: public AbstractBinding
+	/// Specialization for std::list.
+{
+public:
+	typedef typename std::list<T>            ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(ValType& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_pVal(new std::list<T>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr   _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+template <class T>
+class Binding<std::deque<T> >: public AbstractBinding
+	/// Specialization for std::deque.
+{
+public:
+	typedef std::deque<T>                    ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::deque<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _val.size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class T>
+class CopyBinding<std::deque<T> >: public AbstractBinding
+	/// Specialization for std::deque.
+{
+public:
+	typedef std::deque<T>                    ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(std::deque<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_pVal(new std::deque<T>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr   _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+template <class T>
+class Binding<std::set<T> >: public AbstractBinding
+	/// Specialization for std::set.
+{
+public:
+	typedef std::set<T>                      ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::set<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_val.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class T>
+class CopyBinding<std::set<T> >: public AbstractBinding
+	/// Specialization for std::set.
+{
+public:
+	typedef std::set<T>                      ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(std::set<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_pVal(new std::set<T>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr   _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+template <class T>
+class Binding<std::multiset<T> >: public AbstractBinding
+	/// Specialization for std::multiset.
+{
+public:
+	typedef std::multiset<T>                 ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::multiset<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_val.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class T>
+class CopyBinding<std::multiset<T> >: public AbstractBinding
+	/// Specialization for std::multiset.
+{
+public:
+	typedef std::multiset<T>             ValType;
+	typedef SharedPtr<ValType>           ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(std::multiset<T>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_pVal(new std::multiset<T>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<T>::bind(pos, *_begin, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr    _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+template <class K, class V>
+class Binding<std::map<K, V> >: public AbstractBinding
+	/// Specialization for std::map.
+{
+public:
+	typedef std::map<K, V>                   ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::map<K, V>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<V>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_val.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<V>::bind(pos, _begin->second, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class K, class V>
+class CopyBinding<std::map<K, V> >: public AbstractBinding
+	/// Specialization for std::map.
+{
+public:
+	typedef std::map<K, V>                   ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(std::map<K, V>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_pVal(new std::map<K, V>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<V>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<V>::bind(pos, _begin->second, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr   _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+template <class K, class V>
+class Binding<std::multimap<K, V> >: public AbstractBinding
+	/// Specialization for std::multimap.
+{
+public:
+	typedef std::multimap<K, V>              ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<Binding<ValType> >     Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit Binding(std::multimap<K, V>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_val(val), 
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~Binding()
+		/// Destroys the Binding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<V>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_val.size());
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<V>::bind(pos, _begin->second, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _val.begin();
+		_end   = _val.end();
+	}
+
+private:
+	const ValType& _val;
+	Iterator       _begin;
+	Iterator       _end;
+};
+
+
+template <class K, class V>
+class CopyBinding<std::multimap<K, V> >: public AbstractBinding
+	/// Specialization for std::multimap.
+{
+public:
+	typedef std::multimap<K, V>              ValType;
+	typedef SharedPtr<ValType>               ValPtr;
+	typedef SharedPtr<CopyBinding<ValType> > Ptr;
+	typedef typename ValType::const_iterator Iterator;
+
+	explicit CopyBinding(std::multimap<K, V>& val,
+		const std::string& name = "",
+		Direction direction = PD_IN): 
+		AbstractBinding(name, direction), 
+		_pVal(new std::multimap<K, V>(val)),
+		_begin(), 
+		_end()
+		/// Creates the Binding.
+	{
+		if (PD_IN == direction && numOfRowsHandled() == 0)
+			throw BindingException("It is illegal to bind to an empty data collection");
+		reset();
+	}
+
+	~CopyBinding()
+		/// Destroys the CopyBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<V>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _pVal->size();
+	}
+
+	bool canBind() const
+	{
+		return _begin != _end;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		poco_assert_dbg(canBind());
+		TypeHandler<V>::bind(pos, _begin->second, getBinder(), getDirection());
+		++_begin;
+	}
+
+	void reset()
+	{
+		_begin = _pVal->begin();
+		_end   = _pVal->end();
+	}
+
+private:
+	ValPtr   _pVal;
+	Iterator _begin;
+	Iterator _end;
+};
+
+
+namespace Keywords {
+
+
+template <typename T> 
+inline AbstractBinding::Ptr use(T& t, const std::string& name = "")
+	/// Convenience function for a more compact Binding creation.
+{
+	// If this fails to compile, a const ref was passed to use().
+	// This can be resolved by either (a) using bind (which will copy the value),
+	// or (b) if the const ref is guaranteed to exist when execute is called 
+	// (which can be much later!), by using the "useRef" keyword instead
+	poco_static_assert (!IsConst<T>::VALUE);
+	return new Binding<T>(t, name, AbstractBinding::PD_IN);
+}
+
+
+inline AbstractBinding::Ptr use(const NullData& t, const std::string& name = "")
+	/// NullData overload.
+{
+	return new Binding<NullData>(const_cast<NullData&>(t), name, AbstractBinding::PD_IN);
+}
+
+
+template <typename T> 
+inline AbstractBinding::Ptr useRef(T& t, const std::string& name = "")
+	/// Convenience function for a more compact Binding creation.
+{
+	return new Binding<T>(t, name, AbstractBinding::PD_IN);
+}
+
+
+template <typename T> 
+inline AbstractBinding::Ptr in(T& t, const std::string& name = "")
+	/// Convenience function for a more compact Binding creation.
+{
+	return use(t, name);
+}
+
+
+inline AbstractBinding::Ptr in(const NullData& t, const std::string& name = "")
+	/// NullData overload.
+{
+	return use(t, name);
+}
+
+
+template <typename T> 
+inline AbstractBinding::Ptr out(T& t)
+	/// Convenience function for a more compact Binding creation.
+{
+	poco_static_assert (!IsConst<T>::VALUE);
+	return new Binding<T>(t, "", AbstractBinding::PD_OUT);
+}
+
+
+template <typename T> 
+inline AbstractBinding::Ptr io(T& t)
+	/// Convenience function for a more compact Binding creation.
+{
+	poco_static_assert (!IsConst<T>::VALUE);
+	return new Binding<T>(t, "", AbstractBinding::PD_IN_OUT);
+}
+
+
+inline AbstractBindingVec& use(AbstractBindingVec& bv)
+	/// Convenience dummy function (for syntax purposes only).
+{
+	return bv;
+}
+
+
+inline AbstractBindingVec& in(AbstractBindingVec& bv)
+	/// Convenience dummy function (for syntax purposes only).
+{
+	return bv;
+}
+
+
+inline AbstractBindingVec& out(AbstractBindingVec& bv)
+	/// Convenience dummy function (for syntax purposes only).
+{
+	return bv;
+}
+
+
+inline AbstractBindingVec& io(AbstractBindingVec& bv)
+	/// Convenience dummy function (for syntax purposes only).
+{
+	return bv;
+}
+
+
+template <typename T> 
+inline AbstractBinding::Ptr bind(T t, const std::string& name)
+	/// Convenience function for a more compact Binding creation.
+	/// This funtion differs from use() in its value copy semantics.
+{
+	return new CopyBinding<T>(t, name, AbstractBinding::PD_IN);
+}
+
+
+template <typename T> 
+inline AbstractBinding::Ptr bind(T t)
+	/// Convenience function for a more compact Binding creation.
+	/// This funtion differs from use() in its value copy semantics.
+{
+	return Poco::Data::Keywords::bind(t, "");
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Binding_INCLUDED
diff --git a/Poco/Data/Bulk.h b/Poco/Data/Bulk.h
new file mode 100644
index 0000000..7b30ae6
--- /dev/null
+++ b/Poco/Data/Bulk.h
@@ -0,0 +1,96 @@
+//
+// BulkExtraction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Bulk
+//
+// Definition of the BulkExtraction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Bulk_INCLUDED
+#define Data_Bulk_INCLUDED
+
+
+#include "Poco/Void.h"
+#include "Poco/Data/Limit.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API Bulk
+{
+public:
+	Bulk(const Limit& limit);
+		/// Creates the Bulk.
+
+	Bulk(Poco::UInt32 value);
+		/// Creates the Bulk.
+
+	~Bulk();
+		/// Destroys the bulk.
+
+	const Limit& limit() const;
+		/// Returns the limit asociated with this bulk object.
+
+	Poco::UInt32 size() const;
+		/// Returns the value of the limit asociated with 
+		/// this bulk object.
+	
+private:
+	Bulk();
+
+	Limit _limit;
+};
+
+
+///
+/// inlines
+///
+inline const Limit& Bulk::limit() const 
+{ 
+	return _limit; 
+}
+
+
+inline Poco::UInt32 Bulk::size() const 
+{ 
+	return _limit.value(); 
+}
+
+
+namespace Keywords {
+
+
+inline Bulk bulk(const Limit& limit = Limit(Limit::LIMIT_UNLIMITED, false, false))
+	/// Convenience function for creation of bulk.
+{
+	return Bulk(limit);
+}
+
+
+inline void bulk(Void)
+	/// Dummy bulk function. Used for bulk binding creation
+	/// (see BulkBinding) and bulk extraction signalling to Statement.
+{
+}
+
+
+} // namespace Keywords
+
+
+typedef void (*BulkFnType)(Void);
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Bulk_INCLUDED
diff --git a/Poco/Data/BulkBinding.h b/Poco/Data/BulkBinding.h
new file mode 100644
index 0000000..a28213e
--- /dev/null
+++ b/Poco/Data/BulkBinding.h
@@ -0,0 +1,148 @@
+//
+// BulkBinding.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  BulkBinding
+//
+// Definition of the BulkBinding class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_BulkBinding_INCLUDED
+#define Data_BulkBinding_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractBinding.h"
+#include "Poco/Data/DataException.h"
+#include "Poco/Data/TypeHandler.h"
+#include "Poco/Data/Bulk.h"
+#include <vector>
+#include <deque>
+#include <list>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <class T>
+class BulkBinding: public AbstractBinding
+	/// A BulkBinding maps a value to a column. 
+	/// Bulk binding support is provided only for std::vector.
+{
+public:
+	BulkBinding(const T& val, Poco::UInt32 bulkSize, const std::string& name = "", Direction direction = PD_IN): 
+		AbstractBinding(name, direction, bulkSize), 
+		_val(val), 
+		_bound(false)
+		/// Creates the BulkBinding.
+	{
+		if (0 == _val.size())
+			throw BindingException("Zero size containers not allowed.");
+	}
+
+	~BulkBinding()
+		/// Destroys the BulkBinding.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return 1;
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _val.size();
+	}
+
+	bool canBind() const
+	{
+		return !_bound;
+	}
+
+	void bind(std::size_t pos)
+	{
+		poco_assert_dbg(!getBinder().isNull());
+		TypeHandler<T>::bind(pos, _val, getBinder(), getDirection());
+		_bound = true;
+	}
+
+	void reset ()
+	{
+		_bound = false;
+		getBinder()->reset();
+	}
+
+private:
+	const T& _val;
+	bool     _bound;
+};
+
+
+namespace Keywords {
+
+
+template <typename T> 
+AbstractBinding::Ptr use(const std::vector<T>& t, BulkFnType, const std::string& name = "")
+	/// Convenience function for a more compact BulkBinding creation for std::vector.
+{
+	return new BulkBinding<std::vector<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
+}
+
+
+template <typename T> 
+AbstractBinding::Ptr in(const std::vector<T>& t, BulkFnType, const std::string& name = "")
+	/// Convenience function for a more compact BulkBinding creation for std::vector.
+{
+	return new BulkBinding<std::vector<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
+}
+
+
+template <typename T> 
+AbstractBinding::Ptr use(const std::deque<T>& t, BulkFnType, const std::string& name = "")
+	/// Convenience function for a more compact BulkBinding creation for std::deque.
+{
+	return new BulkBinding<std::deque<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
+}
+
+
+template <typename T> 
+AbstractBinding::Ptr in(const std::deque<T>& t, BulkFnType, const std::string& name = "")
+	/// Convenience function for a more compact BulkBinding creation for std::deque.
+{
+	return new BulkBinding<std::deque<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
+}
+
+
+template <typename T> 
+AbstractBinding::Ptr use(const std::list<T>& t, BulkFnType, const std::string& name = "")
+	/// Convenience function for a more compact BulkBinding creation for std::list.
+{
+	return new BulkBinding<std::list<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
+}
+
+
+template <typename T> 
+AbstractBinding::Ptr in(const std::list<T>& t, BulkFnType, const std::string& name = "")
+	/// Convenience function for a more compact BulkBinding creation for std::list.
+{
+	return new BulkBinding<std::list<T> >(t, static_cast<Poco::UInt32>(t.size()), name);
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_BulkBinding_INCLUDED
diff --git a/Poco/Data/BulkExtraction.h b/Poco/Data/BulkExtraction.h
new file mode 100644
index 0000000..75c25f6
--- /dev/null
+++ b/Poco/Data/BulkExtraction.h
@@ -0,0 +1,276 @@
+//
+// BulkExtraction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  BulkExtraction
+//
+// Definition of the BulkExtraction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_BulkExtraction_INCLUDED
+#define Data_BulkExtraction_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractExtraction.h"
+#include "Poco/Data/Bulk.h"
+#include "Poco/Data/Preparation.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <class C>
+class BulkExtraction: public AbstractExtraction
+	/// Specialization for bulk extraction of values from a query result set.
+	/// Bulk extraction support is provided only for following STL containers:
+	/// - std::vector
+	/// - std::deque
+	/// - std::list
+{
+public:
+	typedef C                       ValType;
+	typedef typename C::value_type  CValType;
+	typedef SharedPtr<ValType>      ValPtr;
+	typedef BulkExtraction<ValType> Type;
+	typedef SharedPtr<Type>         Ptr;
+
+	BulkExtraction(C& result, Poco::UInt32 limit, const Position& pos = Position(0)): 
+		AbstractExtraction(limit, pos.value(), true),
+		_rResult(result), 
+		_default()
+	{
+		if (static_cast<Poco::UInt32>(result.size()) != limit)
+			result.resize(limit);
+	}
+
+	BulkExtraction(C& result, const CValType& def, Poco::UInt32 limit, const Position& pos = Position(0)): 
+		AbstractExtraction(limit, pos.value(), true),
+		_rResult(result), 
+		_default(def)
+	{
+		if (static_cast<Poco::UInt32>(result.size()) != limit)
+			result.resize(limit);
+	}
+
+	virtual ~BulkExtraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<C>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _rResult.size();
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		try
+		{
+			return _nulls.at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	std::size_t extract(std::size_t col)
+	{
+		AbstractExtractor::Ptr pExt = getExtractor();
+		TypeHandler<C>::extract(col, _rResult, _default, pExt);
+		typename C::iterator it = _rResult.begin();
+		typename C::iterator end = _rResult.end();
+		for (int row = 0; it !=end; ++it, ++row)
+		{
+			_nulls.push_back(isValueNull(*it, pExt->isNull(col, row)));
+		}
+
+		return _rResult.size();
+	}
+
+	virtual void reset()
+	{
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t col)
+	{
+		Poco::UInt32 limit = getLimit();
+		if (limit != _rResult.size()) _rResult.resize(limit);
+		pPrep->setLength(limit);
+		pPrep->setBulk(true);
+		return new Preparation<C>(pPrep, col, _rResult);
+	}
+
+protected:
+	const C& result() const
+	{
+		return _rResult;
+	}
+
+private:
+	C&               _rResult;
+	CValType         _default;
+	std::deque<bool> _nulls;
+};
+
+
+template <class C>
+class InternalBulkExtraction: public BulkExtraction<C>
+	/// Container Data Type specialization extension for extraction of values from a query result set.
+	///
+	/// This class is intended for PocoData internal use - it is used by StatementImpl 
+	/// to automaticaly create internal BulkExtraction in cases when statement returns data and no external storage
+	/// was supplied. It is later used by RecordSet to retrieve the fetched data after statement execution.
+	/// It takes ownership of the Column pointer supplied as constructor argument. Column object, in turn
+	/// owns the data container pointer.
+	///
+	/// InternalBulkExtraction objects can not be copied or assigned.
+{
+public:
+	typedef C                               ValType;
+	typedef typename C::value_type          CValType;
+	typedef SharedPtr<ValType>              ValPtr;
+	typedef InternalBulkExtraction<ValType> Type;
+	typedef SharedPtr<Type>                 Ptr;
+
+	InternalBulkExtraction(C& result,
+		Column<C>* pColumn,
+		Poco::UInt32 limit,
+		const Position& pos = Position(0)): 
+		BulkExtraction<C>(result, CValType(), limit, pos), 
+		_pColumn(pColumn)
+		/// Creates InternalBulkExtraction.
+	{
+	}
+
+	~InternalBulkExtraction()
+		/// Destroys InternalBulkExtraction.
+	{
+		delete _pColumn;
+	}
+
+	void reset()
+	{
+		_pColumn->reset();
+	}	
+
+	const CValType& value(int index) const
+	{
+		try
+		{ 
+			return BulkExtraction<C>::result().at(index); 
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		return BulkExtraction<C>::isNull(row);
+	}
+
+	const Column<C>& column() const
+	{
+		return *_pColumn;
+	}
+
+private:
+	InternalBulkExtraction();
+	InternalBulkExtraction(const InternalBulkExtraction&);
+	InternalBulkExtraction& operator = (const InternalBulkExtraction&);
+
+	Column<C>* _pColumn;
+};
+
+
+namespace Keywords {
+
+
+template <typename T> 
+AbstractExtraction::Ptr into(std::vector<T>& t, const Bulk& bulk, const Position& pos = Position(0))
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with std::vector bulk extraction support.
+{
+	return new BulkExtraction<std::vector<T> >(t, bulk.size(), pos);
+}
+
+
+template <typename T> 
+AbstractExtraction::Ptr into(std::vector<T>& t, BulkFnType, const Position& pos = Position(0))
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with std::vector bulk extraction support.
+{
+	Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
+	if (0 == size) throw InvalidArgumentException("Zero length not allowed.");
+	return new BulkExtraction<std::vector<T> >(t, size, pos);
+}
+
+
+template <typename T> 
+AbstractExtraction::Ptr into(std::deque<T>& t, const Bulk& bulk, const Position& pos = Position(0))
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with std::deque bulk extraction support.
+{
+	return new BulkExtraction<std::deque<T> >(t, bulk.size(), pos);
+}
+
+
+template <typename T> 
+AbstractExtraction::Ptr into(std::deque<T>& t, BulkFnType, const Position& pos = Position(0))
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with std::deque bulk extraction support.
+{
+	Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
+	if (0 == size) throw InvalidArgumentException("Zero length not allowed.");
+	return new BulkExtraction<std::deque<T> >(t, size, pos);
+}
+
+
+template <typename T> 
+AbstractExtraction::Ptr into(std::list<T>& t, const Bulk& bulk, const Position& pos = Position(0))
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with std::list bulk extraction support.
+{
+	return new BulkExtraction<std::list<T> >(t, bulk.size(), pos);
+}
+
+
+template <typename T> 
+AbstractExtraction::Ptr into(std::list<T>& t, BulkFnType, const Position& pos = Position(0))
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with std::list bulk extraction support.
+{
+	Poco::UInt32 size = static_cast<Poco::UInt32>(t.size());
+	if (0 == size) throw InvalidArgumentException("Zero length not allowed.");
+	return new BulkExtraction<std::list<T> >(t, size, pos);
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_BulkExtraction_INCLUDED
diff --git a/Poco/Data/Column.h b/Poco/Data/Column.h
new file mode 100644
index 0000000..22c44a2
--- /dev/null
+++ b/Poco/Data/Column.h
@@ -0,0 +1,490 @@
+//
+// Column.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Column
+//
+// Definition of the Column class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Column_INCLUDED
+#define Data_Column_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/MetaColumn.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/RefCountedObject.h"
+#include <vector>
+#include <list>
+#include <deque>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <class C>
+class Column
+	/// Column class is column data container.
+	/// Data (a pointer to underlying STL container) is assigned to the class 
+	/// at construction time. Construction with null pointer is not allowed.
+	/// This class owns the data assigned to it and deletes the storage on destruction.
+{
+public:
+	typedef C                                  Container;
+	typedef Poco::SharedPtr<C>                 ContainerPtr;
+	typedef typename C::const_iterator         Iterator;
+	typedef typename C::const_reverse_iterator RIterator;
+	typedef typename C::size_type              Size;
+	typedef typename C::value_type             Type;
+
+	Column(const MetaColumn& metaColumn, Container* pData): 
+		_metaColumn(metaColumn),
+		_pData(pData)
+		/// Creates the Column.
+	{
+		if (!_pData)
+			throw NullPointerException("Container pointer must point to valid storage.");
+	}
+
+	Column(const Column& col): 
+		_metaColumn(col._metaColumn), 
+		_pData(col._pData)
+		/// Creates the Column.
+	{
+	}
+
+	~Column()
+		/// Destroys the Column.
+	{
+	}
+
+	Column& operator = (const Column& col)
+		/// Assignment operator.
+	{
+		Column tmp(col);
+		swap(tmp);
+		return *this;
+	}
+
+	void swap(Column& other)
+		/// Swaps the column with another one.
+	{
+		using std::swap;
+		swap(_metaColumn, other._metaColumn);
+		swap(_pData, other._pData);
+	}
+
+	Container& data()
+		/// Returns reference to contained data.
+	{
+		return *_pData;
+	}
+
+	const Type& value(std::size_t row) const
+		/// Returns the field value in specified row.
+	{
+		try
+		{
+			return _pData->at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	const Type& operator [] (std::size_t row) const
+		/// Returns the field value in specified row.
+	{
+		return value(row);
+	}
+
+	Size rowCount() const
+		/// Returns number of rows.
+	{
+		return _pData->size();
+	}
+
+	void reset()
+		/// Clears and shrinks the storage.
+	{
+		Container().swap(*_pData);
+	}
+
+	const std::string& name() const
+		/// Returns column name.
+	{
+		return _metaColumn.name();
+	}
+
+	std::size_t length() const
+		/// Returns column maximum length.
+	{
+		return _metaColumn.length();
+	}
+
+	std::size_t precision() const
+		/// Returns column precision.
+		/// Valid for floating point fields only (zero for other data types).
+	{
+		return _metaColumn.precision();
+	}
+
+	std::size_t position() const
+		/// Returns column position.
+	{
+		return _metaColumn.position();
+	}
+
+	MetaColumn::ColumnDataType type() const
+		/// Returns column type.
+	{
+		return _metaColumn.type();
+	}
+
+	Iterator begin() const
+		/// Returns iterator pointing to the beginning of data storage vector.
+	{
+		return _pData->begin();
+	}
+
+	Iterator end() const
+		/// Returns iterator pointing to the end of data storage vector.
+	{
+		return _pData->end();
+	}
+
+private:
+	Column();
+
+	MetaColumn   _metaColumn;
+	ContainerPtr _pData;
+};
+
+
+template <>
+class Column<std::vector<bool> >
+	/// The std::vector<bool> specialization for the Column class.
+	/// 
+	/// This specialization is necessary due to the nature of std::vector<bool>.
+	/// For details, see the standard library implementation of vector<bool> 
+	/// or
+	/// S. Meyers: "Effective STL" (Copyright Addison-Wesley 2001),
+	/// Item 18: "Avoid using vector<bool>."
+	/// 
+	/// The workaround employed here is using deque<bool> as an
+	/// internal "companion" container kept in sync with the vector<bool>
+	/// column data.
+{
+public:
+	typedef std::vector<bool>                 Container;
+	typedef Poco::SharedPtr<Container>        ContainerPtr;
+	typedef Container::const_iterator         Iterator;
+	typedef Container::const_reverse_iterator RIterator;
+	typedef Container::size_type              Size;
+
+	Column(const MetaColumn& metaColumn, Container* pData): 
+		_metaColumn(metaColumn), 
+		_pData(pData)
+		/// Creates the Column.
+	{
+		poco_check_ptr (_pData);
+		_deque.assign(_pData->begin(), _pData->end());
+	}
+
+	Column(const Column& col): 
+		_metaColumn(col._metaColumn), 
+		_pData(col._pData)
+		/// Creates the Column.
+	{
+		_deque.assign(_pData->begin(), _pData->end());
+	}
+
+	~Column()
+		/// Destroys the Column.
+	{
+	}
+
+	Column& operator = (const Column& col)
+		/// Assignment operator.
+	{
+		Column tmp(col);
+		swap(tmp);
+		return *this;
+	}
+
+	void swap(Column& other)
+		/// Swaps the column with another one.
+	{
+		using std::swap;
+		swap(_metaColumn, other._metaColumn);
+		swap(_pData, other._pData);
+		swap(_deque, other._deque);
+	}
+
+	Container& data()
+		/// Returns reference to contained data.
+	{
+		return *_pData;
+	}
+
+	const bool& value(std::size_t row) const
+		/// Returns the field value in specified row.
+	{
+		if (_deque.size() < _pData->size())
+			_deque.resize(_pData->size());
+
+		try
+		{
+			return _deque.at(row) = _pData->at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	const bool& operator [] (std::size_t row) const
+		/// Returns the field value in specified row.
+	{
+		return value(row);
+	}
+
+	Size rowCount() const
+		/// Returns number of rows.
+	{
+		return _pData->size();
+	}
+
+	void reset()
+		/// Clears and shrinks the storage.
+	{
+		Container().swap(*_pData);
+		_deque.clear();
+	}
+
+	const std::string& name() const
+		/// Returns column name.
+	{
+		return _metaColumn.name();
+	}
+
+	std::size_t length() const
+		/// Returns column maximum length.
+	{
+		return _metaColumn.length();
+	}
+
+	std::size_t precision() const
+		/// Returns column precision.
+		/// Valid for floating point fields only (zero for other data types).
+	{
+		return _metaColumn.precision();
+	}
+
+	std::size_t position() const
+		/// Returns column position.
+	{
+		return _metaColumn.position();
+	}
+
+	MetaColumn::ColumnDataType type() const
+		/// Returns column type.
+	{
+		return _metaColumn.type();
+	}
+
+	Iterator begin() const
+		/// Returns iterator pointing to the beginning of data storage vector.
+	{
+		return _pData->begin();
+	}
+
+	Iterator end() const
+		/// Returns iterator pointing to the end of data storage vector.
+	{
+		return _pData->end();
+	}
+
+private:
+	Column();
+
+	MetaColumn               _metaColumn;
+	ContainerPtr             _pData;
+	mutable std::deque<bool> _deque;
+};
+
+
+template <class T>
+class Column<std::list<T> >
+	/// Column specialization for std::list
+{
+public:
+	typedef std::list<T>                               Container;
+	typedef Poco::SharedPtr<Container>                 ContainerPtr;
+	typedef typename Container::const_iterator         Iterator;
+	typedef typename Container::const_reverse_iterator RIterator;
+	typedef typename Container::size_type              Size;
+
+	Column(const MetaColumn& metaColumn, std::list<T>* pData): 
+		_metaColumn(metaColumn), 
+		_pData(pData)
+		/// Creates the Column.
+	{
+		poco_check_ptr (_pData);
+	}
+
+	Column(const Column& col):
+		_metaColumn(col._metaColumn),
+		_pData(col._pData)
+		/// Creates the Column.
+	{
+	}
+
+	~Column()
+		/// Destroys the Column.
+	{
+	}
+
+	Column& operator = (const Column& col)
+		/// Assignment operator.
+	{
+		Column tmp(col);
+		swap(tmp);
+		return *this;
+	}
+
+	void swap(Column& other)
+		/// Swaps the column with another one.
+	{
+		using std::swap;
+		swap(_metaColumn, other._metaColumn);
+		swap(_pData, other._pData);
+	}
+
+	Container& data()
+		/// Returns reference to contained data.
+	{
+		return *_pData;
+	}
+
+	const T& value(std::size_t row) const
+		/// Returns the field value in specified row.
+		/// This is the std::list specialization and std::list
+		/// is not the optimal solution for cases where random 
+		/// access is needed.
+		/// However, to allow for compatibility with other
+		/// containers, this functionality is provided here.
+		/// To alleviate the problem, an effort is made
+		/// to start iteration from beginning or end,
+		/// depending on the position requested.
+	{
+		if (row <= (std::size_t) (_pData->size() / 2))
+		{
+			Iterator it = _pData->begin();
+			Iterator end = _pData->end();
+			for (int i = 0; it != end; ++it, ++i)
+				if (i == row) return *it;
+		}
+		else
+		{
+			row = _pData->size() - row;
+			RIterator it = _pData->rbegin();
+			RIterator end = _pData->rend();
+			for (int i = 1; it != end; ++it, ++i)
+				if (i == row) return *it;
+		}
+
+		throw RangeException("Invalid row number."); 
+	}
+
+	const T& operator [] (std::size_t row) const
+		/// Returns the field value in specified row.
+	{
+		return value(row);
+	}
+
+	Size rowCount() const
+		/// Returns number of rows.
+	{
+		return _pData->size();
+	}
+
+	void reset()
+		/// Clears the storage.
+	{
+		_pData->clear();
+	}
+
+	const std::string& name() const
+		/// Returns column name.
+	{
+		return _metaColumn.name();
+	}
+
+	std::size_t length() const
+		/// Returns column maximum length.
+	{
+		return _metaColumn.length();
+	}
+
+	std::size_t precision() const
+		/// Returns column precision.
+		/// Valid for floating point fields only (zero for other data types).
+	{
+		return _metaColumn.precision();
+	}
+
+	std::size_t position() const
+		/// Returns column position.
+	{
+		return _metaColumn.position();
+	}
+
+	MetaColumn::ColumnDataType type() const
+		/// Returns column type.
+	{
+		return _metaColumn.type();
+	}
+
+	Iterator begin() const
+		/// Returns iterator pointing to the beginning of data storage vector.
+	{
+		return _pData->begin();
+	}
+
+	Iterator end() const
+		/// Returns iterator pointing to the end of data storage vector.
+	{
+		return _pData->end();
+	}
+
+private:
+	Column();
+
+	MetaColumn   _metaColumn;
+	ContainerPtr _pData;
+};
+
+
+template <typename C>
+inline void swap(Column<C>& c1, Column<C>& c2)
+{
+	c1.swap(c2);
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Column_INCLUDED
+
diff --git a/Poco/Data/Connector.h b/Poco/Data/Connector.h
new file mode 100644
index 0000000..ee922f4
--- /dev/null
+++ b/Poco/Data/Connector.h
@@ -0,0 +1,56 @@
+//
+// Connector.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Connector
+//
+// Definition of the Connector class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Connector_INCLUDED
+#define Data_Connector_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API Connector
+	/// A Connector creates SessionImpl objects.
+	///
+	/// Every connector library (like the SQLite or the ODBC connector)
+	/// provides a subclass of this class, an instance of which is
+	/// registered with the SessionFactory.
+{
+public:
+	Connector();
+		/// Creates the Connector.
+
+	virtual ~Connector();
+		/// Destroys the Connector.
+
+	virtual const std::string& name() const = 0;
+		/// Returns the name associated with this connector.
+
+	virtual Poco::AutoPtr<SessionImpl> createSession(const std::string& connectionString,
+		std::size_t timeout = SessionImpl::LOGIN_TIMEOUT_DEFAULT) = 0;
+		/// Create a SessionImpl object and initialize it with the given connectionString.
+};
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Connector_INCLUDED
diff --git a/Poco/Data/Constants.h b/Poco/Data/Constants.h
new file mode 100644
index 0000000..574c09b
--- /dev/null
+++ b/Poco/Data/Constants.h
@@ -0,0 +1,36 @@
+//
+// Data.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Constants
+//
+// Constant definitions for the Poco Data library.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Constants_INCLUDED
+#define Data_Constants_INCLUDED
+
+
+#undef max
+#include <limits>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+static const std::size_t POCO_DATA_INVALID_ROW = std::numeric_limits<std::size_t>::max();
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Constants_INCLUDED
diff --git a/Poco/Data/Data.h b/Poco/Data/Data.h
new file mode 100644
index 0000000..8a9e532
--- /dev/null
+++ b/Poco/Data/Data.h
@@ -0,0 +1,62 @@
+//
+// Data.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Data
+//
+// Basic definitions for the Poco Data library.
+// This file must be the first file included by every other Data
+// header file.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Data_INCLUDED
+#define Data_Data_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Data_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Data_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(Data_EXPORTS)
+		#define Data_API __declspec(dllexport)
+	#else
+		#define Data_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Data_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Data_API __attribute__ ((visibility ("default")))
+	#else
+		#define Data_API
+	#endif
+#endif
+
+
+//
+// Automatically link Data library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Data_EXPORTS)
+		#pragma comment(lib, "PocoData" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // Data_Data_INCLUDED
diff --git a/Poco/Data/DataException.h b/Poco/Data/DataException.h
new file mode 100644
index 0000000..cc976e2
--- /dev/null
+++ b/Poco/Data/DataException.h
@@ -0,0 +1,50 @@
+//
+// DataException.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  DataException
+//
+// Definition of the DataException class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_DataException_INCLUDED
+#define Data_DataException_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+POCO_DECLARE_EXCEPTION(Data_API, DataException, Poco::IOException)
+POCO_DECLARE_EXCEPTION(Data_API, RowDataMissingException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, UnknownDataBaseException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, UnknownTypeException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, ExecutionException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, BindingException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, ExtractException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, LimitException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, NotSupportedException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, SessionUnavailableException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExhaustedException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, SessionPoolExistsException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, NoDataException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, LengthExceededException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, ConnectionFailedException, DataException)
+POCO_DECLARE_EXCEPTION(Data_API, NotConnectedException, DataException)
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_DataException_INCLUDED
diff --git a/Poco/Data/Date.h b/Poco/Data/Date.h
new file mode 100644
index 0000000..4ac234b
--- /dev/null
+++ b/Poco/Data/Date.h
@@ -0,0 +1,225 @@
+//
+// Date.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Date
+//
+// Definition of the Date class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Date_INCLUDED
+#define Data_Date_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Dynamic/VarHolder.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+
+class DateTime;
+
+namespace Dynamic {
+
+class Var;
+
+}
+
+namespace Data {
+
+
+class Time;
+
+
+class Data_API Date
+	/// Date class wraps a DateTime and exposes date related interface.
+	/// The purpose of this class is binding/extraction support for date fields.
+{
+public:
+	Date();
+		/// Creates the Date
+
+	Date(int year, int month, int day);
+		/// Creates the Date
+
+	Date(const DateTime& dt);
+		/// Creates the Date from DateTime
+
+	~Date();
+		/// Destroys the Date.
+
+	int year() const;
+		/// Returns the year.
+
+	int month() const;
+		/// Returns the month.
+
+	int day() const;
+		/// Returns the day.
+
+	void assign(int year, int month, int day);
+		/// Assigns date.
+
+	Date& operator = (const Date& d);
+		/// Assignment operator for Date.
+
+	Date& operator = (const DateTime& dt);
+		/// Assignment operator for DateTime.
+
+	Date& operator = (const Poco::Dynamic::Var& var);
+		/// Assignment operator for Var.
+
+	bool operator == (const Date& date) const;
+		/// Equality operator.
+
+	bool operator != (const Date& date) const;
+		/// Inequality operator.
+
+	bool operator < (const Date& date) const;
+		/// Less then operator.
+
+	bool operator > (const Date& date) const;
+		/// Greater then operator.
+
+private:
+	int _year;
+	int _month;
+	int _day;
+};
+
+
+//
+// inlines
+//
+inline int Date::year() const
+{
+	return _year;
+}
+
+
+inline int Date::month() const
+{
+	return _month;
+}
+
+
+inline int Date::day() const
+{
+	return _day;
+}
+
+
+inline Date& Date::operator = (const Date& d)
+{
+	assign(d.year(), d.month(), d.day());
+	return *this;
+}
+
+
+inline Date& Date::operator = (const DateTime& dt)
+{
+	assign(dt.year(), dt.month(), dt.day());
+	return *this;
+}
+
+
+inline bool Date::operator == (const Date& date) const
+{
+	return _year == date.year() &&
+		_month == date.month() &&
+		_day == date.day();
+}
+
+
+inline bool Date::operator != (const Date& date) const
+{
+	return !(*this == date);
+}
+
+
+inline bool Date::operator > (const Date& date) const
+{
+	return !(*this == date) && !(*this < date);
+}
+
+
+} } // namespace Poco::Data
+
+
+//
+// VarHolderImpl<Date>
+//
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <>
+class VarHolderImpl<Poco::Data::Date>: public VarHolder
+{
+public:
+	VarHolderImpl(const Poco::Data::Date& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Poco::Data::Date);
+	}
+
+	void convert(Poco::Timestamp& val) const
+	{
+		DateTime dt;
+		dt.assign(_val.year(), _val.month(), _val.day());
+		val = dt.timestamp();
+	}
+
+	void convert(Poco::DateTime& val) const
+	{
+		val.assign(_val.year(), _val.month(), _val.day());
+	}
+
+	void convert(Poco::LocalDateTime& val) const
+	{
+		val.assign(_val.year(), _val.month(), _val.day());
+	}
+
+	void convert(std::string& val) const
+	{
+		DateTime dt(_val.year(), _val.month(), _val.day());
+		val = DateTimeFormatter::format(dt, "%Y/%m/%d");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Poco::Data::Date& value() const
+	{
+		return _val;
+	}
+
+private:
+	VarHolderImpl();
+	Poco::Data::Date _val;
+};
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // Data_Date_INCLUDED
diff --git a/Poco/Data/DynamicDateTime.h b/Poco/Data/DynamicDateTime.h
new file mode 100644
index 0000000..0ed8730
--- /dev/null
+++ b/Poco/Data/DynamicDateTime.h
@@ -0,0 +1,47 @@
+//
+// DynamicDateTime.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  DynamicDateTime
+//
+// Definition of the Date and Time cast operators for Poco::Dynamic::Var.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_DynamicDateTime_INCLUDED
+#define Data_DynamicDateTime_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.h"
+#include "Poco/Dynamic/Var.h"
+
+
+namespace Poco {
+namespace Data {
+
+class Date;
+class Time;
+
+} } // namespace Poco::Data
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <> Data_API Var::operator Poco::Data::Date () const;
+template <> Data_API Var::operator Poco::Data::Time () const;
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // Data_DynamicDateTime_INCLUDED
diff --git a/Poco/Data/DynamicLOB.h b/Poco/Data/DynamicLOB.h
new file mode 100644
index 0000000..1ed817d
--- /dev/null
+++ b/Poco/Data/DynamicLOB.h
@@ -0,0 +1,45 @@
+//
+// DynamicLOB.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  DynamicLOB
+//
+// Definition of the Poco::Dynamic::Var LOB cast operators.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_DynamicLOB_INCLUDED
+#define Data_DynamicLOB_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/Dynamic/Var.h"
+
+
+namespace Poco {
+namespace Data {
+
+template <typename T> class LOB;
+typedef LOB<unsigned char> BLOB;
+typedef LOB<char> CLOB;
+
+} } // namespace Poco::Data
+
+
+namespace Poco {
+namespace Dynamic {
+
+template <> Data_API Var::operator Poco::Data::CLOB () const;
+template <> Data_API Var::operator Poco::Data::BLOB () const;
+
+} } // namespace Poco::Dynamic
+
+
+#endif // Data_DynamicLOB_INCLUDED
diff --git a/Poco/Data/Extraction.h b/Poco/Data/Extraction.h
new file mode 100644
index 0000000..7b98700
--- /dev/null
+++ b/Poco/Data/Extraction.h
@@ -0,0 +1,869 @@
+//
+// Extraction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Extraction
+//
+// Definition of the Extraction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Extraction_INCLUDED
+#define Data_Extraction_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractExtraction.h"
+#include "Poco/Data/Preparation.h"
+#include "Poco/Data/TypeHandler.h"
+#include "Poco/Data/Column.h"
+#include "Poco/Data/Position.h"
+#include "Poco/Data/DataException.h"
+#include <set>
+#include <vector>
+#include <list>
+#include <deque>
+#include <map>
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <class T>
+class Extraction: public AbstractExtraction
+	/// Concrete Data Type specific extraction of values from a query result set.
+{
+public:
+	typedef T                   ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(T& result, const Position& pos = Position(0)):
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(), 
+		_extracted(false),
+		_null(false)
+		/// Creates an Extraction object at specified position.
+		/// Uses an empty object T as default value.
+	{
+	}
+
+	Extraction(T& result, const T& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def), 
+		_extracted(false),
+		_null(false)
+		/// Creates an Extraction object at specified position.
+		/// Uses the provided def object as default value.
+	{
+	}
+
+	~Extraction()
+		/// Destroys the Extraction object.
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _extracted ? 1u : 0;
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return 1u;
+	}
+
+	bool isNull(std::size_t row = 0) const
+	{
+		return _null;
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		if (_extracted) throw ExtractException("value already extracted");
+		_extracted = true;
+		AbstractExtractor::Ptr pExt = getExtractor();
+		TypeHandler<T>::extract(pos, _rResult, _default, pExt);
+		_null = isValueNull<T>(_rResult, pExt->isNull(pos));
+		
+		return 1u;
+	}
+
+	void reset()
+	{
+		_extracted = false;
+	}
+
+	bool canExtract() const
+	{
+		return !_extracted;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<T>(pPrep, pos, _rResult);
+	}
+
+private:
+	T&   _rResult;
+	T    _default;
+	bool _extracted;
+	bool _null;
+};
+
+
+template <class T>
+class Extraction<std::vector<T> >: public AbstractExtraction
+	/// Vector Data Type specialization for extraction of values from a query result set.
+{
+public:
+	
+	typedef std::vector<T>      ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::vector<T>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::vector<T>& result, const T& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	virtual ~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_rResult.size());
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		try
+		{
+			return _nulls.at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		AbstractExtractor::Ptr pExt = getExtractor();
+		_rResult.push_back(_default);
+		TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
+		_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<T>(pPrep, pos, _default);
+	}
+
+	void reset()
+	{
+		_nulls.clear();
+	}
+
+protected:
+
+	const std::vector<T>& result() const
+	{
+		return _rResult;
+	}
+
+private:
+	std::vector<T>&  _rResult;
+	T                _default;
+	std::deque<bool> _nulls;
+};
+
+
+template <>
+class Extraction<std::vector<bool> >: public AbstractExtraction
+	/// Vector bool specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::vector<bool>   ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::vector<bool>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::vector<bool>& result, const bool& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	virtual ~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<bool>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_rResult.size());
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		try
+		{
+			return _nulls.at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		AbstractExtractor::Ptr pExt = getExtractor();
+
+		bool tmp = _default;
+		TypeHandler<bool>::extract(pos, tmp, _default, pExt);
+		_rResult.push_back(tmp);
+		_nulls.push_back(pExt->isNull(pos));
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<bool>(pPrep, pos, _default);
+	}
+
+	void reset()
+	{
+		_nulls.clear();
+	}
+
+protected:
+
+	const std::vector<bool>& result() const
+	{
+		return _rResult;
+	}
+
+private:
+	std::vector<bool>& _rResult;
+	bool               _default;
+	std::deque<bool>   _nulls;
+};
+
+
+template <class T>
+class Extraction<std::list<T> >: public AbstractExtraction
+	/// List Data Type specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::list<T>        ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::list<T>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::list<T>& result, const T& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	virtual ~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _rResult.size();
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		try
+		{
+			return _nulls.at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		AbstractExtractor::Ptr pExt = getExtractor();
+		_rResult.push_back(_default);
+		TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
+		_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<T>(pPrep, pos, _default);
+	}
+
+	void reset()
+	{
+		_nulls.clear();
+	}
+
+protected:
+
+	const std::list<T>& result() const
+	{
+		return _rResult;
+	}
+
+private:
+	std::list<T>&    _rResult;
+	T                _default;
+	std::deque<bool> _nulls;
+};
+
+
+template <class T>
+class Extraction<std::deque<T> >: public AbstractExtraction
+	/// Deque Data Type specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::deque<T>       ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::deque<T>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::deque<T>& result, const T& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	virtual ~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return _rResult.size();
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		try
+		{
+			return _nulls.at(row);
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		AbstractExtractor::Ptr pExt = getExtractor();
+		_rResult.push_back(_default);
+		TypeHandler<T>::extract(pos, _rResult.back(), _default, pExt);
+		_nulls.push_back(isValueNull(_rResult.back(), pExt->isNull(pos)));
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<T>(pPrep, pos, _default);
+	}
+
+	void reset()
+	{
+		_nulls.clear();
+	}
+
+protected:
+
+	const std::deque<T>& result() const
+	{
+		return _rResult;
+	}
+
+private:
+	std::deque<T>&   _rResult;
+	T                _default;
+	std::deque<bool> _nulls;
+};
+
+
+template <class C>
+class InternalExtraction: public Extraction<C>
+	/// Container Data Type specialization extension for extraction of values from a query result set.
+	///
+	/// This class is intended for PocoData internal use - it is used by StatementImpl 
+	/// to automaticaly create internal Extraction in cases when statement returns data and no external storage
+	/// was supplied. It is later used by RecordSet to retrieve the fetched data after statement execution.
+	/// It takes ownership of the Column pointer supplied as constructor argument. Column object, in turn
+	/// owns the data container pointer.
+	///
+	/// InternalExtraction objects can not be copied or assigned.
+{
+public:
+	typedef typename C::value_type ValType;
+	typedef SharedPtr<ValType>     ValPtr;
+	typedef Extraction<ValType>    Type;
+	typedef SharedPtr<Type>        Ptr;
+
+
+	InternalExtraction(C& result, Column<C>* pColumn, const Position& pos = Position(0)): 
+		Extraction<C>(result, ValType(), pos), 
+		_pColumn(pColumn)
+		/// Creates InternalExtraction.
+	{
+	}
+
+	~InternalExtraction()
+		/// Destroys InternalExtraction.
+	{
+		delete _pColumn;
+	}
+
+	void reset()
+	{
+		Extraction<C>::reset();
+		_pColumn->reset();
+	}	
+
+	const ValType& value(int index) const
+	{
+		try
+		{ 
+			return Extraction<C>::result().at(index); 
+		}
+		catch (std::out_of_range& ex)
+		{ 
+			throw RangeException(ex.what()); 
+		}
+	}
+
+	bool isNull(std::size_t row) const
+	{
+		return Extraction<C>::isNull(row);
+	}
+
+	const Column<C>& column() const
+	{
+		return *_pColumn;
+	}
+
+private:
+	InternalExtraction();
+	InternalExtraction(const InternalExtraction&);
+	InternalExtraction& operator = (const InternalExtraction&);
+
+	Column<C>* _pColumn;
+};
+
+
+template <class T>
+class Extraction<std::set<T> >: public AbstractExtraction
+	/// Set Data Type specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::set<T>                ValType;
+	typedef SharedPtr<ValType>         ValPtr;
+	typedef Extraction<ValType>        Type;
+	typedef SharedPtr<Type>            Ptr;
+	typedef typename ValType::iterator Iterator;
+
+	Extraction(std::set<T>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::set<T>& result, const T& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_rResult.size());
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		T tmp;
+		TypeHandler<T>::extract(pos, tmp, _default, getExtractor());
+		_rResult.insert(tmp);
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<T>(pPrep, pos, _default);
+	}
+
+private:
+	std::set<T>& _rResult;
+	T            _default;
+};
+
+
+template <class T>
+class Extraction<std::multiset<T> >: public AbstractExtraction
+	/// Multiset Data Type specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::multiset<T>    ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::multiset<T>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::multiset<T>& result, const T& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<T>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_rResult.size());
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		T tmp;
+		TypeHandler<T>::extract(pos, tmp, _default, getExtractor());
+		_rResult.insert(tmp);
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<T>(pPrep, pos, _default);
+	}
+
+private:
+	std::multiset<T>& _rResult;
+	T                 _default;
+};
+
+
+template <class K, class V>
+class Extraction<std::map<K, V> >: public AbstractExtraction
+	/// Map Data Type specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::map<K, V>      ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::map<K, V>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::map<K, V>& result, const V& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<V>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_rResult.size());
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		V tmp;
+		TypeHandler<V>::extract(pos, tmp, _default, getExtractor());
+		_rResult.insert(std::make_pair(tmp(), tmp));
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<V>(pPrep, pos, _default);
+	}
+
+private:
+	std::map<K, V>& _rResult;
+	V               _default;
+};
+
+
+template <class K, class V>
+class Extraction<std::multimap<K, V> >: public AbstractExtraction
+	/// Multimap Data Type specialization for extraction of values from a query result set.
+{
+public:
+	typedef std::multimap<K, V> ValType;
+	typedef SharedPtr<ValType>  ValPtr;
+	typedef Extraction<ValType> Type;
+	typedef SharedPtr<Type>     Ptr;
+
+	Extraction(std::multimap<K, V>& result, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default()
+	{
+		_rResult.clear();
+	}
+
+	Extraction(std::multimap<K, V>& result, const V& def, const Position& pos = Position(0)): 
+		AbstractExtraction(Limit::LIMIT_UNLIMITED, pos.value()),
+		_rResult(result), 
+		_default(def)
+	{
+		_rResult.clear();
+	}
+
+	~Extraction()
+	{
+	}
+
+	std::size_t numOfColumnsHandled() const
+	{
+		return TypeHandler<V>::size();
+	}
+
+	std::size_t numOfRowsHandled() const
+	{
+		return static_cast<std::size_t>(_rResult.size());
+	}
+
+	std::size_t numOfRowsAllowed() const
+	{
+		return getLimit();
+	}
+
+	std::size_t extract(std::size_t pos)
+	{
+		V tmp;
+		TypeHandler<V>::extract(pos, tmp, _default, getExtractor());
+		_rResult.insert(std::make_pair(tmp(), tmp));
+		return 1u;
+	}
+
+	AbstractPreparation::Ptr createPreparation(AbstractPreparator::Ptr& pPrep, std::size_t pos)
+	{
+		return new Preparation<V>(pPrep, pos, _default);
+	}
+
+private:
+	std::multimap<K, V>& _rResult;
+	V                    _default;
+};
+
+
+namespace Keywords {
+
+
+template <typename T> 
+inline AbstractExtraction::Ptr into(T& t)
+	/// Convenience function to allow for a more compact creation of an extraction object.
+{
+	return new Extraction<T>(t);
+}
+
+
+template <typename T> 
+inline AbstractExtraction::Ptr into(T& t, const Position& pos)
+	/// Convenience function to allow for a more compact creation of an extraction object
+	/// with multiple recordset support.
+{
+	return new Extraction<T>(t, pos);
+}
+
+
+template <typename T> 
+inline AbstractExtraction::Ptr into(T& t, const Position& pos, const T& def)
+	/// Convenience function to allow for a more compact creation of an extraction object 
+	/// with multiple recordset support and the given default
+{
+	return new Extraction<T>(t, def, pos);
+}
+
+
+inline AbstractExtractionVecVec& into(AbstractExtractionVecVec& evv)
+	/// Convenience dummy function (for syntax purposes only).
+{
+	return evv;
+}
+
+
+inline AbstractExtractionVec& into(AbstractExtractionVec& ev)
+	/// Convenience dummy function (for syntax purposes only).
+{
+	return ev;
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Extraction_INCLUDED
diff --git a/Poco/Data/LOB.h b/Poco/Data/LOB.h
new file mode 100644
index 0000000..99c1e7b
--- /dev/null
+++ b/Poco/Data/LOB.h
@@ -0,0 +1,309 @@
+//
+// LOB.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  LOB
+//
+// Definition of the LOB class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_LOB_INCLUDED
+#define Data_LOB_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Dynamic/VarHolder.h"
+#include "Poco/Exception.h"
+#include <vector>
+#include <algorithm>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <typename T>
+class LOB
+	/// Representation of a Large OBject.
+	///
+	/// A LOB can hold arbitrary data.
+	/// The maximum size depends on the underlying database.
+	///
+	/// The LOBInputStream and LOBOutputStream classes provide
+	/// a convenient way to access the data in a LOB.
+{
+public:
+	typedef typename std::vector<T>::const_iterator Iterator;
+	typedef T ValueType;
+	typedef typename std::vector<T> Container;
+	typedef Poco::SharedPtr<Container> ContentPtr;
+
+	LOB(): _pContent(new std::vector<T>())
+		/// Creates an empty LOB.
+	{
+	}
+
+	LOB(const std::vector<T>& content):
+		_pContent(new std::vector<T>(content))
+		/// Creates the LOB, content is deep-copied.
+	{
+	}
+
+	LOB(const T* const pContent, std::size_t size):
+		_pContent(new std::vector<T>(pContent, pContent + size))
+		/// Creates the LOB by deep-copying pContent.
+	{
+	}
+
+	LOB(const std::basic_string<T>& content):
+		_pContent(new std::vector<T>(content.begin(), content.end()))
+		/// Creates a LOB from a string.
+	{
+	}
+
+	LOB(const LOB& other): _pContent(other._pContent)
+		/// Creates a LOB by copying another one.
+	{
+	}
+
+	~LOB()
+		/// Destroys the LOB.
+	{
+	}
+
+	LOB& operator = (const LOB& other)
+		/// Assignment operator.
+	{
+		LOB tmp(other);
+		swap(tmp);
+		return *this;
+	}
+
+	bool operator == (const LOB& other) const
+		/// Compares for equality LOB by value.
+	{
+		return *_pContent == *other._pContent;
+	}
+
+	bool operator != (const LOB& other) const
+		/// Compares for inequality LOB by value.
+	{
+		return *_pContent != *other._pContent;
+	}
+
+	void swap(LOB& other)
+		/// Swaps the LOB with another one.
+	{
+		using std::swap;
+		swap(_pContent, other._pContent);
+	}
+
+	const std::vector<T>& content() const
+		/// Returns the content.
+	{
+		return *_pContent;
+	}
+
+	const T* rawContent() const
+		/// Returns the raw content.
+		///
+		/// If the LOB is empty, returns NULL.
+	{
+		if (_pContent->empty())
+			return 0;
+		else
+			return &(*_pContent)[0];
+	}
+
+	void assignVal(std::size_t count, const T& val)
+		/// Assigns raw content to internal storage.
+	{
+		ContentPtr tmp = new Container(count, val);
+		_pContent.swap(tmp);
+	}
+
+	void assignRaw(const T* ptr, std::size_t count)
+		/// Assigns raw content to internal storage.
+	{
+		poco_assert_dbg (ptr);
+		LOB tmp(ptr, count);
+		swap(tmp);
+	}
+
+	void appendRaw(const T* pChar, std::size_t count)
+		/// Assigns raw content to internal storage.
+	{
+		poco_assert_dbg (pChar);
+		_pContent->insert(_pContent->end(), pChar, pChar+count);
+	}
+
+	void clear(bool doCompact = false)
+		/// Clears the content of the blob.
+		/// If doCompact is true, trims the excess capacity.
+	{
+		_pContent->clear();
+		if (doCompact) compact();
+	}
+
+	void compact()
+		/// Trims the internal storage excess capacity.
+	{
+		std::vector<T>(*_pContent).swap(*_pContent);
+	}
+
+	Iterator begin() const
+	{
+		return _pContent->begin();
+	}
+
+	Iterator end() const
+	{
+		return _pContent->end();
+	}
+
+	std::size_t size() const
+		/// Returns the size of the LOB in bytes.
+	{
+		return static_cast<std::size_t>(_pContent->size());
+	}
+
+private:
+	ContentPtr _pContent;
+};
+
+
+typedef LOB<unsigned char> BLOB;
+typedef LOB<char> CLOB;
+
+
+//
+// inlines
+//
+
+template <typename T>
+inline void swap(LOB<T>& b1, LOB<T>& b2)
+{
+	b1.swap(b2);
+}
+
+
+} } // namespace Poco::Data
+
+
+namespace std
+{
+	template<>
+	inline void swap<Poco::Data::BLOB>(Poco::Data::BLOB& b1, 
+		Poco::Data::BLOB& b2)
+		/// Full template specalization of std:::swap for BLOB
+	{
+		b1.swap(b2);
+	}
+
+	template<>
+	inline void swap<Poco::Data::CLOB>(Poco::Data::CLOB& c1, 
+		Poco::Data::CLOB& c2)
+		/// Full template specalization of std:::swap for CLOB
+	{
+		c1.swap(c2);
+	}
+}
+
+
+//
+// VarHolderImpl<LOB>
+//
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <>
+class VarHolderImpl<Poco::Data::BLOB>: public VarHolder
+{
+public:
+	VarHolderImpl(const Poco::Data::BLOB& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Poco::Data::BLOB);
+	}
+
+	void convert(std::string& val) const
+	{
+		val.assign(_val.begin(), _val.end());
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Poco::Data::BLOB& value() const
+	{
+		return _val;
+	}
+
+private:
+	VarHolderImpl();
+	Poco::Data::BLOB _val;
+};
+
+
+template <>
+class VarHolderImpl<Poco::Data::CLOB>: public VarHolder
+{
+public:
+	VarHolderImpl(const Poco::Data::CLOB& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Poco::Data::CLOB);
+	}
+
+	void convert(std::string& val) const
+	{
+		val.assign(_val.begin(), _val.end());
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Poco::Data::CLOB& value() const
+	{
+		return _val;
+	}
+
+private:
+	VarHolderImpl();
+	Poco::Data::CLOB _val;
+};
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // Data_LOB_INCLUDED
diff --git a/Poco/Data/LOBStream.h b/Poco/Data/LOBStream.h
new file mode 100644
index 0000000..d363457
--- /dev/null
+++ b/Poco/Data/LOBStream.h
@@ -0,0 +1,150 @@
+//
+// LOBStream.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  LOBStream
+//
+// Definition of the LOBStream class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_LOBStream_INCLUDED
+#define Data_LOBStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include "Poco/Data/LOB.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Data {
+
+
+template <typename T>
+class LOBStreamBuf: public BasicUnbufferedStreamBuf<T, std::char_traits<T> >
+	/// This is the streambuf class used for reading from and writing to a LOB.
+{
+public:	
+	LOBStreamBuf(LOB<T>& lob): _lob(lob), _it(_lob.begin())
+		/// Creates LOBStreamBuf.
+	{
+	}
+
+
+	~LOBStreamBuf()
+		/// Destroys LOBStreamBuf.
+	{
+	}
+
+protected:
+	typedef std::char_traits<T> TraitsType;
+	typedef BasicUnbufferedStreamBuf<T, TraitsType> BaseType;
+
+	typename BaseType::int_type readFromDevice()
+	{
+		if (_it != _lob.end())
+			return BaseType::charToInt(*_it++);
+		else
+			return -1;
+	}
+
+	typename BaseType::int_type writeToDevice(T c)
+	{
+		_lob.appendRaw(&c, 1);
+		return 1;
+	}
+
+private:
+	LOB<T>& _lob;
+	typename LOB<T>::Iterator _it;
+};
+
+
+template <typename T>
+class LOBIOS: public virtual std::ios
+	/// The base class for LOBInputStream and
+	/// LOBOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	LOBIOS(LOB<T>& lob, openmode mode): _buf(lob)
+		/// Creates the LOBIOS with the given LOB.
+	{
+		poco_ios_init(&_buf);
+	}
+
+	~LOBIOS()
+		/// Destroys the LOBIOS.
+	{
+	}
+
+	LOBStreamBuf<T>* rdbuf()
+		/// Returns a pointer to the internal LOBStreamBuf.
+	{
+		return &_buf;
+	}
+
+protected:
+	LOBStreamBuf<T> _buf;
+};
+
+
+template <typename T>
+class LOBOutputStream: public LOBIOS<T>, public std::basic_ostream<T, std::char_traits<T> >
+	/// An output stream for writing to a LOB.
+{
+public:
+	LOBOutputStream(LOB<T>& lob):
+		LOBIOS<T>(lob, std::ios::out),
+		std::ostream(LOBIOS<T>::rdbuf())
+		/// Creates the LOBOutputStream with the given LOB.
+	{
+	}
+
+	~LOBOutputStream()
+		/// Destroys the LOBOutputStream.
+	{
+	}
+};
+
+
+template <typename T>
+class LOBInputStream: public LOBIOS<T>, public std::basic_istream<T, std::char_traits<T> >
+	/// An input stream for reading from a LOB.
+{
+public:
+	LOBInputStream(LOB<T>& lob):
+		LOBIOS<T>(lob, std::ios::in),
+		std::istream(LOBIOS<T>::rdbuf())
+		/// Creates the LOBInputStream with the given LOB.
+	{
+	}
+
+	~LOBInputStream()
+		/// Destroys the LOBInputStream.
+	{
+	}
+};
+
+
+typedef LOBOutputStream<unsigned char> BLOBOutputStream;
+typedef LOBOutputStream<char> CLOBOutputStream;
+
+typedef LOBInputStream<unsigned char> BLOBInputStream;
+typedef LOBInputStream<char> CLOBInputStream;
+
+} } // namespace Poco::Data
+
+
+#endif // Data_LOBStream_INCLUDED
diff --git a/Poco/Data/Limit.h b/Poco/Data/Limit.h
new file mode 100644
index 0000000..f45ec3e
--- /dev/null
+++ b/Poco/Data/Limit.h
@@ -0,0 +1,113 @@
+//
+// Limit.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Limit
+//
+// Definition of the Limit class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Limit_INCLUDED
+#define Data_Limit_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API Limit
+	/// Limit stores information how many rows a query should return.
+{
+public:
+	typedef Poco::UInt32 SizeT;
+
+	enum Type
+	{
+		LIMIT_UNLIMITED = ~((SizeT) 0)
+	};
+	
+	Limit(SizeT value, bool hardLimit = false, bool isLowerLimit = false);
+		/// Creates the Limit. 
+		///
+		/// Value contains the upper row hint, if hardLimit is set to true, the limit acts as a hard
+		/// border, ie. every query must return exactly value rows, returning more than value objects will throw an exception!
+		/// LowerLimits always act as hard-limits!
+		///
+		/// A value of LIMIT_UNLIMITED disables the limit.
+
+	~Limit();
+		/// Destroys the Limit.
+
+	SizeT value() const;
+		/// Returns the value of the limit
+
+	bool isHardLimit() const;
+		/// Returns true if the limit is a hard limit.
+
+	bool isLowerLimit() const;
+		/// Returns true if the limit is a lower limit, otherwise it is an upperLimit
+
+	bool operator == (const Limit& other) const;
+		/// Equality operator.
+
+	bool operator != (const Limit& other) const;
+		/// Inequality operator.
+
+private:
+	SizeT _value;
+	bool  _hardLimit;
+	bool  _isLowerLimit;
+};
+
+
+//
+// inlines
+//
+inline Poco::UInt32 Limit::value() const
+{
+	return _value;
+}
+
+
+inline bool Limit::isHardLimit() const
+{
+	return _hardLimit;
+}
+
+
+inline bool Limit::isLowerLimit() const
+{
+	return _isLowerLimit;
+}
+
+
+inline bool Limit::operator == (const Limit& other) const
+{
+	return other._value == _value &&
+		other._hardLimit == _hardLimit &&
+		other._isLowerLimit == _isLowerLimit;
+}
+
+
+inline bool Limit::operator != (const Limit& other) const
+{
+	return other._value != _value ||
+		other._hardLimit != _hardLimit ||
+		other._isLowerLimit != _isLowerLimit;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Limit_INCLUDED
diff --git a/Poco/Data/MetaColumn.h b/Poco/Data/MetaColumn.h
new file mode 100644
index 0000000..65410a0
--- /dev/null
+++ b/Poco/Data/MetaColumn.h
@@ -0,0 +1,188 @@
+//
+// MetaColumn.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  MetaColumn
+//
+// Definition of the MetaColumn class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_MetaColumn_INCLUDED
+#define Data_MetaColumn_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API MetaColumn
+	/// MetaColumn class contains column metadata information.
+{
+public:
+	enum ColumnDataType
+	{
+		FDT_BOOL,
+		FDT_INT8,
+		FDT_UINT8,
+		FDT_INT16,
+		FDT_UINT16,
+		FDT_INT32,
+		FDT_UINT32,
+		FDT_INT64,
+		FDT_UINT64,
+		FDT_FLOAT,
+		FDT_DOUBLE,
+		FDT_STRING,
+		FDT_WSTRING,
+		FDT_BLOB,
+		FDT_CLOB,
+		FDT_DATE,
+		FDT_TIME,
+		FDT_TIMESTAMP,
+		FDT_UNKNOWN
+	};
+
+	MetaColumn();
+		/// Creates the MetaColumn.
+
+	explicit MetaColumn(std::size_t position,
+		const std::string& name = "",
+		ColumnDataType type = FDT_UNKNOWN,
+		std::size_t length = 0,
+		std::size_t precision = 0,
+		bool nullable = false);
+		/// Creates the MetaColumn.
+
+	virtual ~MetaColumn();
+		/// Destroys the MetaColumn.
+
+	const std::string& name() const;
+		/// Returns column name.
+
+	std::size_t length() const;
+		/// Returns column maximum length.
+
+	std::size_t precision() const;
+		/// Returns column precision.
+		/// Valid for floating point fields only
+		/// (zero for other data types).
+
+	std::size_t position() const;
+		/// Returns column position.
+
+	ColumnDataType type() const;
+		/// Returns column type.
+
+	bool isNullable() const;
+		/// Returns true if column allows null values, false otherwise.
+
+protected:
+	void setName(const std::string& name);
+		/// Sets the column name.
+
+	void setLength(std::size_t length);
+		/// Sets the column length.
+
+	void setPrecision(std::size_t precision);
+		/// Sets the column precision.
+
+	void setType(ColumnDataType type);
+		/// Sets the column data type.
+
+	void setNullable(bool nullable);
+		/// Sets the column nullability.
+
+private:
+	std::string     _name;
+	std::size_t     _length;
+	std::size_t     _precision;
+	std::size_t     _position;
+	ColumnDataType  _type;
+	bool            _nullable;
+};
+
+
+///
+/// inlines
+///
+inline const std::string& MetaColumn::name() const
+{
+	return _name;
+}
+
+
+inline std::size_t MetaColumn::length() const
+{
+	return _length;
+}
+
+
+inline std::size_t MetaColumn::precision() const
+{
+	return _precision;
+}
+
+
+inline std::size_t MetaColumn::position() const
+{
+	return _position;
+}
+
+
+inline MetaColumn::ColumnDataType MetaColumn::type() const
+{
+	return _type;
+}
+
+
+inline bool MetaColumn::isNullable() const
+{
+	return _nullable;
+}
+
+
+inline void MetaColumn::setName(const std::string& name)
+{
+	_name = name;
+}
+
+
+inline void MetaColumn::setLength(std::size_t length)
+{
+	_length = length;
+}
+
+
+inline void MetaColumn::setPrecision(std::size_t precision)
+{
+	_precision = precision;
+}
+
+
+inline void MetaColumn::setType(ColumnDataType type)
+{
+	_type = type;
+}
+
+
+inline void MetaColumn::setNullable(bool nullable)
+{
+	_nullable = nullable;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_MetaColumn_INCLUDED
diff --git a/Poco/Data/ODBC/Binder.h b/Poco/Data/ODBC/Binder.h
new file mode 100644
index 0000000..fd3241f
--- /dev/null
+++ b/Poco/Data/ODBC/Binder.h
@@ -0,0 +1,1516 @@
+//
+// Binder.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Binder
+//
+// Definition of the Binder class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Binder_INCLUDED
+#define Data_ODBC_Binder_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/AbstractBinder.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/Data/ODBC/Handle.h"
+#include "Poco/Data/ODBC/Parameter.h"
+#include "Poco/Data/ODBC/ODBCMetaColumn.h"
+#include "Poco/Data/ODBC/Utility.h"
+#include "Poco/Data/ODBC/TypeInfo.h"
+#include "Poco/Exception.h"
+#include <vector>
+#include <deque>
+#include <list>
+#include <map>
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+
+
+class DateTime;
+
+
+namespace Data {
+
+
+class Date;
+class Time;
+
+
+namespace ODBC {
+
+
+class ODBC_API Binder: public Poco::Data::AbstractBinder
+	/// Binds placeholders in the sql query to the provided values. Performs data types mapping.
+{
+public:
+	typedef AbstractBinder::Direction Direction;
+	typedef std::map<SQLPOINTER, SQLLEN> ParamMap;
+
+	static const size_t DEFAULT_PARAM_SIZE = 1024;
+
+	enum ParameterBinding
+	{
+		PB_IMMEDIATE,
+		PB_AT_EXEC
+	};
+
+	Binder(const StatementHandle& rStmt,
+		std::size_t maxFieldSize,
+		ParameterBinding dataBinding = PB_IMMEDIATE,
+		TypeInfo* pDataTypes = 0);
+		/// Creates the Binder.
+
+	~Binder();
+		/// Destroys the Binder.
+
+	void bind(std::size_t pos, const Poco::Int8& val, Direction dir);
+		/// Binds an Int8.
+
+	void bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir);
+		/// Binds an Int8 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir);
+		/// Binds an Int8 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir);
+		/// Binds an Int8 list.
+
+	void bind(std::size_t pos, const Poco::UInt8& val, Direction dir);
+		/// Binds an UInt8.
+
+	void bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir);
+		/// Binds an UInt8 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir);
+		/// Binds an UInt8 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir);
+		/// Binds an UInt8 list.
+
+	void bind(std::size_t pos, const Poco::Int16& val, Direction dir);
+		/// Binds an Int16.
+	
+	void bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir);
+		/// Binds an Int16 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir);
+		/// Binds an Int16 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir);
+		/// Binds an Int16 list.
+
+	void bind(std::size_t pos, const Poco::UInt16& val, Direction dir);
+		/// Binds an UInt16.
+
+	void bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir);
+		/// Binds an UInt16 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir);
+		/// Binds an UInt16 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir);
+		/// Binds an UInt16 list.
+
+	void bind(std::size_t pos, const Poco::Int32& val, Direction dir);
+		/// Binds an Int32.
+
+	void bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir);
+		/// Binds an Int32 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir);
+		/// Binds an Int32 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir);
+		/// Binds an Int32 list.
+
+	void bind(std::size_t pos, const Poco::UInt32& val, Direction dir);
+		/// Binds an UInt32.
+
+	void bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir);
+		/// Binds an UInt32 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir);
+		/// Binds an UInt32 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir);
+		/// Binds an UInt32 list.
+
+	void bind(std::size_t pos, const Poco::Int64& val, Direction dir);
+		/// Binds an Int64.
+
+	void bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir);
+		/// Binds an Int64 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir);
+		/// Binds an Int64 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir);
+		/// Binds an Int64 list.
+
+	void bind(std::size_t pos, const Poco::UInt64& val, Direction dir);
+		/// Binds an UInt64.
+
+	void bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir);
+		/// Binds an UInt64 vector.
+
+	void bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir);
+		/// Binds an UInt64 deque.
+
+	void bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir);
+		/// Binds an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	void bind(std::size_t pos, const long& val, Direction dir);
+		/// Binds a long.
+
+	void bind(std::size_t pos, const unsigned long& val, Direction dir);
+		/// Binds an unsigned long.
+
+	void bind(std::size_t pos, const std::vector<long>& val, Direction dir);
+		/// Binds a long vector.
+
+	void bind(std::size_t pos, const std::deque<long>& val, Direction dir);
+		/// Binds a long deque.
+
+	void bind(std::size_t pos, const std::list<long>& val, Direction dir);
+		/// Binds a long list.
+#endif
+
+	void bind(std::size_t pos, const bool& val, Direction dir);
+		/// Binds a boolean.
+
+	void bind(std::size_t pos, const std::vector<bool>& val, Direction dir);
+		/// Binds a boolean vector.
+
+	void bind(std::size_t pos, const std::deque<bool>& val, Direction dir);
+		/// Binds a boolean deque.
+
+	void bind(std::size_t pos, const std::list<bool>& val, Direction dir);
+		/// Binds a boolean list.
+
+	void bind(std::size_t pos, const float& val, Direction dir);
+		/// Binds a float.
+
+	void bind(std::size_t pos, const std::vector<float>& val, Direction dir);
+		/// Binds a float vector.
+
+	void bind(std::size_t pos, const std::deque<float>& val, Direction dir);
+		/// Binds a float deque.
+
+	void bind(std::size_t pos, const std::list<float>& val, Direction dir);
+		/// Binds a float list.
+
+	void bind(std::size_t pos, const double& val, Direction dir);
+		/// Binds a double.
+
+	void bind(std::size_t pos, const std::vector<double>& val, Direction dir);
+		/// Binds a double vector.
+
+	void bind(std::size_t pos, const std::deque<double>& val, Direction dir);
+		/// Binds a double deque.
+
+	void bind(std::size_t pos, const std::list<double>& val, Direction dir);
+		/// Binds a double list.
+
+	void bind(std::size_t pos, const char& val, Direction dir);
+		/// Binds a single character.
+
+	void bind(std::size_t pos, const std::vector<char>& val, Direction dir);
+		/// Binds a character vector.
+
+	void bind(std::size_t pos, const std::deque<char>& val, Direction dir);
+		/// Binds a character deque.
+
+	void bind(std::size_t pos, const std::list<char>& val, Direction dir);
+		/// Binds a character list.
+
+	void bind(std::size_t pos, const std::string& val, Direction dir);
+		/// Binds a string.
+
+	void bind(std::size_t pos, const std::vector<std::string>& val, Direction dir);
+		/// Binds a string vector.
+
+	void bind(std::size_t pos, const std::deque<std::string>& val, Direction dir);
+		/// Binds a string deque.
+
+	void bind(std::size_t pos, const std::list<std::string>& val, Direction dir);
+		/// Binds a string list.
+
+	void bind(std::size_t pos, const UTF16String& val, Direction dir);
+		/// Binds a string.
+
+	void bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir);
+		/// Binds a string vector.
+
+	void bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir);
+		/// Binds a string deque.
+
+	void bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir);
+		/// Binds a string list.
+
+	void bind(std::size_t pos, const BLOB& val, Direction dir);
+		/// Binds a BLOB. In-bound only.
+
+	void bind(std::size_t pos, const CLOB& val, Direction dir);
+		/// Binds a CLOB. In-bound only.
+
+	void bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir);
+		/// Binds a BLOB vector.
+
+	void bind(std::size_t pos, const std::deque<BLOB>& val, Direction dir);
+		/// Binds a BLOB deque.
+
+	void bind(std::size_t pos, const std::list<BLOB>& val, Direction dir);
+		/// Binds a BLOB list.
+
+	void bind(std::size_t pos, const std::vector<CLOB>& val, Direction dir);
+		/// Binds a CLOB vector.
+
+	void bind(std::size_t pos, const std::deque<CLOB>& val, Direction dir);
+		/// Binds a CLOB deque.
+
+	void bind(std::size_t pos, const std::list<CLOB>& val, Direction dir);
+		/// Binds a CLOB list.
+
+	void bind(std::size_t pos, const Date& val, Direction dir);
+		/// Binds a Date.
+
+	void bind(std::size_t pos, const std::vector<Date>& val, Direction dir);
+		/// Binds a Date vector.
+
+	void bind(std::size_t pos, const std::deque<Date>& val, Direction dir);
+		/// Binds a Date deque.
+
+	void bind(std::size_t pos, const std::list<Date>& val, Direction dir);
+		/// Binds a Date list.
+
+	void bind(std::size_t pos, const Time& val, Direction dir);
+		/// Binds a Time.
+
+	void bind(std::size_t pos, const std::vector<Time>& val, Direction dir);
+		/// Binds a Time vector.
+
+	void bind(std::size_t pos, const std::deque<Time>& val, Direction dir);
+		/// Binds a Time deque.
+
+	void bind(std::size_t pos, const std::list<Time>& val, Direction dir);
+		/// Binds a Time list.
+
+	void bind(std::size_t pos, const DateTime& val, Direction dir);
+		/// Binds a DateTime.
+
+	void bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir);
+		/// Binds a DateTime vector.
+
+	void bind(std::size_t pos, const std::deque<DateTime>& val, Direction dir);
+		/// Binds a DateTime deque.
+
+	void bind(std::size_t pos, const std::list<DateTime>& val, Direction dir);
+		/// Binds a DateTime list.
+
+	void bind(std::size_t pos, const NullData& val, Direction dir);
+		/// Binds a null. In-bound only.
+
+	void bind(std::size_t pos, const std::vector<NullData>& val, Direction dir);
+		/// Binds a null vector.
+
+	void bind(std::size_t pos, const std::deque<NullData>& val, Direction dir);
+		/// Binds a null deque.
+
+	void bind(std::size_t pos, const std::list<NullData>& val, Direction dir);
+		/// Binds a null list.
+
+	void setDataBinding(ParameterBinding binding);
+		/// Set data binding type.
+
+	ParameterBinding getDataBinding() const;
+		/// Return data binding type.
+
+	std::size_t parameterSize(SQLPOINTER pAddr) const;
+		/// Returns bound data size for parameter at specified position.
+
+	void synchronize();
+		/// Transfers the results of non-POD outbound parameters from internal 
+		/// holders back into the externally supplied buffers.
+
+	void reset();
+		/// Clears the cached storage.
+
+private:
+	typedef std::vector<SQLLEN*>                             LengthPtrVec;
+	typedef std::vector<SQLLEN>                              LengthVec;
+	typedef std::vector<LengthVec*>                          LengthVecVec;
+	typedef std::vector<char*>                               CharPtrVec;
+	typedef std::vector<UTF16Char*>                          UTF16CharPtrVec;
+	typedef std::vector<bool*>                               BoolPtrVec;
+	typedef std::vector<SQL_DATE_STRUCT>                     DateVec;
+	typedef std::vector<DateVec*>                            DateVecVec;
+	typedef std::vector<SQL_TIME_STRUCT>                     TimeVec;
+	typedef std::vector<TimeVec*>                            TimeVecVec;
+	typedef std::vector<SQL_TIMESTAMP_STRUCT>                DateTimeVec;
+	typedef std::vector<DateTimeVec*>                        DateTimeVecVec;
+	typedef std::vector<Poco::Any>                           AnyVec;
+	typedef std::vector<AnyVec>                              AnyVecVec;
+	typedef std::map<char*, std::string*>                    StringMap;
+	typedef std::map<UTF16String::value_type*, UTF16String*> UTF16StringMap;
+	typedef std::map<SQL_DATE_STRUCT*, Date*>                DateMap;
+	typedef std::map<SQL_TIME_STRUCT*, Time*>                TimeMap;
+	typedef std::map<SQL_TIMESTAMP_STRUCT*, DateTime*>       TimestampMap;
+
+	void describeParameter(std::size_t pos);
+		/// Sets the description field for the parameter, if needed.
+
+	void bind(std::size_t pos, const char* const& pVal, Direction dir);
+		/// Binds a const char ptr. 
+		/// This is a private no-op in this implementation
+		/// due to security risk.
+
+	SQLSMALLINT toODBCDirection(Direction dir) const;
+		/// Returns ODBC parameter direction based on the parameter binding direction
+		/// specified by user.
+
+	template <typename T>
+	void bindImpl(std::size_t pos, T& val, SQLSMALLINT cDataType, Direction dir)
+	{
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
+
+		_lengthIndicator.push_back(0);
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			cDataType, 
+			Utility::sqlDataType(cDataType), 
+			colSize,
+			decDigits,
+			(SQLPOINTER) &val, 0, 0)))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter()");
+		}
+	}
+
+	template <typename L>
+	void bindImplLOB(std::size_t pos, const L& val, Direction dir)
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("LOB parameter type can only be inbound.");
+
+		SQLPOINTER pVal = (SQLPOINTER) val.rawContent();
+		SQLINTEGER size = (SQLINTEGER) val.size();
+			
+		_inParams.insert(ParamMap::value_type(pVal, size));
+
+		SQLLEN* pLenIn = new SQLLEN;
+		*pLenIn  = size;
+
+		if (PB_AT_EXEC == _paramBinding)
+			*pLenIn  = SQL_LEN_DATA_AT_EXEC(size);
+
+		_lengthIndicator.push_back(pLenIn);
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			SQL_PARAM_INPUT, 
+			SQL_C_BINARY, 
+			SQL_LONGVARBINARY, 
+			(SQLUINTEGER) size,
+			0,
+			pVal,
+			(SQLINTEGER) size, 
+			_lengthIndicator.back())))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(LOB)");
+		}
+	}
+
+	template <typename T>
+	void bindImplVec(std::size_t pos, const std::vector<T>& val, SQLSMALLINT cDataType, Direction dir)
+	{
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("std::vector can only be bound immediately.");
+
+		std::size_t length = val.size();
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
+		setParamSetSize(length);
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length);
+		}
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			cDataType, 
+			Utility::sqlDataType(cDataType), 
+			colSize,
+			decDigits,
+			(SQLPOINTER) &val[0], 
+			0, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter()");
+		}
+	}
+
+	template <typename C>
+	void bindImplContainer(std::size_t pos, const C& val, SQLSMALLINT cDataType, Direction dir)
+		/// Utility function - a "stand-in" for non-vector containers.
+		/// Creates, fills and stores the reference to the replacement std::vector container
+		/// for std::deque and std::list. Calls std::vector binding.
+	{
+		typedef typename C::value_type Type;
+
+		if (_containers.size() <= pos)
+			_containers.resize(pos + 1);
+
+		_containers[pos].push_back(std::vector<Type>());
+
+		std::vector<Type>& cont = RefAnyCast<std::vector<Type> >(_containers[pos].back());
+		cont.assign(val.begin(), val.end());
+		bindImplVec(pos, cont, cDataType, dir);
+	}
+
+	template <typename C>
+	void bindImplContainerBool(std::size_t pos, const C& val, SQLSMALLINT cDataType, Direction dir)
+	{
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("std::vector can only be bound immediately.");
+
+		std::size_t length = val.size();
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, cDataType, colSize, decDigits);
+
+		setParamSetSize(val.size());
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length);
+		}
+
+		if (_boolPtrs.size() <= pos)
+			_boolPtrs.resize(pos + 1);
+
+		_boolPtrs[pos] = new bool[val.size()];
+
+		typename C::const_iterator it = val.begin();
+		typename C::const_iterator end = val.end();
+		for (int i = 0; it != end; ++it, ++i) _boolPtrs[pos][i] = *it;
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			cDataType, 
+			Utility::sqlDataType(cDataType), 
+			colSize,
+			decDigits,
+			(SQLPOINTER) &_boolPtrs[pos][0], 
+			0, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter()");
+		}
+	}
+
+	template <typename C>
+	void bindImplContainerString(std::size_t pos, const C& val, Direction dir)
+		/// Utility function to bind containers of strings.
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("String container parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("Containers can only be bound immediately.");
+
+		std::size_t length = val.size();
+
+		if (0 == length)
+			throw InvalidArgumentException("Empty container not allowed.");
+
+		setParamSetSize(length);
+
+		SQLINTEGER size = 0;
+		getColumnOrParameterSize(pos, size);
+		poco_assert (size > 0);
+
+		if (size == _maxFieldSize)
+		{
+			getMinValueSize(val, size);
+			// accomodate for terminating zero
+			if (size != _maxFieldSize) ++size;
+		}
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1, SQL_NTS);
+		}
+
+		if (_charPtrs.size() <= pos)
+			_charPtrs.resize(pos + 1, 0);
+
+		_charPtrs[pos] = (char*) std::calloc(val.size() * size, sizeof(char));
+		
+		std::size_t strSize;
+		std::size_t offset = 0;
+		typename C::const_iterator it = val.begin();
+		typename C::const_iterator end = val.end();
+		for (; it != end; ++it)
+		{
+			strSize = it->size();
+			if (strSize > size)	
+				throw LengthExceededException("SQLBindParameter(std::vector<std::string>)");
+			std::memcpy(_charPtrs[pos] + offset, it->c_str(), strSize);
+			offset += size;
+		}
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			SQL_C_CHAR, 
+			SQL_LONGVARCHAR, 
+			(SQLUINTEGER) size - 1,
+			0,
+			_charPtrs[pos], 
+			(SQLINTEGER) size, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(std::vector<std::string>)");
+		}
+	}
+
+	template <typename C>
+	void bindImplContainerUTF16String(std::size_t pos, const C& val, Direction dir)
+		/// Utility function to bind containers of strings.
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("String container parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("Containers can only be bound immediately.");
+
+		std::size_t length = val.size();
+		if (0 == length)
+			throw InvalidArgumentException("Empty container not allowed.");
+
+		setParamSetSize(val.size());
+
+		SQLINTEGER size = 0;
+		getColumnOrParameterSize(pos, size);
+		poco_assert(size > 0);
+
+		if (size == _maxFieldSize)
+		{
+			getMinValueSize(val, size);
+			// accomodate for terminating zero
+			if (size != _maxFieldSize) size += sizeof(UTF16Char);
+		}
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1, SQL_NTS);
+		}
+
+		if (_utf16CharPtrs.size() <= pos)
+			_utf16CharPtrs.resize(pos + 1, 0);
+
+		_utf16CharPtrs[pos] = (UTF16Char*)std::calloc(val.size() * size, sizeof(UTF16Char));
+
+		std::size_t strSize;
+		std::size_t offset = 0;
+		char* pBuf = (char*)_utf16CharPtrs[pos];
+		typename C::const_iterator it = val.begin();
+		typename C::const_iterator end = val.end();
+		for (; it != end; ++it)
+		{
+			strSize = it->size() * sizeof(UTF16Char);
+			if (strSize > size)
+				throw LengthExceededException("SQLBindParameter(std::vector<UTF16String>)");
+			std::memcpy(pBuf + offset, it->data(), strSize);
+			offset += size;
+		}
+
+		if (Utility::isError(SQLBindParameter(_rStmt,
+			(SQLUSMALLINT)pos + 1,
+			toODBCDirection(dir),
+			SQL_C_WCHAR,
+			SQL_WLONGVARCHAR,
+			(SQLUINTEGER)size - 1,
+			0,
+			_utf16CharPtrs[pos],
+			(SQLINTEGER)size,
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(std::vector<UTF16String>)");
+		}
+	}
+
+	template <typename C>
+	void bindImplContainerLOB(std::size_t pos, const C& val, Direction dir)
+	{
+		typedef typename C::value_type LOBType;
+		typedef typename LOBType::ValueType CharType;
+
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("BLOB container parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("Containers can only be bound immediately.");
+
+		std::size_t length = val.size();
+		if (0 == length)
+			throw InvalidArgumentException("Empty container not allowed.");
+
+		setParamSetSize(length);
+
+		SQLINTEGER size = 0;
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
+		}
+
+		std::vector<SQLLEN>::iterator lIt = _vecLengthIndicator[pos]->begin();
+		std::vector<SQLLEN>::iterator lEnd = _vecLengthIndicator[pos]->end();
+		typename C::const_iterator cIt = val.begin();
+		for (; lIt != lEnd; ++lIt, ++cIt) 
+		{
+			SQLLEN sz = static_cast<SQLLEN>(cIt->size());
+			if (sz > size) size = static_cast<SQLINTEGER>(sz);
+			*lIt = sz;
+		}
+
+		if (_charPtrs.size() <= pos)
+			_charPtrs.resize(pos + 1, 0);
+
+		_charPtrs[pos] = (char*) std::calloc(val.size() * size, sizeof(CharType));
+		poco_check_ptr (_charPtrs[pos]);
+
+		std::size_t blobSize;
+		std::size_t offset = 0;
+		cIt = val.begin();
+		typename C::const_iterator cEnd = val.end();
+		for (; cIt != cEnd; ++cIt)
+		{
+			blobSize = cIt->size();
+			if (blobSize > size)	
+				throw LengthExceededException("SQLBindParameter(std::vector<BLOB>)");
+			std::memcpy(_charPtrs[pos] + offset, cIt->rawContent(), blobSize * sizeof(CharType));
+			offset += size;
+		}
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			SQL_PARAM_INPUT, 
+			SQL_C_BINARY, 
+			SQL_LONGVARBINARY, 
+			(SQLUINTEGER) size,
+			0,
+			_charPtrs[pos], 
+			(SQLINTEGER) size, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(std::vector<BLOB>)");
+		}
+	}
+
+	template<typename C>
+	void bindImplContainerDate(std::size_t pos, const C& val, Direction dir)
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("Date vector parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("std::vector can only be bound immediately.");
+
+		std::size_t length = val.size();
+
+		if (0 == length)
+			throw InvalidArgumentException("Empty vector not allowed.");
+
+		setParamSetSize(length);
+
+		SQLINTEGER size = (SQLINTEGER) sizeof(SQL_DATE_STRUCT);
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
+		}
+
+		if (_dateVecVec.size() <= pos)
+		{
+			_dateVecVec.resize(pos + 1, 0);
+			_dateVecVec[pos] = new DateVec(length ? length : 1);
+		}
+
+		Utility::dateSync(*_dateVecVec[pos], val);
+
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, SQL_TYPE_DATE, colSize, decDigits);
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			SQL_C_TYPE_DATE, 
+			SQL_TYPE_DATE, 
+			colSize,
+			decDigits,
+			(SQLPOINTER) &(*_dateVecVec[pos])[0], 
+			0, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(Date[])");
+		}
+	}
+
+	template<typename C>
+	void bindImplContainerTime(std::size_t pos, const C& val, Direction dir)
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("Time container parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("Containers can only be bound immediately.");
+
+		std::size_t length = val.size();
+		if (0 == length)
+			throw InvalidArgumentException("Empty container not allowed.");
+
+		setParamSetSize(val.size());
+
+		SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIME_STRUCT);
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
+		}
+
+		if (_timeVecVec.size() <= pos)
+		{
+			_timeVecVec.resize(pos + 1, 0);
+			_timeVecVec[pos] = new TimeVec(length ? length : 1);
+		}
+
+		Utility::timeSync(*_timeVecVec[pos], val);
+
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, SQL_TYPE_TIME, colSize, decDigits);
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			SQL_C_TYPE_TIME, 
+			SQL_TYPE_TIME, 
+			colSize,
+			decDigits,
+			(SQLPOINTER) &(*_timeVecVec[pos])[0], 
+			0, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(Time[])");
+		}
+	}
+
+	template<typename C>
+	void bindImplContainerDateTime(std::size_t pos, const C& val, Direction dir)
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("DateTime container parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("Containers can only be bound immediately.");
+
+		std::size_t length = val.size();
+
+		if (0 == length)
+			throw InvalidArgumentException("Empty Containers not allowed.");
+
+		setParamSetSize(length);
+
+		SQLINTEGER size = (SQLINTEGER) sizeof(SQL_TIMESTAMP_STRUCT);
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
+		}
+
+		if (_dateTimeVecVec.size() <= pos)
+		{
+			_dateTimeVecVec.resize(pos + 1, 0);
+			_dateTimeVecVec[pos] = new DateTimeVec(length ? length : 1);
+		}
+
+		Utility::dateTimeSync(*_dateTimeVecVec[pos], val);
+
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, SQL_TYPE_TIMESTAMP, colSize, decDigits);
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			toODBCDirection(dir), 
+			SQL_C_TYPE_TIMESTAMP, 
+			SQL_TYPE_TIMESTAMP, 
+			colSize,
+			decDigits,
+			(SQLPOINTER) &(*_dateTimeVecVec[pos])[0], 
+			0, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter(Time[])");
+		}
+	}
+
+	template<typename C>
+	void bindImplNullContainer(std::size_t pos, const C& val, Direction dir)
+	{
+		if (isOutBound(dir) || !isInBound(dir))
+			throw NotImplementedException("Null container parameter type can only be inbound.");
+
+		if (PB_IMMEDIATE != _paramBinding)
+			throw InvalidAccessException("Container can only be bound immediately.");
+
+		std::size_t length = val.size();
+
+		if (0 == length)
+			throw InvalidArgumentException("Empty container not allowed.");
+
+		setParamSetSize(length);
+
+		SQLINTEGER size = SQL_NULL_DATA;
+
+		if (_vecLengthIndicator.size() <= pos)
+		{
+			_vecLengthIndicator.resize(pos + 1, 0);
+			_vecLengthIndicator[pos] = new LengthVec(length ? length : 1);
+		}
+
+		SQLINTEGER colSize = 0;
+		SQLSMALLINT decDigits = 0;
+		getColSizeAndPrecision(pos, SQL_C_STINYINT, colSize, decDigits);
+
+		if (Utility::isError(SQLBindParameter(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			SQL_PARAM_INPUT, 
+			SQL_C_STINYINT, 
+			Utility::sqlDataType(SQL_C_STINYINT), 
+			colSize,
+			decDigits,
+			0, 
+			0, 
+			&(*_vecLengthIndicator[pos])[0])))
+		{
+			throw StatementException(_rStmt, "SQLBindParameter()");
+		}
+	}
+
+	void getColSizeAndPrecision(std::size_t pos, 
+		SQLSMALLINT cDataType, 
+		SQLINTEGER& colSize, 
+		SQLSMALLINT& decDigits,
+		std::size_t actualSize = 0);
+		/// Used to retrieve column size and precision.
+		/// Not all drivers cooperate with this inquiry under all circumstances
+		/// This function runs for query and stored procedure parameters (in and 
+		/// out-bound). Some drivers, however, do not care about knowing this 
+		/// information to start with. For that reason, after all the attempts 
+		/// to discover the required values are unsuccesfully exhausted, the values 
+		/// are both set to zero and no exception is thrown.
+		/// However, if the colSize is succesfully retrieved and it is greater than
+		/// session-wide maximum allowed field size, LengthExceededException is thrown.
+
+	void setParamSetSize(std::size_t length);
+		/// Sets the parameter set size. Used for column-wise binding.
+
+	void getColumnOrParameterSize(std::size_t pos, SQLINTEGER& size);
+		/// Fills the column or parameter size into the 'size' argument.
+		/// Does nothing if neither can be obtained from the driver, so
+		/// size should be set to some default value prior to calling this 
+		/// function in order to avoid undefined size value.
+
+	void freeMemory();
+		/// Frees all dynamically allocated memory resources.
+
+	template<typename T>
+	void getMinValueSize(T& val, SQLINTEGER& size)
+		/// Some ODBC drivers return DB-wide maximum allowed size for variable size columns,
+		/// rather than the allowed size for the actual column. In such cases, the length is 
+		/// automatically resized to the maximum field size allowed by the session.
+		/// This function, in order to prevent unnecessary memory allocation, does further 
+		/// optimization, looking for the maximum length within supplied data container and
+		/// uses the smaller of maximum found and maximum predefined data length.
+	{
+		typedef typename T::value_type ContainedValType;
+		typedef typename ContainedValType::value_type BaseValType;
+		std::size_t typeSize = sizeof(BaseValType);
+		std::size_t maxSize = 0;
+		typename T::const_iterator it = val.begin();
+		typename T::const_iterator end = val.end();
+		for (; it != end; ++it)
+		{
+			std::size_t sz = it->size() * typeSize;
+			if (sz > _maxFieldSize)
+				throw LengthExceededException();
+
+			if (sz == _maxFieldSize)
+			{
+				maxSize = 0;
+				break;
+			}
+
+			if (sz < _maxFieldSize && sz > maxSize)
+				maxSize = sz;
+		}
+		if (maxSize) size = static_cast<SQLINTEGER>(maxSize);
+	}
+
+	const StatementHandle& _rStmt;
+
+	LengthPtrVec     _lengthIndicator;
+	LengthVecVec     _vecLengthIndicator;
+
+	ParamMap         _inParams;
+	ParamMap         _outParams;
+	ParameterBinding _paramBinding;
+	
+	DateMap          _dates;
+	TimeMap          _times;
+	TimestampMap     _timestamps;
+	StringMap        _strings;
+	UTF16StringMap   _utf16Strings;
+
+	DateVecVec       _dateVecVec;
+	TimeVecVec       _timeVecVec;
+	DateTimeVecVec   _dateTimeVecVec;
+	CharPtrVec       _charPtrs;
+	UTF16CharPtrVec  _utf16CharPtrs;
+	BoolPtrVec       _boolPtrs;
+	const TypeInfo*  _pTypeInfo;
+	SQLINTEGER       _paramSetSize;
+	std::size_t      _maxFieldSize;
+	AnyVecVec        _containers;
+};
+
+
+//
+// inlines
+//
+inline void Binder::bind(std::size_t pos, const Poco::Int8& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::Int8>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::Int8>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt8& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_UTINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt8>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_UTINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::UInt8>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_UTINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt8>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_UTINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::Int16& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_SSHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int16>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_SSHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::Int16>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SSHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::Int16>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SSHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt16& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_USHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt16>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_USHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::UInt16>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_USHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt16>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_USHORT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::Int32& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int32>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::Int32>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::Int32>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt32& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_ULONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt32>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_ULONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::UInt32>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_ULONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt32>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_ULONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::Int64& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_SBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::Int64>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_SBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::Int64>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::Int64>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt64& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_UBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Poco::UInt64>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_UBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Poco::UInt64>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_UBIGINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Poco::UInt64>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_UBIGINT, dir);
+}
+
+
+#ifndef POCO_LONG_IS_64_BIT
+inline void Binder::bind(std::size_t pos, const long& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const unsigned long& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<long>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<long>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SLONG, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<long>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_SLONG, dir);
+}
+#endif
+
+
+inline void Binder::bind(std::size_t pos, const float& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_FLOAT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<float>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_FLOAT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<float>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_FLOAT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<float>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_FLOAT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const double& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_DOUBLE, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<double>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_DOUBLE, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<double>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_DOUBLE, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<double>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_DOUBLE, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const bool& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_BIT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<bool>& val, Direction dir)
+{
+	bindImplContainerBool(pos, val, SQL_C_BIT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<bool>& val, Direction dir)
+{
+	bindImplContainerBool(pos, val, SQL_C_BIT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<bool>& val, Direction dir)
+{
+	bindImplContainerBool(pos, val, SQL_C_BIT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const char& val, Direction dir)
+{
+	bindImpl(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<char>& val, Direction dir)
+{
+	bindImplVec(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<char>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<char>& val, Direction dir)
+{
+	bindImplContainer(pos, val, SQL_C_STINYINT, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<std::string>& val, Direction dir)
+{
+	bindImplContainerString(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<std::string>& val, Direction dir)
+{
+	bindImplContainerString(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<std::string>& val, Direction dir)
+{
+	bindImplContainerString(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<UTF16String>& val, Direction dir)
+{
+	bindImplContainerUTF16String(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<UTF16String>& val, Direction dir)
+{
+	bindImplContainerUTF16String(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<UTF16String>& val, Direction dir)
+{
+	bindImplContainerUTF16String(pos, val, dir);
+}
+
+inline void Binder::bind(std::size_t pos, const BLOB& val, Direction dir)
+{
+	bindImplLOB<BLOB>(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const CLOB& val, Direction dir)
+{
+	bindImplLOB<CLOB>(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<BLOB>& val, Direction dir)
+{
+	bindImplContainerLOB(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<BLOB>& val, Direction dir)
+{
+	bindImplContainerLOB(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<BLOB>& val, Direction dir)
+{
+	bindImplContainerLOB(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<CLOB>& val, Direction dir)
+{
+	bindImplContainerLOB(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<CLOB>& val, Direction dir)
+{
+	bindImplContainerLOB(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<CLOB>& val, Direction dir)
+{
+	bindImplContainerLOB(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Date>& val, Direction dir)
+{
+	bindImplContainerDate(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Date>& val, Direction dir)
+{
+	bindImplContainerDate(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Date>& val, Direction dir)
+{
+	bindImplContainerDate(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<Time>& val, Direction dir)
+{
+	bindImplContainerTime(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<Time>& val, Direction dir)
+{
+	bindImplContainerTime(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<Time>& val, Direction dir)
+{
+	bindImplContainerTime(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<DateTime>& val, Direction dir)
+{
+	bindImplContainerDateTime(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<DateTime>& val, Direction dir)
+{
+	bindImplContainerDateTime(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<DateTime>& val, Direction dir)
+{
+	bindImplContainerDateTime(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::vector<NullData>& val, Direction dir)
+{
+	bindImplNullContainer(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::deque<NullData>& val, Direction dir)
+{
+	bindImplNullContainer(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const std::list<NullData>& val, Direction dir)
+{
+	bindImplNullContainer(pos, val, dir);
+}
+
+
+inline void Binder::setDataBinding(Binder::ParameterBinding binding)
+{
+	_paramBinding = binding;
+}
+
+
+inline Binder::ParameterBinding Binder::getDataBinding() const
+{
+	return _paramBinding;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_Binder_INCLUDED
diff --git a/Poco/Data/ODBC/ConnectionHandle.h b/Poco/Data/ODBC/ConnectionHandle.h
new file mode 100644
index 0000000..466ad93
--- /dev/null
+++ b/Poco/Data/ODBC/ConnectionHandle.h
@@ -0,0 +1,96 @@
+//
+// ConnectionHandle.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  ConnectionHandle
+//
+// Definition of ConnectionHandle.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_ConnectionHandle_INCLUDED
+#define Data_ODBC_ConnectionHandle_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/EnvironmentHandle.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API ConnectionHandle
+/// ODBC connection handle class
+{
+public:
+	ConnectionHandle(EnvironmentHandle* pEnvironment = 0);
+		/// Creates the ConnectionHandle.
+
+	~ConnectionHandle();
+		/// Creates the ConnectionHandle.
+
+	operator const SQLHDBC& () const;
+		/// Const conversion operator into reference to native type.
+
+	const SQLHDBC& handle() const;
+		/// Returns const reference to handle;
+
+private:
+	operator SQLHDBC& ();
+		/// Conversion operator into reference to native type.
+
+	SQLHDBC& handle();
+		/// Returns reference to handle;
+
+	ConnectionHandle(const ConnectionHandle&);
+	const ConnectionHandle& operator=(const ConnectionHandle&);
+
+	const EnvironmentHandle* _pEnvironment;
+	SQLHDBC                  _hdbc;
+	bool                     _ownsEnvironment;
+};
+
+
+//
+// inlines
+//
+inline ConnectionHandle::operator const SQLHDBC& () const
+{
+	return handle();
+}
+
+
+inline const SQLHDBC& ConnectionHandle::handle() const
+{
+	return _hdbc;
+}
+
+
+inline ConnectionHandle::operator SQLHDBC& ()
+{
+	return handle();
+}
+
+
+inline SQLHDBC& ConnectionHandle::handle()
+{
+	return _hdbc;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/Connector.h b/Poco/Data/ODBC/Connector.h
new file mode 100644
index 0000000..a4dc92d
--- /dev/null
+++ b/Poco/Data/ODBC/Connector.h
@@ -0,0 +1,70 @@
+//
+// Connector.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Connector
+//
+// Definition of the Connector class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Connector_INCLUDED
+#define Data_ODBC_Connector_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/Connector.h"
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API Connector: public Poco::Data::Connector
+	/// Connector instantiates SqLite SessionImpl objects.
+{
+public:
+	static const std::string KEY;
+		/// Keyword for creating ODBC sessions.
+
+	Connector();
+		/// Creates the Connector.
+
+	~Connector();
+		/// Destroys the Connector.
+
+	const std::string& name() const;
+		/// Returns the name associated with this connector.
+
+	Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
+		std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT);
+		/// Creates a ODBC SessionImpl object and initializes it with the given connectionString.
+
+	static void registerConnector();
+		/// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
+
+	static void unregisterConnector();
+		/// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory
+};
+
+
+///
+/// inlines
+///
+inline const std::string& Connector::name() const
+{
+	return KEY;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_Connector_INCLUDED
diff --git a/Poco/Data/ODBC/Diagnostics.h b/Poco/Data/ODBC/Diagnostics.h
new file mode 100644
index 0000000..86c15fa
--- /dev/null
+++ b/Poco/Data/ODBC/Diagnostics.h
@@ -0,0 +1,239 @@
+//
+// Diagnostics.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Diagnostics
+//
+// Definition of Diagnostics.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Diagnostics_INCLUDED
+#define Data_ODBC_Diagnostics_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include <vector>
+#include <cstring>
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+template <typename H, SQLSMALLINT handleType>
+class Diagnostics
+	/// Utility class providing functionality for retrieving ODBC diagnostic
+	/// records. Diagnostics object must be created with corresponding handle
+	/// as constructor argument. During construction, diagnostic records fields 
+	/// are populated and the object is ready for querying.
+{
+public:
+
+	static const unsigned int SQL_STATE_SIZE = SQL_SQLSTATE_SIZE + 1;
+	static const unsigned int SQL_MESSAGE_LENGTH = SQL_MAX_MESSAGE_LENGTH + 1;
+	static const unsigned int SQL_NAME_LENGTH = 128;
+	static const std::string  DATA_TRUNCATED;
+
+	struct DiagnosticFields
+	{
+		/// SQLGetDiagRec fields
+		SQLCHAR    _sqlState[SQL_STATE_SIZE];
+		SQLCHAR    _message[SQL_MESSAGE_LENGTH];
+		SQLINTEGER _nativeError;
+	};
+
+	typedef std::vector<DiagnosticFields> FieldVec;
+	typedef typename FieldVec::const_iterator Iterator;
+
+	explicit Diagnostics(const H& handle): _handle(handle)
+		/// Creates and initializes the Diagnostics.
+	{
+		std::memset(_connectionName, 0, sizeof(_connectionName));
+		std::memset(_serverName, 0, sizeof(_serverName));
+		diagnostics();
+	}
+
+	~Diagnostics()
+		/// Destroys the Diagnostics.
+	{
+	}
+
+	std::string sqlState(int index) const
+		/// Returns SQL state.
+	{
+		poco_assert (index < count());
+		return std::string((char*) _fields[index]._sqlState);
+	}
+
+	std::string message(int index) const
+		/// Returns error message.
+	{
+		poco_assert (index < count());
+		return std::string((char*) _fields[index]._message);
+	}
+
+	long nativeError(int index) const
+		/// Returns native error code.
+	{
+		poco_assert (index < count());
+		return _fields[index]._nativeError;
+	}
+
+	std::string connectionName() const
+		/// Returns the connection name. 
+		/// If there is no active connection, connection name defaults to NONE.
+		/// If connection name is not applicable for query context (such as when querying environment handle),
+		/// connection name defaults to NOT_APPLICABLE.
+	{
+		return std::string((char*) _connectionName);
+	}
+
+	std::string serverName() const
+		/// Returns the server name.
+		/// If the connection has not been established, server name defaults to NONE.
+		/// If server name is not applicable for query context (such as when querying environment handle),
+		/// connection name defaults to NOT_APPLICABLE.
+	{
+		return std::string((char*) _serverName);
+	}
+
+	int count() const
+		/// Returns the number of contained diagnostic records.
+	{
+		return (int) _fields.size();
+	}
+
+	void reset()
+		/// Resets the diagnostic fields container.
+	{
+		_fields.clear();
+	}
+
+	const FieldVec& fields() const
+	{
+		return _fields;
+	}
+
+	Iterator begin() const
+	{
+		return _fields.begin();
+	}
+
+	Iterator end() const
+	{
+		return _fields.end();
+	}
+
+	const Diagnostics& diagnostics()
+	{
+		DiagnosticFields df;
+		SQLSMALLINT count = 1;
+		SQLSMALLINT messageLength = 0;
+		static const std::string none = "None";
+		static const std::string na = "Not applicable";
+
+		reset();
+
+		while (!Utility::isError(SQLGetDiagRec(handleType, 
+			_handle, 
+			count, 
+			df._sqlState, 
+			&df._nativeError, 
+			df._message, 
+			SQL_MESSAGE_LENGTH, 
+			&messageLength))) 
+		{
+			if (1 == count)
+			{
+				// success of the following two calls is optional
+				// (they fail if connection has not been established yet
+				//  or return empty string if not applicable for the context)
+				if (Utility::isError(SQLGetDiagField(handleType, 
+					_handle, 
+					count, 
+					SQL_DIAG_CONNECTION_NAME, 
+					_connectionName, 
+					sizeof(_connectionName), 
+					&messageLength)))
+				{
+					std::size_t len = sizeof(_connectionName) > none.length() ? 
+						none.length() : sizeof(_connectionName) - 1;
+					std::memcpy(_connectionName, none.c_str(), len);
+				}
+				else if (0 == _connectionName[0]) 
+				{
+					std::size_t len = sizeof(_connectionName) > na.length() ? 
+						na.length() : sizeof(_connectionName) - 1;
+					std::memcpy(_connectionName, na.c_str(), len);
+				}
+				
+				if (Utility::isError(SQLGetDiagField(handleType, 
+					_handle, 
+					count, 
+					SQL_DIAG_SERVER_NAME, 
+					_serverName, 
+					sizeof(_serverName), 
+					&messageLength)))
+				{
+					std::size_t len = sizeof(_serverName) > none.length() ? 
+						none.length() : sizeof(_serverName) - 1;
+					std::memcpy(_serverName, none.c_str(), len);
+				}
+				else if (0 == _serverName[0]) 
+				{
+					std::size_t len = sizeof(_serverName) > na.length() ? 
+						na.length() : sizeof(_serverName) - 1;
+					std::memcpy(_serverName, na.c_str(), len);
+				}
+			}
+
+			_fields.push_back(df);
+
+			std::memset(df._sqlState, 0, SQL_STATE_SIZE);
+			std::memset(df._message, 0, SQL_MESSAGE_LENGTH);
+			df._nativeError = 0;
+
+			++count;
+		}
+
+		return *this;
+	}
+
+private:
+
+	Diagnostics();
+
+	/// SQLGetDiagField fields
+	SQLCHAR _connectionName[SQL_NAME_LENGTH];
+	SQLCHAR _serverName[SQL_NAME_LENGTH];
+
+	/// Diagnostics container
+	FieldVec _fields;
+
+	/// Context handle
+	const H& _handle;
+};
+
+
+typedef Diagnostics<SQLHENV, SQL_HANDLE_ENV> EnvironmentDiagnostics;
+typedef Diagnostics<SQLHDBC, SQL_HANDLE_DBC> ConnectionDiagnostics;
+typedef Diagnostics<SQLHSTMT, SQL_HANDLE_STMT> StatementDiagnostics;
+typedef Diagnostics<SQLHDESC, SQL_HANDLE_DESC> DescriptorDiagnostics;
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/EnvironmentHandle.h b/Poco/Data/ODBC/EnvironmentHandle.h
new file mode 100644
index 0000000..cec8d72
--- /dev/null
+++ b/Poco/Data/ODBC/EnvironmentHandle.h
@@ -0,0 +1,94 @@
+//
+// EnvironmentHandle.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  EnvironmentHandle
+//
+// Definition of EnvironmentHandle.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_EnvironmentHandle_INCLUDED
+#define Data_ODBC_EnvironmentHandle_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API EnvironmentHandle
+/// ODBC environment handle class
+{
+public:
+	EnvironmentHandle();
+		/// Creates the EnvironmentHandle.
+
+	~EnvironmentHandle();
+		/// Destroys the EnvironmentHandle.
+
+	operator const SQLHENV& () const;
+		/// Const conversion operator into reference to native type.
+
+	const SQLHENV& handle() const;
+		/// Returns const reference to handle.
+
+private:
+	operator SQLHENV& ();
+		/// Conversion operator into reference to native type.
+
+	SQLHENV& handle();
+		/// Returns reference to handle.
+
+	EnvironmentHandle(const EnvironmentHandle&);
+	const EnvironmentHandle& operator=(const EnvironmentHandle&);
+
+	SQLHENV _henv;
+	bool    _isOwner;
+};
+
+
+///
+/// inlines
+///
+inline EnvironmentHandle::operator const SQLHENV& () const
+{
+	return handle();
+}
+
+
+inline const SQLHENV& EnvironmentHandle::handle() const
+{
+	return _henv;
+}
+
+
+inline EnvironmentHandle::operator SQLHENV& ()
+{
+	return handle();
+}
+
+
+inline SQLHENV& EnvironmentHandle::handle()
+{
+	return _henv;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/Error.h b/Poco/Data/ODBC/Error.h
new file mode 100644
index 0000000..049cc02
--- /dev/null
+++ b/Poco/Data/ODBC/Error.h
@@ -0,0 +1,124 @@
+//
+// Error.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Error
+//
+// Definition of Error.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Error_INCLUDED
+#define Data_ODBC_Error_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/Utility.h"
+#include "Poco/Data/ODBC/Diagnostics.h"
+#include "Poco/Format.h"
+#include <vector>
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+template <typename H, SQLSMALLINT handleType>
+class Error
+	/// Class encapsulating ODBC diagnostic record collection. Collection is generated
+	/// during construction. Class provides access and string generation for the collection
+	/// as well as individual diagnostic records.
+{
+public:
+	explicit Error(const H& handle) : _diagnostics(handle)
+		/// Creates the Error.
+	{
+	}
+
+	~Error()
+		/// Destroys the Error.
+	{
+	}
+
+	const Diagnostics<H, handleType>& diagnostics() const
+		/// Returns the associated diagnostics.
+	{
+		return _diagnostics;
+	}
+
+	int count() const
+		/// Returns the count of diagnostic records.
+	{
+		return (int) _diagnostics.count();
+	}
+
+	std::string& toString(int index, std::string& str) const
+		/// Generates the string for the diagnostic record.
+	{
+		if ((index < 0) || (index > (count() - 1))) 
+			return str;
+
+		std::string s;
+		Poco::format(s, 
+			"===========================\n"
+			"ODBC Diagnostic record #%d:\n"
+			"===========================\n"
+			"SQLSTATE = %s\nNative Error Code = %ld\n%s\n\n",
+			index + 1,
+			_diagnostics.sqlState(index),
+			_diagnostics.nativeError(index),
+			_diagnostics.message(index));
+
+		str.append(s);
+
+		return str;
+	}
+
+	std::string toString() const
+		/// Generates the string for the diagnostic record collection.
+	{
+		std::string str;
+
+		Poco::format(str, 
+			"Connection:%s\nServer:%s\n",
+			_diagnostics.connectionName(),
+			_diagnostics.serverName());
+
+		std::string s;
+		for (int i = 0; i < count(); ++i)
+		{
+			s.clear();
+			str.append(toString(i, s));
+		}
+
+		return str;
+	}
+
+private:
+	Error();
+
+	Diagnostics<H, handleType> _diagnostics;
+};
+
+
+typedef Error<SQLHENV, SQL_HANDLE_ENV> EnvironmentError;
+typedef Error<SQLHDBC, SQL_HANDLE_DBC> ConnectionError;
+typedef Error<SQLHSTMT, SQL_HANDLE_STMT> StatementError;
+typedef Error<SQLHSTMT, SQL_HANDLE_DESC> DescriptorError;
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/Extractor.h b/Poco/Data/ODBC/Extractor.h
new file mode 100644
index 0000000..f3ce016
--- /dev/null
+++ b/Poco/Data/ODBC/Extractor.h
@@ -0,0 +1,728 @@
+//
+// Extractor.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Extractor
+//
+// Definition of the Extractor class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Extractor_INCLUDED
+#define Data_ODBC_Extractor_INCLUDED
+
+
+#include "Poco/Data/Constants.h"
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/AbstractExtractor.h"
+#include "Poco/Data/ODBC/Preparator.h"
+#include "Poco/Data/ODBC/ODBCMetaColumn.h"
+#include "Poco/Data/ODBC/Error.h"
+#include "Poco/Data/ODBC/Utility.h"
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.h"
+#include "Poco/DateTime.h"
+#include "Poco/Any.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Nullable.h"
+#include "Poco/UTFString.h"
+#include "Poco/Exception.h"
+#include <map>
+#ifdef POCO_OS_FAMILY_WINDOWS
+	#include <windows.h>
+#endif
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API Extractor: public Poco::Data::AbstractExtractor
+	/// Extracts and converts data values from the result row returned by ODBC.
+	/// If NULL is received, the incoming val value is not changed and false is returned
+{
+public:
+	typedef Preparator::Ptr PreparatorPtr;
+
+	Extractor(const StatementHandle& rStmt, 
+		Preparator::Ptr pPreparator);
+		/// Creates the Extractor.
+
+	~Extractor();
+		/// Destroys the Extractor.
+
+	bool extract(std::size_t pos, Poco::Int8& val);
+		/// Extracts an Int8.
+
+	bool extract(std::size_t pos, std::vector<Poco::Int8>& val);
+		/// Extracts an Int8 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Int8>& val);
+		/// Extracts an Int8 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Int8>& val);
+		/// Extracts an Int8 list.
+
+	bool extract(std::size_t pos, Poco::UInt8& val);
+		/// Extracts an UInt8.
+
+	bool extract(std::size_t pos, std::vector<Poco::UInt8>& val);
+		/// Extracts an UInt8 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::UInt8>& val);
+		/// Extracts an UInt8 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::UInt8>& val);
+		/// Extracts an UInt8 list.
+
+	bool extract(std::size_t pos, Poco::Int16& val);
+		/// Extracts an Int16.
+
+	bool extract(std::size_t pos, std::vector<Poco::Int16>& val);
+		/// Extracts an Int16 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Int16>& val);
+		/// Extracts an Int16 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Int16>& val);
+		/// Extracts an Int16 list.
+
+	bool extract(std::size_t pos, Poco::UInt16& val);
+		/// Extracts an UInt16.
+
+	bool extract(std::size_t pos, std::vector<Poco::UInt16>& val);
+		/// Extracts an UInt16 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::UInt16>& val);
+		/// Extracts an UInt16 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::UInt16>& val);
+		/// Extracts an UInt16 list.
+
+	bool extract(std::size_t pos, Poco::Int32& val);
+		/// Extracts an Int32.
+
+	bool extract(std::size_t pos, std::vector<Poco::Int32>& val);
+		/// Extracts an Int32 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Int32>& val);
+		/// Extracts an Int32 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Int32>& val);
+		/// Extracts an Int32 list.
+
+	bool extract(std::size_t pos, Poco::UInt32& val);
+		/// Extracts an UInt32.
+
+	bool extract(std::size_t pos, std::vector<Poco::UInt32>& val);
+		/// Extracts an UInt32 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::UInt32>& val);
+		/// Extracts an UInt32 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::UInt32>& val);
+		/// Extracts an UInt32 list.
+
+	bool extract(std::size_t pos, Poco::Int64& val);
+		/// Extracts an Int64.
+
+	bool extract(std::size_t pos, std::vector<Poco::Int64>& val);
+		/// Extracts an Int64 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Int64>& val);
+		/// Extracts an Int64 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Int64>& val);
+		/// Extracts an Int64 list.
+
+	bool extract(std::size_t pos, Poco::UInt64& val);
+		/// Extracts an UInt64.
+
+	bool extract(std::size_t pos, std::vector<Poco::UInt64>& val);
+		/// Extracts an UInt64 vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::UInt64>& val);
+		/// Extracts an UInt64 deque.
+
+	bool extract(std::size_t pos, std::list<Poco::UInt64>& val);
+		/// Extracts an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	bool extract(std::size_t pos, long& val);
+		/// Extracts a long.
+
+	bool extract(std::size_t pos, unsigned long& val);
+		/// Extracts an unsigned long.
+
+	bool extract(std::size_t pos, std::vector<long>& val);
+		/// Extracts a long vector.
+
+	bool extract(std::size_t pos, std::deque<long>& val);
+		/// Extracts a long deque.
+
+	bool extract(std::size_t pos, std::list<long>& val);
+		/// Extracts a long list.
+#endif
+
+	bool extract(std::size_t pos, bool& val);
+		/// Extracts a boolean.
+
+	bool extract(std::size_t pos, std::vector<bool>& val);
+		/// Extracts a boolean vector.
+
+	bool extract(std::size_t pos, std::deque<bool>& val);
+		/// Extracts a boolean deque.
+
+	bool extract(std::size_t pos, std::list<bool>& val);
+		/// Extracts a boolean list.
+
+	bool extract(std::size_t pos, float& val);
+		/// Extracts a float.
+
+	bool extract(std::size_t pos, std::vector<float>& val);
+		/// Extracts a float vector.
+
+	bool extract(std::size_t pos, std::deque<float>& val);
+		/// Extracts a float deque.
+
+	bool extract(std::size_t pos, std::list<float>& val);
+		/// Extracts a float list.
+
+	bool extract(std::size_t pos, double& val);
+		/// Extracts a double.
+
+	bool extract(std::size_t pos, std::vector<double>& val);
+		/// Extracts a double vector.
+
+	bool extract(std::size_t pos, std::deque<double>& val);
+		/// Extracts a double deque.
+
+	bool extract(std::size_t pos, std::list<double>& val);
+		/// Extracts a double list.
+
+	bool extract(std::size_t pos, char& val);
+		/// Extracts a single character.
+
+	bool extract(std::size_t pos, std::vector<char>& val);
+		/// Extracts a single character vector.
+
+	bool extract(std::size_t pos, std::deque<char>& val);
+		/// Extracts a single character deque.
+
+	bool extract(std::size_t pos, std::list<char>& val);
+		/// Extracts a single character list.
+
+	bool extract(std::size_t pos, std::string& val);
+		/// Extracts a string.
+
+	bool extract(std::size_t pos, std::vector<std::string>& val);
+		/// Extracts a string vector.
+
+	bool extract(std::size_t pos, std::deque<std::string>& val);
+		/// Extracts a string deque.
+
+	bool extract(std::size_t pos, std::list<std::string>& val);
+		/// Extracts a string list.
+		/// Extracts a single character list.
+
+	bool extract(std::size_t pos, UTF16String& val);
+	/// Extracts a string.
+
+	bool extract(std::size_t pos, std::vector<UTF16String>& val);
+	/// Extracts a string vector.
+
+	bool extract(std::size_t pos, std::deque<UTF16String>& val);
+	/// Extracts a string deque.
+
+	bool extract(std::size_t pos, std::list<UTF16String>& val);
+	/// Extracts a string list.
+
+	bool extract(std::size_t pos, Poco::Data::BLOB& val);
+		/// Extracts a BLOB.
+
+	bool extract(std::size_t pos, Poco::Data::CLOB& val);
+		/// Extracts a CLOB.
+
+	bool extract(std::size_t pos, std::vector<Poco::Data::BLOB>& val);
+		/// Extracts a BLOB vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Data::BLOB>& val);
+		/// Extracts a BLOB deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Data::BLOB>& val);
+		/// Extracts a BLOB list.
+
+	bool extract(std::size_t pos, std::vector<Poco::Data::CLOB>& val);
+		/// Extracts a CLOB vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Data::CLOB>& val);
+		/// Extracts a CLOB deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Data::CLOB>& val);
+		/// Extracts a CLOB list.
+
+	bool extract(std::size_t pos, Poco::Data::Date& val);
+		/// Extracts a Date.
+
+	bool extract(std::size_t pos, std::vector<Poco::Data::Date>& val);
+		/// Extracts a Date vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Data::Date>& val);
+		/// Extracts a Date deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Data::Date>& val);
+		/// Extracts a Date list.
+
+	bool extract(std::size_t pos, Poco::Data::Time& val);
+		/// Extracts a Time.
+
+	bool extract(std::size_t pos, std::vector<Poco::Data::Time>& val);
+		/// Extracts a Time vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Data::Time>& val);
+		/// Extracts a Time deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Data::Time>& val);
+		/// Extracts a Time list.
+
+	bool extract(std::size_t pos, Poco::DateTime& val);
+		/// Extracts a DateTime.
+
+	bool extract(std::size_t pos, std::vector<Poco::DateTime>& val);
+		/// Extracts a DateTime vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::DateTime>& val);
+		/// Extracts a DateTime deque.
+
+	bool extract(std::size_t pos, std::list<Poco::DateTime>& val);
+		/// Extracts a DateTime list.
+	
+	bool extract(std::size_t pos, Poco::Any& val);
+		/// Extracts an Any.
+
+	bool extract(std::size_t pos, std::vector<Poco::Any>& val);
+		/// Extracts an Any vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::Any>& val);
+		/// Extracts an Any deque.
+
+	bool extract(std::size_t pos, std::list<Poco::Any>& val);
+		/// Extracts an Any list.
+
+	bool extract(std::size_t pos, Poco::DynamicAny& val);
+		/// Extracts a DynamicAny.
+
+	bool extract(std::size_t pos, std::vector<Poco::DynamicAny>& val);
+		/// Extracts a DynamicAny vector.
+
+	bool extract(std::size_t pos, std::deque<Poco::DynamicAny>& val);
+		/// Extracts a DynamicAny deque.
+
+	bool extract(std::size_t pos, std::list<Poco::DynamicAny>& val);
+		/// Extracts a DynamicAny list.
+
+	void setDataExtraction(Preparator::DataExtraction ext);
+		/// Set data extraction mode.
+
+	Preparator::DataExtraction getDataExtraction() const;
+		/// Returns data extraction mode.
+
+	bool isNull(std::size_t col, std::size_t row = POCO_DATA_INVALID_ROW);
+		/// Returns true if the value at [col,row] is null.
+
+	void reset();
+		/// Resets the internally cached length indicators. 
+
+private:
+	static const int CHUNK_SIZE = 1024;
+		/// Amount of data retrieved in one SQLGetData() request when doing manual extract.
+
+	static const std::string FLD_SIZE_EXCEEDED_FMT;
+		/// String format for the exception message when the field size is exceeded.
+
+	void checkDataSize(std::size_t size);
+		/// This check is only performed for bound data
+		/// retrieval from variable length columns.
+		/// The reason for this check is to ensure we can
+		/// accept the value ODBC driver is supplying
+		/// (i.e. the bound buffer is large enough to receive
+		/// the returned value)
+
+	void resizeLengths(std::size_t pos);
+		/// Resizes the vector holding extracted data lengths to the
+		/// appropriate size.
+
+	template<typename T>
+	bool extractBoundImpl(std::size_t pos, T& val)
+	{
+		if (isNull(pos)) return false;
+		poco_assert_dbg (typeid(T) == _pPreparator->at(pos).type());
+		val = *AnyCast<T>(&_pPreparator->at(pos)); 
+		return true;
+	}
+
+	bool extractBoundImpl(std::size_t pos, Poco::Data::BLOB& val);
+	bool extractBoundImpl(std::size_t pos, Poco::Data::CLOB& val);
+
+	template <typename C>
+	bool extractBoundImplContainer(std::size_t pos, C& val)
+	{
+		typedef typename C::value_type Type;
+		poco_assert_dbg (typeid(std::vector<Type>) == _pPreparator->at(pos).type());
+		std::vector<Type>& v = RefAnyCast<std::vector<Type> >(_pPreparator->at(pos));
+		val.assign(v.begin(), v.end());
+		return true;
+	}
+
+	bool extractBoundImplContainer(std::size_t pos, std::vector<std::string>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::deque<std::string>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::list<std::string>& values); 
+	bool extractBoundImplContainer(std::size_t pos, std::vector<Poco::UTF16String>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::deque<Poco::UTF16String>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::list<Poco::UTF16String>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::vector<Poco::Data::CLOB>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::deque<Poco::Data::CLOB>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::list<Poco::Data::CLOB>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::vector<Poco::Data::BLOB>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::deque<Poco::Data::BLOB>& values);
+	bool extractBoundImplContainer(std::size_t pos, std::list<Poco::Data::BLOB>& values);
+
+	template <typename C>
+	bool extractBoundImplContainerString(std::size_t pos, C& values)
+	{
+		typedef typename C::value_type StringType;
+		typedef typename C::iterator ItType;
+		typedef typename StringType::value_type CharType;
+
+		CharType** pc = AnyCast<CharType*>(&(_pPreparator->at(pos)));
+		poco_assert_dbg (pc);
+		poco_assert_dbg (_pPreparator->bulkSize() == values.size());
+		std::size_t colWidth = columnSize(pos);
+		ItType it = values.begin();
+		ItType end = values.end();
+		for (int row = 0; it != end; ++it, ++row)
+		{
+			it->assign(*pc + row * colWidth / sizeof(CharType), _pPreparator->actualDataSize(pos, row));
+			// clean up superfluous null chars returned by some drivers
+			typename StringType::size_type trimLen = 0;
+			typename StringType::reverse_iterator sIt = it->rbegin();
+			typename StringType::reverse_iterator sEnd = it->rend();
+			for (; sIt != sEnd; ++sIt)
+			{
+				if (*sIt == '\0') ++trimLen;
+				else break;
+			}
+			if (trimLen) it->assign(it->begin(), it->begin() + it->length() - trimLen);
+		}
+
+		return true;
+	}
+
+	template <typename C>
+	bool extractBoundImplContainerLOB(std::size_t pos, C& values)
+	{
+		typedef typename C::value_type LOBType;
+		typedef typename LOBType::ValueType CharType;
+		typedef typename C::iterator ItType;
+
+		CharType** pc = AnyCast<CharType*>(&(_pPreparator->at(pos)));
+		poco_assert_dbg (pc);
+		poco_assert_dbg (_pPreparator->bulkSize() == values.size());
+		std::size_t colWidth = _pPreparator->maxDataSize(pos);
+		ItType it = values.begin();
+		ItType end = values.end();
+		for (int row = 0; it != end; ++it, ++row)
+			it->assignRaw(*pc + row * colWidth, _pPreparator->actualDataSize(pos, row));
+
+		return true;
+	}
+
+	template<typename T>
+	bool extractBoundImplLOB(std::size_t pos, Poco::Data::LOB<T>& val)
+	{
+		if (isNull(pos)) return false;
+
+		std::size_t dataSize = _pPreparator->actualDataSize(pos);
+		checkDataSize(dataSize);
+		T* sp = AnyCast<T*>(_pPreparator->at(pos));
+		val.assignRaw(sp, dataSize);
+
+		return true;
+	}
+
+	template<typename T>
+	bool extractManualImpl(std::size_t pos, T& val, SQLSMALLINT cType)
+	{
+		SQLRETURN rc = 0;
+		T value = (T) 0;
+
+		resizeLengths(pos);
+
+		rc = SQLGetData(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			cType,  //C data type
+			&value, //returned value
+			0,      //buffer length (ignored)
+			&_lengths[pos]);  //length indicator
+
+		if (Utility::isError(rc))
+			throw StatementException(_rStmt, "SQLGetData()");
+		
+		if (isNullLengthIndicator(_lengths[pos])) 
+			return false;
+		else 
+		{
+			//for fixed-length data, buffer must be large enough
+			//otherwise, driver may write past the end
+			poco_assert_dbg (_lengths[pos] <= sizeof(T));
+			val = value;
+		}
+
+		return true;
+	}
+
+	template <typename T, typename NT>
+	bool extAny(std::size_t pos, T& val)
+	{
+		NT i;
+		if (extract(pos, i))
+		{
+			val = i;
+			return true;
+		}
+		else
+		{
+			val = Nullable<NT>();
+			return false;
+		}
+	}
+
+	template <typename T>
+	bool extractImpl(std::size_t pos, T& val)
+		/// Utility function for extraction of Any and DynamicAny.
+	{
+		ODBCMetaColumn column(_rStmt, pos);
+
+		switch (column.type())
+		{
+			case MetaColumn::FDT_INT8:
+			{ return extAny<T, Poco::Int8>(pos, val); }
+
+			case MetaColumn::FDT_UINT8:
+			{ return extAny<T, Poco::UInt8>(pos, val); }
+
+			case MetaColumn::FDT_INT16:
+			{ return extAny<T, Poco::Int16>(pos, val); }
+
+			case MetaColumn::FDT_UINT16:
+			{ return extAny<T, Poco::UInt16>(pos, val); }
+
+			case MetaColumn::FDT_INT32:
+			{ return extAny<T, Poco::Int32>(pos, val);	}
+
+			case MetaColumn::FDT_UINT32:
+			{ return extAny<T, Poco::UInt32>(pos, val); }
+
+			case MetaColumn::FDT_INT64:
+			{ return extAny<T, Poco::Int64>(pos, val); }
+
+			case MetaColumn::FDT_UINT64:
+			{ return extAny<T, Poco::UInt64>(pos, val); }
+
+			case MetaColumn::FDT_BOOL:
+			{ return extAny<T, bool>(pos, val); }
+
+			case MetaColumn::FDT_FLOAT:
+			{ return extAny<T, float>(pos, val); }
+
+			case MetaColumn::FDT_DOUBLE:
+			{ return extAny<T, double>(pos, val); }
+
+			case MetaColumn::FDT_STRING:
+			{ return extAny<T, std::string>(pos, val); }
+
+			case MetaColumn::FDT_WSTRING:
+			{ return extAny<T, Poco::UTF16String>(pos, val); }
+
+			case MetaColumn::FDT_BLOB:
+			{ return extAny<T, Poco::Data::BLOB>(pos, val); }
+
+			case MetaColumn::FDT_CLOB:
+			{ return extAny<T, Poco::Data::CLOB>(pos, val); }
+
+			case MetaColumn::FDT_DATE:
+			{ return extAny<T, Poco::Data::Date>(pos, val); }
+
+			case MetaColumn::FDT_TIME:
+			{ return extAny<T, Poco::Data::Time>(pos, val); }
+
+			case MetaColumn::FDT_TIMESTAMP:
+			{ return extAny<T, Poco::DateTime>(pos, val); }
+
+			default: 
+				throw DataFormatException("Unsupported data type.");
+		}
+
+		return false;
+	}
+
+	bool isNullLengthIndicator(SQLLEN val) const;
+		/// The reason for this utility wrapper are platforms where 
+		/// SQLLEN macro (a.k.a. SQLINTEGER) yields 64-bit value, 
+		/// while SQL_NULL_DATA (#define'd as -1 literal) remains 32-bit.
+
+	SQLINTEGER columnSize(std::size_t pos) const;
+
+	const StatementHandle&     _rStmt;
+	PreparatorPtr              _pPreparator;
+	Preparator::DataExtraction _dataExtraction;
+	std::vector<SQLLEN>        _lengths;
+};
+
+
+///
+/// inlines
+///
+
+inline bool Extractor::extractBoundImpl(std::size_t pos, Poco::Data::BLOB& val)
+{
+	return extractBoundImplLOB<BLOB::ValueType>(pos, val);
+}
+
+
+inline bool Extractor::extractBoundImpl(std::size_t pos, Poco::Data::CLOB& val)
+{
+	return extractBoundImplLOB<CLOB::ValueType>(pos, val);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::vector<std::string>& values)
+{
+	return extractBoundImplContainerString(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::deque<std::string>& values)
+{
+	return extractBoundImplContainerString(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::list<std::string>& values)
+{
+	return extractBoundImplContainerString(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::vector<Poco::UTF16String>& values)
+{
+	return extractBoundImplContainerString(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::deque<Poco::UTF16String>& values)
+{
+	return extractBoundImplContainerString(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, std::list<Poco::UTF16String>& values)
+{
+	return extractBoundImplContainerString(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, 
+	std::vector<Poco::Data::CLOB>& values)
+{
+	return extractBoundImplContainerLOB(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, 
+	std::deque<Poco::Data::CLOB>& values)
+{
+	return extractBoundImplContainerLOB(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, 
+	std::list<Poco::Data::CLOB>& values)
+{
+	return extractBoundImplContainerLOB(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, 
+	std::vector<Poco::Data::BLOB>& values)
+{
+	return extractBoundImplContainerLOB(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, 
+	std::deque<Poco::Data::BLOB>& values)
+{
+	return extractBoundImplContainerLOB(pos, values);
+}
+
+
+inline bool Extractor::extractBoundImplContainer(std::size_t pos, 
+	std::list<Poco::Data::BLOB>& values)
+{
+	return extractBoundImplContainerLOB(pos, values);
+}
+
+
+inline void Extractor::setDataExtraction(Preparator::DataExtraction ext)
+{
+	_pPreparator->setDataExtraction(_dataExtraction = ext);
+}
+
+
+inline Preparator::DataExtraction Extractor::getDataExtraction() const
+{
+	return _dataExtraction;
+}
+
+
+inline void Extractor::reset()
+{
+	_lengths.clear();
+}
+
+
+inline void Extractor::resizeLengths(std::size_t pos)
+{
+	if (pos >= _lengths.size()) 
+		_lengths.resize(pos + 1, (SQLLEN) 0);
+}
+
+
+inline bool Extractor::isNullLengthIndicator(SQLLEN val) const
+{
+	return SQL_NULL_DATA == (int) val;
+}
+
+
+inline SQLINTEGER Extractor::columnSize(std::size_t pos) const
+{
+	std::size_t size = ODBCMetaColumn(_rStmt, pos).length();
+	std::size_t maxSize = _pPreparator->maxDataSize(pos);
+	if (size > maxSize) size = maxSize;
+	return (SQLINTEGER) size;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_Extractor_INCLUDED
diff --git a/Poco/Data/ODBC/Handle.h b/Poco/Data/ODBC/Handle.h
new file mode 100644
index 0000000..962ffe6
--- /dev/null
+++ b/Poco/Data/ODBC/Handle.h
@@ -0,0 +1,116 @@
+//
+// Handle.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Handle
+//
+// Definition of Handle.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Handle_INCLUDED
+#define Data_ODBC_Handle_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/EnvironmentHandle.h"
+#include "Poco/Data/ODBC/ConnectionHandle.h"
+#include "Poco/Data/ODBC/ODBCException.h"
+#include "Poco/Data/ODBC/Utility.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+template <typename H, SQLSMALLINT handleType>
+class Handle
+/// ODBC handle class template
+{
+public:
+	Handle(const ConnectionHandle& rConnection): 
+		_rConnection(rConnection),
+		_handle(0)
+			/// Creates the Handle.
+	{
+		if (Utility::isError(SQLAllocHandle(handleType, 
+			_rConnection, 
+			&_handle))) 
+		{
+			throw ODBCException("Could not allocate statement handle.");
+		}
+	}
+
+	~Handle()
+		/// Destroys the Handle.
+	{
+		try
+		{
+#if defined(_DEBUG)
+			SQLRETURN rc = 
+#endif
+			SQLFreeHandle(handleType, _handle);
+			// N.B. Destructors should not throw, but neither do we want to
+			// leak resources. So, we throw here in debug mode if things go bad.
+			poco_assert_dbg (!Utility::isError(rc));
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	operator const H& () const
+		/// Const conversion operator into reference to native type.
+	{
+		return handle();
+	}
+
+	const H& handle() const
+		/// Returns const reference to native type.
+	{
+		return _handle;
+	}
+
+private:
+	Handle(const Handle&);
+	const Handle& operator=(const Handle&);
+
+	operator H& ()
+		/// Conversion operator into reference to native type.
+	{
+		return handle();
+	}
+
+	H& handle()
+		/// Returns reference to native type.
+	{
+		return _handle;
+	}
+
+	const ConnectionHandle& _rConnection;
+	H _handle;
+
+	friend class ODBCStatementImpl;
+};
+
+
+typedef Handle<SQLHSTMT, SQL_HANDLE_STMT> StatementHandle;
+typedef Handle<SQLHDESC, SQL_HANDLE_DESC> DescriptorHandle;
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/ODBC.h b/Poco/Data/ODBC/ODBC.h
new file mode 100644
index 0000000..647e4b8
--- /dev/null
+++ b/Poco/Data/ODBC/ODBC.h
@@ -0,0 +1,69 @@
+//
+// ODBC.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  ODBC
+//
+// Basic definitions for the Poco ODBC library.
+// This file must be the first file included by every other ODBC
+// header file.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_ODBC_INCLUDED
+#define Data_ODBC_ODBC_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the ODBC_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// ODBC_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(ODBC_EXPORTS)
+		#define ODBC_API __declspec(dllexport)
+	#else
+		#define ODBC_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(ODBC_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define ODBC_API __attribute__ ((visibility ("default")))
+	#else
+		#define ODBC_API
+	#endif
+#endif
+
+
+
+#include "Poco/Data/ODBC/Unicode.h"
+
+
+//
+// Automatically link Data library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(ODBC_EXPORTS)
+		#pragma comment(lib, "PocoDataODBC" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // ODBC_ODBC_INCLUDED
diff --git a/Poco/Data/ODBC/ODBCException.h b/Poco/Data/ODBC/ODBCException.h
new file mode 100644
index 0000000..63e5dab
--- /dev/null
+++ b/Poco/Data/ODBC/ODBCException.h
@@ -0,0 +1,150 @@
+//
+// ODBCException.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  ODBCException
+//
+// Definition of ODBCException.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_ODBCException_INCLUDED
+#define Data_ODBC_ODBCException_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/Utility.h"
+#include "Poco/Data/ODBC/Diagnostics.h"
+#include "Poco/Data/ODBC/Error.h"
+#include "Poco/Data/DataException.h"
+#include "Poco/Format.h"
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+POCO_DECLARE_EXCEPTION(ODBC_API, ODBCException, Poco::Data::DataException)
+POCO_DECLARE_EXCEPTION(ODBC_API, InsufficientStorageException, ODBCException)
+POCO_DECLARE_EXCEPTION(ODBC_API, UnknownDataLengthException, ODBCException)
+POCO_DECLARE_EXCEPTION(ODBC_API, DataTruncatedException, ODBCException)
+
+
+template <class H, SQLSMALLINT handleType>
+class HandleException: public ODBCException
+{
+public:
+	HandleException(const H& handle): _error(handle)
+		/// Creates HandleException
+	{
+		message(_error.toString());
+	}
+
+	HandleException(const H& handle, const std::string& msg): 
+		ODBCException(msg), 
+		_error(handle)
+		/// Creates HandleException
+	{
+		extendedMessage(_error.toString());
+	}							
+
+	HandleException(const H& handle, const std::string& msg, const std::string& arg): 
+		ODBCException(msg, arg), 
+		_error(handle)
+		/// Creates HandleException
+	{
+	}
+
+	HandleException(const H& handle, const std::string& msg, const Poco::Exception& exc): 
+		ODBCException(msg, exc),
+		_error(handle)
+		/// Creates HandleException
+	{
+	}
+
+	HandleException(const HandleException& exc): 
+		ODBCException(exc),
+		_error(exc._error)
+		/// Creates HandleException
+	{
+	}
+
+	~HandleException() throw()
+		/// Destroys HandleException
+	{
+	}
+
+	HandleException& operator = (const HandleException& exc)
+		/// Assignment operator
+	{
+		if (&exc != this) _error = exc._error;
+
+		return *this;
+	}
+
+	const char* name() const throw()
+		/// Returns the name of the exception
+	{
+		return "ODBC handle exception";
+	}
+
+	const char* className() const throw()
+		/// Returns the HandleException class name.
+	{
+		return typeid(*this).name();
+	}
+
+	Poco::Exception* clone() const
+		/// Clones the HandleException
+	{
+		return new HandleException(*this);
+	}
+
+	void rethrow() const
+		/// Re-throws the HandleException.
+	{
+		throw *this;
+	}
+
+	const Diagnostics<H, handleType>& diagnostics() const
+		/// Returns error diagnostics.
+	{
+		return _error.diagnostics();
+	}
+
+	std::string toString() const
+		/// Returns the formatted error diagnostics for the handle.
+	{
+		return Poco::format("ODBC Error: %s\n===================\n%s\n",
+			std::string(what()),
+			_error.toString());
+	}
+
+	static std::string errorString(const H& handle)
+		/// Returns the error diagnostics string for the handle.
+	{
+		return Error<H, handleType>(handle).toString();
+	}
+
+private:
+	Error<H, handleType> _error;
+};
+
+
+typedef HandleException<SQLHENV, SQL_HANDLE_ENV>   EnvironmentException;
+typedef HandleException<SQLHDBC, SQL_HANDLE_DBC>   ConnectionException;
+typedef HandleException<SQLHSTMT, SQL_HANDLE_STMT> StatementException;
+typedef HandleException<SQLHDESC, SQL_HANDLE_DESC> DescriptorException;
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/ODBCMetaColumn.h b/Poco/Data/ODBC/ODBCMetaColumn.h
new file mode 100644
index 0000000..cc9df6d
--- /dev/null
+++ b/Poco/Data/ODBC/ODBCMetaColumn.h
@@ -0,0 +1,92 @@
+//
+// ODBCMetaColumn.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  ODBCMetaColumn
+//
+// Definition of ODBCMetaColumn.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_ODBCColumn_INCLUDED
+#define Data_ODBC_ODBCColumn_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/Error.h"
+#include "Poco/Data/ODBC/Handle.h"
+#include "Poco/Data/ODBC/ODBCException.h"
+#include "Poco/Data/MetaColumn.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API ODBCMetaColumn: public MetaColumn
+{
+public:
+	explicit ODBCMetaColumn(const StatementHandle& rStmt, std::size_t position);
+		/// Creates the ODBCMetaColumn.
+		
+	~ODBCMetaColumn();
+		/// Destroys the ODBCMetaColumn.
+
+	std::size_t dataLength() const;
+		/// A numeric value that is either the maximum or actual character length of a character 
+		/// string or binary data type. It is the maximum character length for a fixed-length data type, 
+		/// or the actual character length for a variable-length data type. Its value always excludes the 
+		/// null-termination byte that ends the character string. 
+		/// This information is returned from the SQL_DESC_LENGTH record field of the IRD.
+
+	bool isUnsigned() const;
+		/// Returns true if column is unsigned or a non-numeric data type.
+
+private:
+	ODBCMetaColumn();
+
+	static const int NAME_BUFFER_LENGTH = 2048;
+
+	struct ColumnDescription
+	{
+		SQLCHAR name[NAME_BUFFER_LENGTH];
+		SQLSMALLINT  nameBufferLength;
+		SQLSMALLINT  dataType;
+		SQLULEN      size;
+		SQLSMALLINT  decimalDigits;
+		SQLSMALLINT  isNullable;
+	};
+
+	void init();
+	void getDescription();
+
+	SQLLEN                 _dataLength;
+	const StatementHandle& _rStmt;
+	ColumnDescription      _columnDesc;
+};
+
+
+///
+/// inlines
+///
+inline std::size_t ODBCMetaColumn::dataLength() const
+{
+	return _dataLength;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/ODBCStatementImpl.h b/Poco/Data/ODBC/ODBCStatementImpl.h
new file mode 100644
index 0000000..c4f8b3f
--- /dev/null
+++ b/Poco/Data/ODBC/ODBCStatementImpl.h
@@ -0,0 +1,206 @@
+//
+// ODBCStatementImpl.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  ODBCStatementImpl
+//
+// Definition of the ODBCStatementImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_ODBCStatementImpl_INCLUDED
+#define Data_ODBC_ODBCStatementImpl_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/SessionImpl.h"
+#include "Poco/Data/ODBC/Binder.h"
+#include "Poco/Data/ODBC/Extractor.h"
+#include "Poco/Data/ODBC/Preparator.h"
+#include "Poco/Data/ODBC/ODBCMetaColumn.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/Data/Column.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Format.h"
+#include <sstream>
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API ODBCStatementImpl: public Poco::Data::StatementImpl
+	/// Implements statement functionality needed for ODBC
+{
+public:
+	ODBCStatementImpl(SessionImpl& rSession);
+		/// Creates the ODBCStatementImpl.
+
+	~ODBCStatementImpl();
+		/// Destroys the ODBCStatementImpl.
+
+protected:
+	std::size_t columnsReturned() const;
+		/// Returns number of columns returned by query.
+
+	int affectedRowCount() const;
+		/// Returns the number of affected rows.
+		/// Used to find out the number of rows affected by insert or update.
+
+	const MetaColumn& metaColumn(std::size_t pos) const;
+		/// Returns column meta data.
+
+	bool hasNext();
+		/// Returns true if a call to next() will return data.
+
+	std::size_t next();
+		/// Retrieves the next row or set of rows from the resultset.
+		/// Returns the number of rows retrieved.
+		/// Will throw, if the resultset is empty.
+
+	bool canBind() const;
+		/// Returns true if a valid statement is set and we can bind.
+
+	bool canCompile() const;
+		/// Returns true if another compile is possible.
+
+	void compileImpl();
+		/// Compiles the statement, doesn't bind yet. 
+		/// Does nothing if the statement has already been compiled.
+
+	void bindImpl();
+		/// Binds all parameters and executes the statement.
+
+	AbstractExtraction::ExtractorPtr extractor();
+		/// Returns the concrete extractor used by the statement.
+
+	AbstractBinding::BinderPtr binder();
+		/// Returns the concrete binder used by the statement.
+
+	std::string nativeSQL();
+		/// Returns the SQL string as modified by the driver.
+
+private:
+	typedef Poco::Data::AbstractBindingVec    Bindings;
+	typedef Poco::SharedPtr<Binder>           BinderPtr;
+	typedef Poco::Data::AbstractExtractionVec Extractions;
+	typedef Poco::SharedPtr<Preparator>       PreparatorPtr;
+	typedef std::vector<PreparatorPtr>        PreparatorVec;
+	typedef Poco::SharedPtr<Extractor>        ExtractorPtr;
+	typedef std::vector<ExtractorPtr>         ExtractorVec;
+	typedef std::vector<ODBCMetaColumn*>      ColumnPtrVec;
+	typedef std::vector<ColumnPtrVec>         ColumnPtrVecVec;
+	
+	static const std::string INVALID_CURSOR_STATE;
+
+	void clear();
+		/// Closes the cursor and resets indicator variables.
+	
+	void doBind();
+		/// Binds parameters.
+
+	void makeInternalExtractors();
+		/// Creates internal extractors if none were supplied from the user.
+
+	bool isStoredProcedure() const;
+		/// Returns true if SQL is a stored procedure call.
+
+	void doPrepare();
+		/// Prepares placeholders for data returned by statement.
+		/// It is called during statement compilation for SQL statements
+		/// returning data. For stored procedures returning datasets, 
+		/// it is called upon the first check for data availability 
+		/// (see hasNext() function).
+
+	bool hasData() const;
+		/// Returns true if statement returns data.
+
+	void makeStep();
+		/// Fetches the next row of data.
+
+	bool nextRowReady() const;
+		/// Returns true if there is a row fetched but not yet extracted.
+
+	void putData();
+		/// Called whenever SQLExecute returns SQL_NEED_DATA. This is expected 
+		/// behavior for PB_AT_EXEC binding mode. 
+
+	void getData();
+
+	void addPreparator();
+	void fillColumns();
+	void checkError(SQLRETURN rc, const std::string& msg="");
+
+	const SQLHDBC&        _rConnection;
+	const StatementHandle _stmt;
+	PreparatorVec         _preparations;
+	BinderPtr             _pBinder;
+	ExtractorVec          _extractors;
+	bool                  _stepCalled;
+	int                   _nextResponse;
+	ColumnPtrVecVec       _columnPtrs;
+	bool                  _prepared;
+	mutable std::size_t   _affectedRowCount;
+	bool                  _canCompile;
+};
+
+
+//
+// inlines
+//
+inline AbstractExtraction::ExtractorPtr ODBCStatementImpl::extractor()
+{
+	poco_assert_dbg (currentDataSet() < _extractors.size());
+	poco_assert_dbg (_extractors[currentDataSet()]);
+	return _extractors[currentDataSet()];
+}
+
+
+inline AbstractBinding::BinderPtr ODBCStatementImpl::binder()
+{
+	poco_assert_dbg (!_pBinder.isNull());
+	return _pBinder;
+}
+
+
+inline std::size_t ODBCStatementImpl::columnsReturned() const
+{
+	poco_assert_dbg (currentDataSet() < _preparations.size());
+	poco_assert_dbg (_preparations[currentDataSet()]);
+	return static_cast<std::size_t>(_preparations[currentDataSet()]->columns());
+}
+
+
+inline bool ODBCStatementImpl::hasData() const
+{
+	return (columnsReturned() > 0);
+}
+
+
+inline bool ODBCStatementImpl::nextRowReady() const
+{
+	return (!Utility::isError(_nextResponse));
+}
+
+
+inline bool ODBCStatementImpl::canCompile() const
+{
+	return _canCompile;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_ODBCStatementImpl_INCLUDED
diff --git a/Poco/Data/ODBC/Parameter.h b/Poco/Data/ODBC/Parameter.h
new file mode 100644
index 0000000..e9f11bd
--- /dev/null
+++ b/Poco/Data/ODBC/Parameter.h
@@ -0,0 +1,111 @@
+//
+// Parameter.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Parameter
+//
+// Definition of Parameter.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Parameter_INCLUDED
+#define Data_ODBC_Parameter_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/Handle.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API Parameter
+{
+public:
+	explicit Parameter(const StatementHandle& rStmt, std::size_t colNum);
+		/// Creates the Parameter.
+		
+	~Parameter();
+		/// Destroys the Parameter.
+
+	std::size_t number() const;
+		/// Returns the column number.
+
+	std::size_t dataType() const;
+		/// Returns the SQL data type.
+
+	std::size_t columnSize() const;
+		/// Returns the the size of the column or expression of the corresponding 
+		/// parameter marker as defined by the data source.
+
+	std::size_t decimalDigits() const;
+		/// Returns the number of decimal digits of the column or expression 
+		/// of the corresponding parameter as defined by the data source.
+
+	bool isNullable() const;
+		/// Returns true if column allows null values, false otherwise.
+
+private:
+	Parameter();
+
+	void init();
+
+	SQLSMALLINT _dataType;
+    SQLULEN     _columnSize;
+    SQLSMALLINT _decimalDigits;
+    SQLSMALLINT _isNullable;
+
+	const StatementHandle& _rStmt;
+	std::size_t _number;
+};
+
+
+///
+/// inlines
+///
+inline std::size_t Parameter::number() const
+{
+	return _number;
+}
+
+
+inline std::size_t Parameter::dataType() const
+{
+	return _dataType;
+}
+
+
+inline std::size_t Parameter::columnSize() const
+{
+	return _columnSize;
+}
+
+
+inline std::size_t Parameter::decimalDigits() const
+{
+	return _decimalDigits;
+}
+
+
+inline bool Parameter::isNullable() const
+{
+	return SQL_NULLABLE == _isNullable;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/Preparator.h b/Poco/Data/ODBC/Preparator.h
new file mode 100644
index 0000000..aa38ea2
--- /dev/null
+++ b/Poco/Data/ODBC/Preparator.h
@@ -0,0 +1,1271 @@
+//
+// Preparator.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Preparator
+//
+// Definition of the Preparator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Preparator_INCLUDED
+#define Data_ODBC_Preparator_INCLUDED
+
+
+#include "Poco/Data/Constants.h"
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/Handle.h"
+#include "Poco/Data/ODBC/ODBCMetaColumn.h"
+#include "Poco/Data/ODBC/Utility.h"
+#include "Poco/Data/AbstractPreparator.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/Any.h"
+#include "Poco/DynamicAny.h"
+#include "Poco/DateTime.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/UTFString.h"
+#include <vector>
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Date;
+class Time;
+
+
+namespace ODBC {
+
+
+class ODBC_API Preparator : public AbstractPreparator
+	/// Class used for database preparation where we first have to register all data types 
+	/// with respective memory output locations before extracting data. 
+	/// Extraction works in two-phases: first prepare is called once, then extract n-times.
+	/// In ODBC, SQLBindCol/SQLFetch is the preferred method of data retrieval (SQLGetData is available, 
+	/// however with numerous driver implementation dependent limitations and inferior performance). 
+	/// In order to fit this functionality into Poco DataConnectors framework, every ODBC SQL statement 
+	/// instantiates its own Preparator object. 
+	/// This is done once per statement execution (from StatementImpl::bindImpl()).
+	///
+	/// Preparator object is used to :
+	///
+	///   1) Prepare SQL statement.
+	///   2) Provide and contain the memory locations where retrieved values are placed during recordset iteration.
+	///   3) Keep count of returned number of columns with their respective datatypes and sizes.
+	///
+	/// Notes:
+	///
+	/// - Value datatypes in this interface prepare() calls serve only for the purpose of type distinction.
+	/// - Preparator keeps its own std::vector<Any> buffer for fetched data to be later retrieved by Extractor.
+	/// - prepare() methods should not be called when extraction mode is DE_MANUAL
+	/// 
+{
+public:
+	typedef std::vector<char*> CharArray;
+	typedef SharedPtr<Preparator> Ptr;
+
+	enum DataExtraction
+	{
+		DE_MANUAL,
+		DE_BOUND
+	};
+
+	enum DataType
+	{
+		DT_BOOL,
+		DT_BOOL_ARRAY,
+		DT_CHAR,
+		DT_WCHAR,
+		DT_UCHAR,
+		DT_CHAR_ARRAY,
+		DT_WCHAR_ARRAY,
+		DT_UCHAR_ARRAY,
+		DT_DATE,
+		DT_TIME,
+		DT_DATETIME
+	};
+
+	Preparator(const StatementHandle& rStmt, 
+		const std::string& statement, 
+		std::size_t maxFieldSize,
+		DataExtraction dataExtraction = DE_BOUND);
+		/// Creates the Preparator.
+
+	Preparator(const Preparator& other);
+		/// Copy constructs the Preparator.
+
+	~Preparator();
+		/// Destroys the Preparator.
+
+	void prepare(std::size_t pos, const Poco::Int8& val);
+		/// Prepares an Int8.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Int8>& val);
+		/// Prepares an Int8 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Int8>& val);
+		/// Prepares an Int8 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Int8>& val);
+		/// Prepares an Int8 list.
+
+	void prepare(std::size_t pos, const Poco::UInt8& val);
+		/// Prepares an UInt8.
+
+	void prepare(std::size_t pos, const std::vector<Poco::UInt8>& val);
+		/// Prepares an UInt8 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::UInt8>& val);
+		/// Prepares an UInt8 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::UInt8>& val);
+		/// Prepares an UInt8 list.
+
+	void prepare(std::size_t pos, const Poco::Int16& val);
+		/// Prepares an Int16.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Int16>& val);
+		/// Prepares an Int16 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Int16>& val);
+		/// Prepares an Int16 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Int16>& val);
+		/// Prepares an Int16 list.
+
+	void prepare(std::size_t pos, const Poco::UInt16& val);
+		/// Prepares an UInt16.
+
+	void prepare(std::size_t pos, const std::vector<Poco::UInt16>& val);
+		/// Prepares an UInt16 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::UInt16>& val);
+		/// Prepares an UInt16 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::UInt16>& val);
+		/// Prepares an UInt16 list.
+
+	void prepare(std::size_t pos, const Poco::Int32& val);
+		/// Prepares an Int32.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Int32>& val);
+		/// Prepares an Int32 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Int32>& val);
+		/// Prepares an Int32 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Int32>& val);
+		/// Prepares an Int32 list.
+
+	void prepare(std::size_t pos, const Poco::UInt32& val);
+		/// Prepares an UInt32.
+
+	void prepare(std::size_t pos, const std::vector<Poco::UInt32>& val);
+		/// Prepares an UInt32 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::UInt32>& val);
+		/// Prepares an UInt32 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::UInt32>& val);
+		/// Prepares an UInt32 list.
+
+	void prepare(std::size_t pos, const Poco::Int64& val);
+		/// Prepares an Int64.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Int64>& val);
+		/// Prepares an Int64 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Int64>& val);
+		/// Prepares an Int64 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Int64>& val);
+		/// Prepares an Int64 list.
+
+	void prepare(std::size_t pos, const Poco::UInt64& val);
+		/// Prepares an UInt64.
+
+	void prepare(std::size_t pos, const std::vector<Poco::UInt64>& val);
+		/// Prepares an UInt64 vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::UInt64>& val);
+		/// Prepares an UInt64 deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::UInt64>& val);
+		/// Prepares an UInt64 list.
+
+#ifndef POCO_LONG_IS_64_BIT
+	void prepare(std::size_t pos, const long& val);
+		/// Prepares a long.
+
+	void prepare(std::size_t pos, const unsigned long& val);
+		/// Prepares an unsigned long.
+
+	void prepare(std::size_t pos, const std::vector<long>& val);
+		/// Prepares a long vector.
+
+	void prepare(std::size_t pos, const std::deque<long>& val);
+		/// Prepares a long deque.
+
+	void prepare(std::size_t pos, const std::list<long>& val);
+		/// Prepares a long list.
+#endif
+
+	void prepare(std::size_t pos, const bool& val);
+		/// Prepares a boolean.
+
+	void prepare(std::size_t pos, const std::vector<bool>& val);
+		/// Prepares a boolean vector.
+
+	void prepare(std::size_t pos, const std::deque<bool>& val);
+		/// Prepares a boolean deque.
+
+	void prepare(std::size_t pos, const std::list<bool>& val);
+		/// Prepares a boolean list.
+
+	void prepare(std::size_t pos, const float& val);
+		/// Prepares a float.
+
+	void prepare(std::size_t pos, const std::vector<float>& val);
+		/// Prepares a float vector.
+
+	void prepare(std::size_t pos, const std::deque<float>& val);
+		/// Prepares a float deque.
+
+	void prepare(std::size_t pos, const std::list<float>& val);
+		/// Prepares a float list.
+
+	void prepare(std::size_t pos, const double& val);
+		/// Prepares a double.
+
+	void prepare(std::size_t pos, const std::vector<double>& val);
+		/// Prepares a double vector.
+
+	void prepare(std::size_t pos, const std::deque<double>& val);
+		/// Prepares a double deque.
+
+	void prepare(std::size_t pos, const std::list<double>& val);
+		/// Prepares a double list.
+
+	void prepare(std::size_t pos, const char& val);
+		/// Prepares a single character.
+
+	void prepare(std::size_t pos, const std::vector<char>& val);
+		/// Prepares a single character vector.
+
+	void prepare(std::size_t pos, const std::deque<char>& val);
+		/// Prepares a single character deque.
+
+	void prepare(std::size_t pos, const std::list<char>& val);
+		/// Prepares a single character list.
+
+	void prepare(std::size_t pos, const std::string& val);
+		/// Prepares a string.
+
+	void prepare(std::size_t pos, const std::vector<std::string>& val);
+		/// Prepares a string vector.
+
+	void prepare(std::size_t pos, const std::deque<std::string>& val);
+		/// Prepares a string deque.
+
+	void prepare(std::size_t pos, const std::list<std::string>& val);
+		/// Prepares a string list.
+
+	void prepare(std::size_t pos, const UTF16String& val);
+	/// Prepares a string.
+
+	void prepare(std::size_t pos, const std::vector<UTF16String>& val);
+	/// Prepares a string vector.
+
+	void prepare(std::size_t pos, const std::deque<UTF16String>& val);
+	/// Prepares a string deque.
+
+	void prepare(std::size_t pos, const std::list<UTF16String>& val);
+	/// Prepares a string list.
+
+	void prepare(std::size_t pos, const Poco::Data::BLOB& val);
+		/// Prepares a BLOB.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Data::BLOB>& val);
+		/// Prepares a BLOB vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Data::BLOB>& val);
+		/// Prepares a BLOB deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Data::BLOB>& val);
+		/// Prepares a BLOB list.
+
+	void prepare(std::size_t pos, const Poco::Data::CLOB& val);
+		/// Prepares a CLOB.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Data::CLOB>& val);
+		/// Prepares a CLOB vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Data::CLOB>& val);
+		/// Prepares a CLOB deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Data::CLOB>& val);
+		/// Prepares a CLOB list.
+
+	void prepare(std::size_t pos, const Poco::Data::Date& val);
+		/// Prepares a Date.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Data::Date>& val);
+		/// Prepares a Date vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Data::Date>& val);
+		/// Prepares a Date deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Data::Date>& val);
+		/// Prepares a Date list.
+
+	void prepare(std::size_t pos, const Poco::Data::Time& val);
+		/// Prepares a Time.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Data::Time>& val);
+		/// Prepares a Time vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Data::Time>& val);
+		/// Prepares a Time deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Data::Time>& val);
+		/// Prepares a Time list.
+
+	void prepare(std::size_t pos, const Poco::DateTime& val);
+		/// Prepares a DateTime.
+
+	void prepare(std::size_t pos, const std::vector<Poco::DateTime>& val);
+		/// Prepares a DateTime vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::DateTime>& val);
+		/// Prepares a DateTime deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::DateTime>& val);
+		/// Prepares a DateTime list.
+
+	void prepare(std::size_t pos, const Poco::Any& val);
+		/// Prepares an Any.
+
+	void prepare(std::size_t pos, const std::vector<Poco::Any>& val);
+		/// Prepares an Any vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::Any>& val);
+		/// Prepares an Any deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::Any>& val);
+		/// Prepares an Any list.
+
+	void prepare(std::size_t pos, const Poco::DynamicAny& val);
+		/// Prepares a DynamicAny.
+
+	void prepare(std::size_t pos, const std::vector<Poco::DynamicAny>& val);
+		/// Prepares a DynamicAny vector.
+
+	void prepare(std::size_t pos, const std::deque<Poco::DynamicAny>& val);
+		/// Prepares a DynamicAny deque.
+
+	void prepare(std::size_t pos, const std::list<Poco::DynamicAny>& val);
+		/// Prepares a DynamicAny list.
+
+	std::size_t columns() const;
+		/// Returns the number of columns.
+		/// Resizes the internal storage iff the size is zero.
+
+	Poco::Any& operator [] (std::size_t pos);
+		/// Returns reference to column data.
+
+	Poco::Any& at(std::size_t pos);
+		/// Returns reference to column data.
+
+	void setMaxFieldSize(std::size_t size);
+		/// Sets maximum supported field size.
+
+	std::size_t getMaxFieldSize() const;
+		// Returns maximum supported field size.
+
+	std::size_t maxDataSize(std::size_t pos) const;
+		/// Returns max supported size for column at position pos.
+		/// Returned length for variable length fields is the one 
+		/// supported by this implementation, not the underlying DB.
+
+	std::size_t actualDataSize(std::size_t col, std::size_t row = POCO_DATA_INVALID_ROW) const;
+		/// Returns the returned length for the column and row specified. 
+		/// This is usually equal to the column size, except for 
+		/// variable length fields (BLOB and variable length strings).
+		/// For null values, the return value is -1 (SQL_NO_DATA)
+
+	std::size_t bulkSize(std::size_t col = 0) const;
+		/// Returns bulk size. Column argument is optional
+		/// since all columns must be the same size.
+
+	void setDataExtraction(DataExtraction ext);
+		/// Set data extraction mode.
+
+	DataExtraction getDataExtraction() const;
+		/// Returns data extraction mode.
+
+private:
+	typedef std::vector<Poco::Any> ValueVec;
+	typedef std::vector<SQLLEN>    LengthVec;
+	typedef std::vector<LengthVec> LengthLengthVec;
+	typedef std::map<std::size_t, DataType> IndexMap;
+
+	Preparator();
+	Preparator& operator = (const Preparator&);
+
+	template <typename C>
+	void prepareImpl(std::size_t pos, const C* pVal = 0)
+		/// Utility function to prepare Any and DynamicAny.
+	{
+		ODBCMetaColumn col(_rStmt, pos);
+
+		switch (col.type())
+		{
+			case MetaColumn::FDT_INT8:
+				if (pVal)
+					return prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT, pVal->size());
+				else
+					return prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT); 
+
+			case MetaColumn::FDT_UINT8:
+				if (pVal)
+					return prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT, pVal->size());
+				else
+					return prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT);
+
+			case MetaColumn::FDT_INT16:
+				if (pVal)
+					return prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT, pVal->size());
+				else
+					return prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT);
+
+			case MetaColumn::FDT_UINT16:
+				if (pVal)
+					return prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT, pVal->size());
+				else
+					return prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT);
+
+			case MetaColumn::FDT_INT32:
+				if (pVal)
+					return prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG, pVal->size());
+				else
+					return prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG);
+
+			case MetaColumn::FDT_UINT32:
+				if (pVal)
+					return prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG, pVal->size());
+				else
+					return prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG);
+
+			case MetaColumn::FDT_INT64:
+				if (pVal)
+					return prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT, pVal->size());
+				else
+					return prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT);
+
+			case MetaColumn::FDT_UINT64:
+				if (pVal)
+					return prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT, pVal->size());
+				else
+					return prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT);
+
+			case MetaColumn::FDT_BOOL:
+				if (pVal)
+					return prepareBoolArray(pos, SQL_C_BIT, pVal->size());
+				else
+					return prepareFixedSize<bool>(pos, SQL_C_BIT);
+
+			case MetaColumn::FDT_FLOAT:
+				if (pVal)
+					return prepareFixedSize<float>(pos, SQL_C_FLOAT, pVal->size());
+				else
+					return prepareFixedSize<float>(pos, SQL_C_FLOAT);
+
+			case MetaColumn::FDT_DOUBLE:
+				if (pVal)
+					return prepareFixedSize<double>(pos, SQL_C_DOUBLE, pVal->size());
+				else
+					return prepareFixedSize<double>(pos, SQL_C_DOUBLE);
+
+			case MetaColumn::FDT_STRING:
+				if (pVal)
+					return prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_CHAR, maxDataSize(pos), pVal->size());
+				else
+					return prepareVariableLen<char>(pos, SQL_C_CHAR, maxDataSize(pos), DT_CHAR);
+
+			case MetaColumn::FDT_WSTRING:
+			{
+				typedef UTF16String::value_type CharType;
+				if (pVal)
+					return prepareCharArray<CharType, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), pVal->size());
+				else
+					return prepareVariableLen<CharType>(pos, SQL_C_WCHAR, maxDataSize(pos), DT_WCHAR);
+			}
+
+			case MetaColumn::FDT_BLOB:
+			{
+				typedef Poco::Data::BLOB::ValueType CharType;
+				if (pVal)
+					return prepareCharArray<CharType, DT_UCHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), pVal->size());
+				else
+					return prepareVariableLen<CharType>(pos, SQL_C_BINARY, maxDataSize(pos), DT_UCHAR);
+			}
+
+			case MetaColumn::FDT_CLOB:
+			{
+				typedef Poco::Data::CLOB::ValueType CharType;
+				if (pVal)
+					return prepareCharArray<CharType, DT_CHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), pVal->size());
+				else
+					return prepareVariableLen<CharType>(pos, SQL_C_BINARY, maxDataSize(pos), DT_CHAR);
+			}
+
+			case MetaColumn::FDT_DATE:
+				if (pVal)
+					return prepareFixedSize<Date>(pos, SQL_C_TYPE_DATE, pVal->size());
+				else
+					return prepareFixedSize<Date>(pos, SQL_C_TYPE_DATE);
+
+			case MetaColumn::FDT_TIME:
+				if (pVal)
+					return prepareFixedSize<Time>(pos, SQL_C_TYPE_TIME, pVal->size());
+				else
+					return prepareFixedSize<Time>(pos, SQL_C_TYPE_TIME);
+
+			case MetaColumn::FDT_TIMESTAMP:
+				if (pVal)
+					return prepareFixedSize<DateTime>(pos, SQL_C_TYPE_TIMESTAMP, pVal->size());
+				else
+					return prepareFixedSize<DateTime>(pos, SQL_C_TYPE_TIMESTAMP);
+
+			default: 
+				throw DataFormatException("Unsupported data type.");
+		}
+	}
+
+	void resize() const;
+		/// Resize the values and lengths vectors.
+
+	template <typename T>
+	void prepareFixedSize(std::size_t pos, SQLSMALLINT valueType)
+		/// Utility function for preparation of fixed length columns.
+	{
+		poco_assert (DE_BOUND == _dataExtraction);
+		std::size_t dataSize = sizeof(T);
+
+		poco_assert (pos < _values.size());
+		_values[pos] = Poco::Any(T());
+
+		T* pVal = AnyCast<T>(&_values[pos]);
+		if (Utility::isError(SQLBindCol(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			valueType, 
+			(SQLPOINTER) pVal,  
+			(SQLINTEGER) dataSize, 
+			&_lengths[pos])))
+		{
+			throw StatementException(_rStmt, "SQLBindCol()");
+		}
+	}
+
+	template <typename T>
+	void prepareFixedSize(std::size_t pos, SQLSMALLINT valueType, std::size_t length)
+		/// Utility function for preparation of fixed length columns that are
+		/// bound to a std::vector.
+	{
+		poco_assert (DE_BOUND == _dataExtraction);
+		std::size_t dataSize = sizeof(T);
+
+		poco_assert (pos < _values.size());
+		poco_assert (length);
+		_values[pos] = Poco::Any(std::vector<T>());
+		_lengths[pos] = 0;
+		poco_assert (0 == _lenLengths[pos].size());
+		_lenLengths[pos].resize(length);
+
+		std::vector<T>& cache = RefAnyCast<std::vector<T> >(_values[pos]);
+		cache.resize(length);
+
+		if (Utility::isError(SQLBindCol(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			valueType, 
+			(SQLPOINTER) &cache[0], 
+			(SQLINTEGER) dataSize, 
+			&_lenLengths[pos][0])))
+		{
+			throw StatementException(_rStmt, "SQLBindCol()");
+		}
+	}
+
+	template <typename T>
+	void prepareVariableLen(std::size_t pos, SQLSMALLINT valueType, std::size_t size, DataType dt)
+		/// Utility function for preparation of variable length columns.
+	{
+		poco_assert (DE_BOUND == _dataExtraction);
+		poco_assert (pos < _values.size());
+
+		T* pCache = new T[size]; 
+		std::memset(pCache, 0, size);
+
+		_values[pos] = Any(pCache);
+		_lengths[pos] = (SQLLEN) size;
+		_varLengthArrays.insert(IndexMap::value_type(pos, dt));
+
+		if (Utility::isError(SQLBindCol(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			valueType, 
+			(SQLPOINTER) pCache, 
+			(SQLINTEGER) size*sizeof(T), 
+			&_lengths[pos])))
+		{
+			throw StatementException(_rStmt, "SQLBindCol()");
+		}
+	}
+
+	template <typename T, DataType DT>
+	void prepareCharArray(std::size_t pos, SQLSMALLINT valueType, std::size_t size, std::size_t length)
+		/// Utility function for preparation of bulk variable length character and LOB columns.
+	{
+		poco_assert_dbg (DE_BOUND == _dataExtraction);
+		poco_assert_dbg (pos < _values.size());
+		poco_assert_dbg (pos < _lengths.size());
+		poco_assert_dbg (pos < _lenLengths.size());
+
+		T* pArray = (T*) std::calloc(length * size, sizeof(T));
+
+		_values[pos] = Any(pArray);
+		_lengths[pos] = 0;
+		_lenLengths[pos].resize(length);
+		_varLengthArrays.insert(IndexMap::value_type(pos, DT));
+
+		if (Utility::isError(SQLBindCol(_rStmt, 
+			(SQLUSMALLINT) pos + 1, 
+			valueType, 
+			(SQLPOINTER) pArray, 
+			(SQLINTEGER) size, 
+			&_lenLengths[pos][0])))
+		{
+			throw StatementException(_rStmt, "SQLBindCol()");
+		}
+	}
+
+	void prepareBoolArray(std::size_t pos, SQLSMALLINT valueType, std::size_t length);
+		/// Utility function for preparation of bulk bool columns.
+
+	void freeMemory() const;
+		/// Utility function. Releases memory allocated for variable length columns.
+
+	template <typename T>
+	void deleteCachedArray(std::size_t pos) const
+	{
+		T** p = Poco::AnyCast<T*>(&_values[pos]);
+		if (p) delete [] *p;
+	}
+
+	const StatementHandle&  _rStmt;
+	mutable ValueVec        _values;
+	mutable LengthVec       _lengths;
+	mutable LengthLengthVec _lenLengths;
+	mutable IndexMap        _varLengthArrays;
+	std::size_t             _maxFieldSize;
+	DataExtraction          _dataExtraction;
+};
+
+
+//
+// inlines
+//
+inline void Preparator::prepare(std::size_t pos, const Poco::Int8&)
+{
+	prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Int8>& val)
+{
+	prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Int8>& val)
+{
+	prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Int8>& val)
+{
+	prepareFixedSize<Poco::Int8>(pos, SQL_C_STINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::UInt8&)
+{
+	prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::UInt8>& val)
+{
+	prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::UInt8>& val)
+{
+	prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::UInt8>& val)
+{
+	prepareFixedSize<Poco::UInt8>(pos, SQL_C_UTINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Int16&)
+{
+	prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Int16>& val)
+{
+	prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Int16>& val)
+{
+	prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Int16>& val)
+{
+	prepareFixedSize<Poco::Int16>(pos, SQL_C_SSHORT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::UInt16&)
+{
+	prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::UInt16>& val)
+{
+	prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::UInt16>& val)
+{
+	prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::UInt16>& val)
+{
+	prepareFixedSize<Poco::UInt16>(pos, SQL_C_USHORT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Int32&)
+{
+	prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Int32>& val)
+{
+	prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Int32>& val)
+{
+	prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Int32>& val)
+{
+	prepareFixedSize<Poco::Int32>(pos, SQL_C_SLONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::UInt32&)
+{
+	prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::UInt32>& val)
+{
+	prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::UInt32>& val)
+{
+	prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::UInt32>& val)
+{
+	prepareFixedSize<Poco::UInt32>(pos, SQL_C_ULONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Int64&)
+{
+	prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Int64>& val)
+{
+	prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Int64>& val)
+{
+	prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Int64>& val)
+{
+	prepareFixedSize<Poco::Int64>(pos, SQL_C_SBIGINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::UInt64&)
+{
+	prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::UInt64>& val)
+{
+	prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::UInt64>& val)
+{
+	prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::UInt64>& val)
+{
+	prepareFixedSize<Poco::UInt64>(pos, SQL_C_UBIGINT, val.size());
+}
+
+
+#ifndef POCO_LONG_IS_64_BIT
+inline void Preparator::prepare(std::size_t pos, const long&)
+{
+	prepareFixedSize<long>(pos, SQL_C_SLONG);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const unsigned long&)
+{
+	prepareFixedSize<long>(pos, SQL_C_SLONG);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<long>& val)
+{
+	prepareFixedSize<long>(pos, SQL_C_SLONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<long>& val)
+{
+	prepareFixedSize<long>(pos, SQL_C_SLONG, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<long>& val)
+{
+	prepareFixedSize<long>(pos, SQL_C_SLONG, val.size());
+}
+#endif
+
+
+inline void Preparator::prepare(std::size_t pos, const bool&)
+{
+	prepareFixedSize<bool>(pos, SQL_C_BIT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<bool>& val)
+{
+	prepareBoolArray(pos, SQL_C_BIT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<bool>& val)
+{
+	prepareBoolArray(pos, SQL_C_BIT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<bool>& val)
+{
+	prepareBoolArray(pos, SQL_C_BIT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const float&)
+{
+	prepareFixedSize<float>(pos, SQL_C_FLOAT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<float>& val)
+{
+	prepareFixedSize<float>(pos, SQL_C_FLOAT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<float>& val)
+{
+	prepareFixedSize<float>(pos, SQL_C_FLOAT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<float>& val)
+{
+	prepareFixedSize<float>(pos, SQL_C_FLOAT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const double&)
+{
+	prepareFixedSize<double>(pos, SQL_C_DOUBLE);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<double>& val)
+{
+	prepareFixedSize<double>(pos, SQL_C_DOUBLE, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<double>& val)
+{
+	prepareFixedSize<double>(pos, SQL_C_DOUBLE, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<double>& val)
+{
+	prepareFixedSize<double>(pos, SQL_C_DOUBLE, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const char&)
+{
+	prepareFixedSize<char>(pos, SQL_C_STINYINT);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<char>& val)
+{
+	prepareFixedSize<char>(pos, SQL_C_STINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<char>& val)
+{
+	prepareFixedSize<char>(pos, SQL_C_STINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<char>& val)
+{
+	prepareFixedSize<char>(pos, SQL_C_STINYINT, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::string&)
+{
+	prepareVariableLen<char>(pos, SQL_C_CHAR, maxDataSize(pos), DT_CHAR);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<std::string>& val)
+{
+	prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_CHAR, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<std::string>& val)
+{
+	prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_CHAR, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<std::string>& val)
+{
+	prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_CHAR, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const UTF16String&)
+{
+	prepareVariableLen<UTF16String::value_type>(pos, SQL_C_WCHAR, maxDataSize(pos), DT_WCHAR);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<UTF16String>& val)
+{
+	prepareCharArray<UTF16String::value_type, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<UTF16String>& val)
+{
+	prepareCharArray<UTF16String::value_type, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<UTF16String>& val)
+{
+	prepareCharArray<UTF16String::value_type, DT_WCHAR_ARRAY>(pos, SQL_C_WCHAR, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Data::BLOB&)
+{
+	prepareVariableLen<Poco::Data::BLOB::ValueType>(pos, SQL_C_BINARY, maxDataSize(pos), DT_UCHAR);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Data::BLOB>& val)
+{
+	prepareCharArray<char, DT_UCHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Data::BLOB>& val)
+{
+	prepareCharArray<char, DT_UCHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Data::BLOB>& val)
+{
+	prepareCharArray<char, DT_UCHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Data::CLOB&)
+{
+	prepareVariableLen<Poco::Data::CLOB::ValueType>(pos, SQL_C_BINARY, maxDataSize(pos), DT_CHAR);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Data::CLOB>& val)
+{
+	prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Data::CLOB>& val)
+{
+	prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Data::CLOB>& val)
+{
+	prepareCharArray<char, DT_CHAR_ARRAY>(pos, SQL_C_BINARY, maxDataSize(pos), val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Data::Date&)
+{
+	prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Data::Date>& val)
+{
+	prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Data::Date>& val)
+{
+	prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Data::Date>& val)
+{
+	prepareFixedSize<SQL_DATE_STRUCT>(pos, SQL_C_TYPE_DATE, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Data::Time&)
+{
+	prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Data::Time>& val)
+{
+	prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Data::Time>& val)
+{
+	prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Data::Time>& val)
+{
+	prepareFixedSize<SQL_TIME_STRUCT>(pos, SQL_C_TYPE_TIME, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::DateTime&)
+{
+	prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::DateTime>& val)
+{
+	prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::DateTime>& val)
+{
+	prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::DateTime>& val)
+{
+	prepareFixedSize<SQL_TIMESTAMP_STRUCT>(pos, SQL_C_TYPE_TIMESTAMP, val.size());
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::Any& val)
+{
+	prepareImpl<std::vector<Poco::Any> >(pos);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::Any>& val)
+{
+	prepareImpl<std::vector<Poco::Any> >(pos, &val);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::Any>& val)
+{
+	prepareImpl<std::deque<Poco::Any> >(pos, &val);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::Any>& val)
+{
+	prepareImpl<std::list<Poco::Any> >(pos, &val);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const Poco::DynamicAny& val)
+{
+	prepareImpl<std::vector<Poco::DynamicAny> >(pos);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::vector<Poco::DynamicAny>& val)
+{
+	prepareImpl<std::vector<Poco::DynamicAny> >(pos, &val);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::deque<Poco::DynamicAny>& val)
+{
+	prepareImpl<std::deque<Poco::DynamicAny> >(pos, &val);
+}
+
+
+inline void Preparator::prepare(std::size_t pos, const std::list<Poco::DynamicAny>& val)
+{
+	prepareImpl<std::list<Poco::DynamicAny> >(pos, &val);
+}
+
+
+inline std::size_t Preparator::bulkSize(std::size_t col) const
+{
+	poco_assert (col < _lenLengths.size());
+
+	return _lenLengths[col].size();
+}
+
+
+inline void Preparator::setMaxFieldSize(std::size_t size)
+{
+	_maxFieldSize = size;
+}
+
+
+inline std::size_t Preparator::getMaxFieldSize() const
+{
+	return _maxFieldSize;
+}
+
+
+inline void Preparator::setDataExtraction(Preparator::DataExtraction ext)
+{
+	_dataExtraction = ext;
+}
+
+
+inline Preparator::DataExtraction Preparator::getDataExtraction() const
+{
+	return _dataExtraction;
+}
+
+
+inline Poco::Any& Preparator::operator [] (std::size_t pos)
+{
+	return at(pos);
+}
+
+
+inline Poco::Any& Preparator::at(std::size_t pos)
+{
+	return _values.at(pos);
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_Preparator_INCLUDED
diff --git a/Poco/Data/ODBC/SessionImpl.h b/Poco/Data/ODBC/SessionImpl.h
new file mode 100644
index 0000000..72937bf
--- /dev/null
+++ b/Poco/Data/ODBC/SessionImpl.h
@@ -0,0 +1,290 @@
+//
+// SessionImpl.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  SessionImpl
+//
+// Definition of the SessionImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_SessionImpl_INCLUDED
+#define Data_ODBC_SessionImpl_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/Connector.h"
+#include "Poco/Data/ODBC/TypeInfo.h"
+#include "Poco/Data/ODBC/Binder.h"
+#include "Poco/Data/ODBC/Handle.h"
+#include "Poco/Data/ODBC/ODBCException.h"
+#include "Poco/Data/AbstractSessionImpl.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Mutex.h"
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
+	/// Implements SessionImpl interface
+{
+public:
+	static const std::size_t ODBC_MAX_FIELD_SIZE = 1024u;
+
+	enum TransactionCapability
+	{
+		ODBC_TXN_CAPABILITY_UNKNOWN = -1,
+		ODBC_TXN_CAPABILITY_FALSE = 0,
+		ODBC_TXN_CAPABILITY_TRUE = 1
+	};
+
+	SessionImpl(const std::string& connect,
+		std::size_t loginTimeout,
+		std::size_t maxFieldSize = ODBC_MAX_FIELD_SIZE, 
+		bool autoBind = true,
+		bool autoExtract = true);
+		/// Creates the SessionImpl. Opens a connection to the database.
+		/// Throws NotConnectedException if connection was not succesful.
+
+	//@ deprecated
+	SessionImpl(const std::string& connect, 
+		Poco::Any maxFieldSize = ODBC_MAX_FIELD_SIZE, 
+		bool enforceCapability=false,
+		bool autoBind = true,
+		bool autoExtract = true);
+		/// Creates the SessionImpl. Opens a connection to the database.
+
+	~SessionImpl();
+		/// Destroys the SessionImpl.
+
+	Poco::Data::StatementImpl* createStatementImpl();
+		/// Returns an ODBC StatementImpl
+
+	void open(const std::string& connect = "");
+		/// Opens a connection to the Database
+
+	void close();
+		/// Closes the connection
+
+	bool isConnected();
+		/// Returns true if session is connected
+
+	void setConnectionTimeout(std::size_t timeout);
+		/// Sets the session connection timeout value.
+
+	std::size_t getConnectionTimeout();
+		/// Returns the session connection timeout value.
+
+	void begin();
+		/// Starts a transaction
+
+	void commit();
+		/// Commits and ends a transaction
+
+	void rollback();
+		/// Aborts a transaction
+
+	bool isTransaction();
+		/// Returns true iff a transaction is in progress.
+
+	const std::string& connectorName() const;
+		/// Returns the name of the connector.
+
+	bool canTransact();
+		/// Returns true if connection is transaction-capable.
+
+	void setTransactionIsolation(Poco::UInt32 ti);
+		/// Sets the transaction isolation level.
+
+	Poco::UInt32 getTransactionIsolation();
+		/// Returns the transaction isolation level.
+
+	bool hasTransactionIsolation(Poco::UInt32);
+		/// Returns true iff the transaction isolation level corresponding
+		/// to the supplied bitmask is supported.
+
+	bool isTransactionIsolation(Poco::UInt32);
+		/// Returns true iff the transaction isolation level corresponds
+		/// to the supplied bitmask.
+
+	void autoCommit(const std::string&, bool val);
+		/// Sets autocommit property for the session.
+
+	bool isAutoCommit(const std::string& name="");
+		/// Returns autocommit property value.
+
+	void autoBind(const std::string&, bool val);
+		/// Sets automatic binding for the session.
+
+	bool isAutoBind(const std::string& name="");
+		/// Returns true if binding is automatic for this session.
+
+	void autoExtract(const std::string&, bool val);
+		/// Sets automatic extraction for the session.
+
+	bool isAutoExtract(const std::string& name="");
+		/// Returns true if extraction is automatic for this session.
+
+	void setMaxFieldSize(const std::string& rName, const Poco::Any& rValue);
+		/// Sets the max field size (the default used when column size is unknown).
+		
+	Poco::Any getMaxFieldSize(const std::string& rName="");
+		/// Returns the max field size (the default used when column size is unknown).
+
+	int maxStatementLength();
+		/// Returns maximum length of SQL statement allowed by driver.
+
+	void setQueryTimeout(const std::string&, const Poco::Any& value);
+		/// Sets the timeout (in seconds) for queries.
+		/// Value must be of type int.
+		
+	Poco::Any getQueryTimeout(const std::string&);
+		/// Returns the timeout (in seconds) for queries,
+		/// or -1 if no timeout has been set.
+		
+	int queryTimeout() const;
+		/// Returns the timeout (in seconds) for queries,
+		/// or -1 if no timeout has been set.
+
+	const ConnectionHandle& dbc() const;
+		/// Returns the connection handle.
+
+	Poco::Any dataTypeInfo(const std::string& rName="");
+		/// Returns the data types information.
+
+private:
+	void setDataTypeInfo(const std::string& rName, const Poco::Any& rValue);
+		/// No-op. Throws InvalidAccessException.
+
+	static const int FUNCTIONS = SQL_API_ODBC3_ALL_FUNCTIONS_SIZE;
+
+	void checkError(SQLRETURN rc, const std::string& msg="");
+
+	Poco::UInt32 getDefaultTransactionIsolation();
+
+	Poco::UInt32 transactionIsolation(SQLULEN isolation);
+
+	std::string            _connector;
+	const ConnectionHandle _db;
+	Poco::Any              _maxFieldSize;
+	bool                   _autoBind;
+	bool                   _autoExtract;
+	TypeInfo               _dataTypes;
+	char                   _canTransact;
+	bool                   _inTransaction;
+	int                    _queryTimeout;
+	Poco::FastMutex        _mutex;
+};
+
+
+///
+/// inlines
+///
+inline void SessionImpl::checkError(SQLRETURN rc, const std::string& msg)
+{
+	if (Utility::isError(rc))
+		throw ConnectionException(_db, msg);
+}
+
+
+inline const ConnectionHandle& SessionImpl::dbc() const
+{
+	return _db;
+}
+
+
+inline void SessionImpl::setMaxFieldSize(const std::string& rName, const Poco::Any& rValue)
+{
+	_maxFieldSize = rValue;
+}
+
+		
+inline Poco::Any SessionImpl::getMaxFieldSize(const std::string& rName)
+{
+	return _maxFieldSize;
+}
+
+
+inline void SessionImpl::setDataTypeInfo(const std::string& rName, const Poco::Any& rValue)
+{
+	throw InvalidAccessException();
+}
+
+		
+inline Poco::Any SessionImpl::dataTypeInfo(const std::string& rName)
+{
+	return &_dataTypes;
+}
+
+
+inline void SessionImpl::autoBind(const std::string&, bool val)
+{
+	_autoBind = val;
+}
+
+
+inline bool SessionImpl::isAutoBind(const std::string& name)
+{
+	return _autoBind;
+}
+
+
+inline void SessionImpl::autoExtract(const std::string&, bool val)
+{
+	_autoExtract = val;
+}
+
+
+inline bool SessionImpl::isAutoExtract(const std::string& name)
+{
+	return _autoExtract;
+}
+
+
+inline const std::string& SessionImpl::connectorName() const
+{
+	return _connector;
+}
+
+
+inline bool SessionImpl::isTransactionIsolation(Poco::UInt32 ti)
+{
+	return 0 != (ti & getTransactionIsolation());
+}
+
+
+inline void SessionImpl::setQueryTimeout(const std::string&, const Poco::Any& value)
+{
+	_queryTimeout = Poco::AnyCast<int>(value);
+}
+
+
+inline Poco::Any SessionImpl::getQueryTimeout(const std::string&)
+{
+	return _queryTimeout;
+}
+
+
+inline int SessionImpl::queryTimeout() const
+{
+	return _queryTimeout;
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_SessionImpl_INCLUDED
diff --git a/Poco/Data/ODBC/TypeInfo.h b/Poco/Data/ODBC/TypeInfo.h
new file mode 100644
index 0000000..f8b14a8
--- /dev/null
+++ b/Poco/Data/ODBC/TypeInfo.h
@@ -0,0 +1,117 @@
+//
+// TypeInfo.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  TypeInfo
+//
+// Definition of TypeInfo.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_DataTypes_INCLUDED
+#define Data_ODBC_DataTypes_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/NamedTuple.h"
+#include "Poco/DynamicAny.h"
+#include <vector>
+#include <map>
+#ifdef POCO_OS_FAMILY_WINDOWS
+#include <windows.h>
+#endif
+#include <sqlext.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API TypeInfo
+	/// Datatypes mapping utility class.
+	///
+	/// This class provides mapping between C and SQL datatypes as well
+	/// as datatypes supported by the underlying database. In order for database
+	/// types to be available, a valid conection handle must be supplied at either
+	/// object construction time, or at a later point in time, through call to
+	/// fillTypeInfo member function.
+	///
+	/// Class also provides a convenient debugging function that prints
+	/// tabulated data to an output stream.
+{
+public:
+	typedef std::map<int, int> DataTypeMap;
+	typedef DataTypeMap::value_type ValueType;
+	typedef Poco::NamedTuple<std::string,
+		SQLSMALLINT,
+		SQLINTEGER,
+		std::string,
+		std::string,
+		std::string,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		std::string,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLSMALLINT,
+		SQLINTEGER,
+		SQLSMALLINT> TypeInfoTup;
+	typedef std::vector<TypeInfoTup> TypeInfoVec;
+
+	explicit TypeInfo(SQLHDBC* pHDBC=0);
+		/// Creates the TypeInfo.
+
+	~TypeInfo();
+		/// Destroys the TypeInfo.
+
+	int cDataType(int sqlDataType) const;
+		/// Returns C data type corresponding to supplied SQL data type.
+
+	int sqlDataType(int cDataType) const;
+		/// Returns SQL data type corresponding to supplied C data type.
+
+	void fillTypeInfo(SQLHDBC pHDBC);
+		/// Fills the data type info structure for the database.
+
+	DynamicAny getInfo(SQLSMALLINT type, const std::string& param) const;
+		/// Returns information about specified data type as specified by parameter 'type'.
+		/// The requested information is specified by parameter 'param'.
+		/// Will fail with a Poco::NotFoundException thrown if the param is not found
+		
+	bool tryGetInfo(SQLSMALLINT type, const std::string& param, DynamicAny& result) const;
+		/// Returns information about specified data type as specified by parameter 'type' in param result.
+		/// The requested information is specified by parameter 'param'.
+		/// Will return false if the param is not found. The value of result will be not changed in this case.
+			
+
+	void print(std::ostream& ostr);
+		/// Prints all the types (as reported by the underlying database)
+		/// to the supplied output stream.
+
+private:
+	void fillCTypes();
+	void fillSQLTypes();
+
+	DataTypeMap _cDataTypes; 
+	DataTypeMap _sqlDataTypes; 
+	TypeInfoVec _typeInfo;
+	SQLHDBC*    _pHDBC;
+};
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/ODBC/Unicode.h b/Poco/Data/ODBC/Unicode.h
new file mode 100644
index 0000000..1c5e4b3
--- /dev/null
+++ b/Poco/Data/ODBC/Unicode.h
@@ -0,0 +1,985 @@
+//
+// Unicode.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Unicode
+//
+// Definition of Unicode.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Unicode_INCLUDED
+#define Data_ODBC_Unicode_INCLUDED
+
+
+#include "Poco/UnicodeConverter.h"
+#include "Poco/Buffer.h"
+#include "Poco/Exception.h"
+#include <cstring>
+#ifdef POCO_OS_FAMILY_WINDOWS
+	#include <windows.h>
+#endif
+#ifndef SQL_NOUNICODEMAP
+	#define SQL_NOUNICODEMAP
+#endif
+#include <sqlext.h>
+#include <sqltypes.h>
+#include <sqlucode.h>
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+	#define POCO_ODBC_UNICODE
+	#define POCO_ODBC_UNICODE_WINDOWS
+#elif defined(POCO_OS_FAMILY_UNIX) && defined(UNICODE)
+	#define POCO_ODBC_UNICODE
+	#ifdef POCO_UNIXODBC
+		#define POCO_ODBC_UNICODE_UNIXODBC
+	#elif defined(POCO_IODBC)
+		#error "iODBC Unicode not supported"
+	#endif
+#endif
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+#if defined(POCO_PTR_IS_64_BIT) || defined(POCO_OS_FAMILY_UNIX) // mkrivos - POCO_OS_FAMILY_UNIX doesn't compile with SQLPOINTER & SQLColAttribute()
+	typedef SQLLEN* NumAttrPtrType;
+#else
+	typedef SQLPOINTER NumAttrPtrType;
+#endif
+
+
+SQLRETURN ODBC_API SQLColAttribute(SQLHSTMT hstmt,
+	SQLUSMALLINT   iCol,
+	SQLUSMALLINT   iField,
+	SQLPOINTER	   pCharAttr,
+	SQLSMALLINT	   cbCharAttrMax,
+	SQLSMALLINT*   pcbCharAttr,
+	NumAttrPtrType pNumAttr);
+
+
+SQLRETURN ODBC_API SQLColAttributes(SQLHSTMT hstmt,
+	SQLUSMALLINT icol,
+	SQLUSMALLINT fDescType,
+	SQLPOINTER   rgbDesc,
+	SQLSMALLINT  cbDescMax,
+	SQLSMALLINT* pcbDesc,
+	SQLLEN*      pfDesc);
+
+SQLRETURN ODBC_API SQLConnect(SQLHDBC hdbc,
+	SQLCHAR*    szDSN,
+	SQLSMALLINT cbDSN,
+	SQLCHAR*    szUID,
+	SQLSMALLINT cbUID,
+	SQLCHAR*    szAuthStr,
+	SQLSMALLINT cbAuthStr);
+
+SQLRETURN ODBC_API SQLDescribeCol(SQLHSTMT hstmt,
+	SQLUSMALLINT icol,
+	SQLCHAR*     szColName,
+	SQLSMALLINT  cbColNameMax,
+	SQLSMALLINT* pcbColName,
+	SQLSMALLINT* pfSqlType,
+	SQLULEN*     pcbColDef,
+	SQLSMALLINT* pibScale,
+	SQLSMALLINT* pfNullable);
+
+SQLRETURN ODBC_API SQLError(SQLHENV henv,
+	SQLHDBC      hdbc,
+	SQLHSTMT     hstmt,
+	SQLCHAR*     szSqlState,
+	SQLINTEGER*  pfNativeError,
+	SQLCHAR*     szErrorMsg,
+	SQLSMALLINT  cbErrorMsgMax,
+	SQLSMALLINT* pcbErrorMsg);
+
+SQLRETURN ODBC_API SQLExecDirect(SQLHSTMT hstmt,
+	SQLCHAR*   szSqlStr,
+	SQLINTEGER cbSqlStr);
+
+SQLRETURN ODBC_API SQLGetConnectAttr(SQLHDBC hdbc,
+	SQLINTEGER  fAttribute,
+	SQLPOINTER  rgbValue,
+	SQLINTEGER  cbValueMax,
+	SQLINTEGER* pcbValue);
+
+SQLRETURN ODBC_API SQLGetCursorName(SQLHSTMT hstmt,
+	SQLCHAR*     szCursor,
+	SQLSMALLINT  cbCursorMax,
+	SQLSMALLINT* pcbCursor);
+
+SQLRETURN ODBC_API SQLSetDescField(SQLHDESC DescriptorHandle,
+	SQLSMALLINT RecNumber,
+	SQLSMALLINT FieldIdentifier,
+	SQLPOINTER  Value,
+	SQLINTEGER  BufferLength);
+
+SQLRETURN ODBC_API SQLGetDescField(SQLHDESC hdesc,
+	SQLSMALLINT iRecord,
+	SQLSMALLINT iField,
+	SQLPOINTER  rgbValue,
+	SQLINTEGER	cbValueMax,
+	SQLINTEGER* pcbValue);
+
+SQLRETURN ODBC_API SQLGetDescRec(SQLHDESC hdesc,
+	SQLSMALLINT  iRecord,
+	SQLCHAR*     szName,
+	SQLSMALLINT  cbNameMax,
+	SQLSMALLINT* pcbName,
+	SQLSMALLINT* pfType,
+	SQLSMALLINT* pfSubType,
+	SQLLEN*      pLength,
+	SQLSMALLINT* pPrecision,
+	SQLSMALLINT* pScale,
+	SQLSMALLINT* pNullable);
+
+SQLRETURN ODBC_API SQLGetDiagField(SQLSMALLINT fHandleType,
+	SQLHANDLE    handle,
+	SQLSMALLINT  iRecord,
+	SQLSMALLINT  fDiagField,
+	SQLPOINTER   rgbDiagInfo,
+	SQLSMALLINT  cbDiagInfoMax,
+	SQLSMALLINT* pcbDiagInfo);
+
+SQLRETURN ODBC_API SQLGetDiagRec(SQLSMALLINT fHandleType,
+	SQLHANDLE    handle,
+	SQLSMALLINT  iRecord,
+	SQLCHAR*     szSqlState,
+	SQLINTEGER*  pfNativeError,
+	SQLCHAR*     szErrorMsg,
+	SQLSMALLINT  cbErrorMsgMax,
+	SQLSMALLINT* pcbErrorMsg);
+
+SQLRETURN ODBC_API SQLPrepare(SQLHSTMT hstmt,
+	SQLCHAR*   szSqlStr,
+	SQLINTEGER cbSqlStr);
+
+SQLRETURN ODBC_API SQLSetConnectAttr(SQLHDBC hdbc,
+	SQLINTEGER fAttribute,
+	SQLPOINTER rgbValue,
+	SQLINTEGER cbValue);
+
+SQLRETURN ODBC_API SQLSetCursorName(SQLHSTMT hstmt,
+	SQLCHAR*    szCursor,
+	SQLSMALLINT cbCursor);
+
+SQLRETURN ODBC_API SQLSetStmtAttr(SQLHSTMT hstmt,
+	SQLINTEGER fAttribute,
+	SQLPOINTER rgbValue,
+	SQLINTEGER cbValueMax);
+
+SQLRETURN ODBC_API SQLGetStmtAttr(SQLHSTMT hstmt,
+	SQLINTEGER  fAttribute,
+	SQLPOINTER  rgbValue,
+	SQLINTEGER  cbValueMax,
+	SQLINTEGER* pcbValue);
+
+SQLRETURN ODBC_API SQLColumns(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName,
+	SQLCHAR*    szColumnName,
+	SQLSMALLINT cbColumnName);
+
+SQLRETURN ODBC_API SQLGetConnectOption(SQLHDBC hdbc,
+	SQLUSMALLINT fOption,
+	SQLPOINTER   pvParam);
+
+SQLRETURN ODBC_API SQLGetInfo(SQLHDBC hdbc,
+	SQLUSMALLINT fInfoType,
+	SQLPOINTER   rgbInfoValue,
+	SQLSMALLINT  cbInfoValueMax,
+	SQLSMALLINT* pcbInfoValue);
+
+SQLRETURN ODBC_API SQLGetTypeInfo(SQLHSTMT StatementHandle,
+	SQLSMALLINT	DataType);
+
+SQLRETURN ODBC_API SQLSetConnectOption(SQLHDBC hdbc,
+	SQLUSMALLINT fOption,
+	SQLULEN      vParam);
+
+SQLRETURN ODBC_API SQLSpecialColumns(SQLHSTMT hstmt,
+	SQLUSMALLINT fColType,
+	SQLCHAR*     szCatalogName,
+	SQLSMALLINT  cbCatalogName,
+	SQLCHAR*     szSchemaName,
+	SQLSMALLINT  cbSchemaName,
+	SQLCHAR*     szTableName,
+	SQLSMALLINT  cbTableName,
+	SQLUSMALLINT fScope,
+	SQLUSMALLINT fNullable);
+
+SQLRETURN ODBC_API SQLStatistics(SQLHSTMT hstmt,
+	SQLCHAR*     szCatalogName,
+	SQLSMALLINT  cbCatalogName,
+	SQLCHAR*     szSchemaName,
+	SQLSMALLINT  cbSchemaName,
+	SQLCHAR*     szTableName,
+	SQLSMALLINT  cbTableName,
+	SQLUSMALLINT fUnique,
+	SQLUSMALLINT fAccuracy);
+
+SQLRETURN ODBC_API SQLTables(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName,
+	SQLCHAR*    szTableType,
+	SQLSMALLINT cbTableType);
+
+SQLRETURN ODBC_API SQLDataSources(SQLHENV henv,
+	SQLUSMALLINT fDirection,
+	SQLCHAR*     szDSN,
+	SQLSMALLINT  cbDSNMax,
+	SQLSMALLINT* pcbDSN,
+	SQLCHAR*     szDescription,
+	SQLSMALLINT  cbDescriptionMax,
+	SQLSMALLINT* pcbDescription);
+
+SQLRETURN ODBC_API SQLDriverConnect(SQLHDBC hdbc,
+	SQLHWND      hwnd,
+	SQLCHAR*     szConnStrIn,
+	SQLSMALLINT  cbConnStrIn,
+	SQLCHAR*     szConnStrOut,
+	SQLSMALLINT  cbConnStrOutMax,
+	SQLSMALLINT* pcbConnStrOut,
+	SQLUSMALLINT fDriverCompletion);
+
+SQLRETURN ODBC_API SQLBrowseConnect(SQLHDBC hdbc,
+	SQLCHAR*     szConnStrIn,
+	SQLSMALLINT  cbConnStrIn,
+	SQLCHAR*     szConnStrOut,
+	SQLSMALLINT  cbConnStrOutMax,
+	SQLSMALLINT* pcbConnStrOut);
+
+SQLRETURN ODBC_API SQLColumnPrivileges(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName,
+	SQLCHAR*    szColumnName,
+	SQLSMALLINT cbColumnName);
+
+SQLRETURN ODBC_API SQLForeignKeys(SQLHSTMT hstmt,
+	SQLCHAR*    szPkCatalogName,
+	SQLSMALLINT cbPkCatalogName,
+	SQLCHAR*    szPkSchemaName,
+	SQLSMALLINT cbPkSchemaName,
+	SQLCHAR*    szPkTableName,
+	SQLSMALLINT cbPkTableName,
+	SQLCHAR*    szFkCatalogName,
+	SQLSMALLINT cbFkCatalogName,
+	SQLCHAR*    szFkSchemaName,
+	SQLSMALLINT cbFkSchemaName,
+	SQLCHAR*    szFkTableName,
+	SQLSMALLINT cbFkTableName);
+
+SQLRETURN ODBC_API SQLNativeSql(SQLHDBC hdbc,
+	SQLCHAR*    szSqlStrIn,
+	SQLINTEGER  cbSqlStrIn,
+	SQLCHAR*    szSqlStr,
+	SQLINTEGER  cbSqlStrMax,
+	SQLINTEGER* pcbSqlStr);
+
+SQLRETURN ODBC_API SQLPrimaryKeys(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName);
+
+SQLRETURN ODBC_API SQLProcedureColumns(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szProcName,
+	SQLSMALLINT cbProcName,
+	SQLCHAR*    szColumnName,
+	SQLSMALLINT cbColumnName);
+
+SQLRETURN ODBC_API SQLProcedures(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szProcName,
+	SQLSMALLINT cbProcName);
+
+SQLRETURN ODBC_API SQLTablePrivileges(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName);
+
+SQLRETURN ODBC_API SQLDrivers(SQLHENV henv,
+	SQLUSMALLINT fDirection,
+	SQLCHAR*     szDriverDesc,
+	SQLSMALLINT  cbDriverDescMax,
+	SQLSMALLINT* pcbDriverDesc,
+	SQLCHAR*     szDriverAttributes,
+	SQLSMALLINT  cbDrvrAttrMax,
+	SQLSMALLINT* pcbDrvrAttr);
+
+
+///
+/// inlines
+///
+
+inline bool isString(SQLPOINTER pValue, SQLINTEGER length)
+{
+	return (SQL_NTS == length || length > 0) && pValue;
+}
+
+
+inline SQLINTEGER stringLength(SQLPOINTER pValue, SQLINTEGER length)
+{
+	if (SQL_NTS != length) return length;
+
+	return (SQLINTEGER) std::strlen((const char*) pValue);
+}
+
+
+#if !defined(POCO_ODBC_UNICODE)
+
+
+///
+/// inlines
+///
+
+inline SQLRETURN SQLColAttribute(SQLHSTMT hstmt,
+	SQLUSMALLINT   iCol,
+	SQLUSMALLINT   iField,
+	SQLPOINTER     pCharAttr,
+	SQLSMALLINT    cbCharAttrMax,
+	SQLSMALLINT*   pcbCharAttr,
+	NumAttrPtrType pNumAttr)
+{
+	return ::SQLColAttributeA(hstmt,
+		iCol,
+		iField,
+		pCharAttr,
+		cbCharAttrMax,
+		pcbCharAttr,
+		pNumAttr);
+}
+
+
+inline SQLRETURN SQLColAttributes(SQLHSTMT hstmt,
+	SQLUSMALLINT icol,
+	SQLUSMALLINT fDescType,
+	SQLPOINTER   rgbDesc,
+	SQLSMALLINT  cbDescMax,
+	SQLSMALLINT* pcbDesc,
+	SQLLEN*      pfDesc)
+{
+	return ::SQLColAttributesA(hstmt,
+		icol,
+		fDescType,
+		rgbDesc,
+		cbDescMax,
+		pcbDesc,
+		pfDesc);
+}
+
+
+inline SQLRETURN SQLConnect(SQLHDBC hdbc,
+	SQLCHAR*    szDSN,
+	SQLSMALLINT cbDSN,
+	SQLCHAR*    szUID,
+	SQLSMALLINT cbUID,
+	SQLCHAR*    szAuthStr,
+	SQLSMALLINT cbAuthStr)
+{
+	return ::SQLConnectA(hdbc,
+		szDSN,
+		cbDSN,
+		szUID,
+		cbUID,
+		szAuthStr,
+		cbAuthStr);
+}
+
+
+inline SQLRETURN SQLDescribeCol(SQLHSTMT hstmt,
+	SQLUSMALLINT icol,
+	SQLCHAR*     szColName,
+	SQLSMALLINT  cbColNameMax,
+	SQLSMALLINT* pcbColName,
+	SQLSMALLINT* pfSqlType,
+	SQLULEN*     pcbColDef,
+	SQLSMALLINT* pibScale,
+	SQLSMALLINT* pfNullable)
+{
+	return ::SQLDescribeColA(hstmt,
+		icol,
+		szColName,
+		cbColNameMax,
+		pcbColName,
+		pfSqlType,
+		pcbColDef,
+		pibScale,
+		pfNullable);
+}
+
+
+inline SQLRETURN SQLError(SQLHENV henv,
+	SQLHDBC      hdbc,
+	SQLHSTMT     hstmt,
+	SQLCHAR*     szSqlState,
+	SQLINTEGER*  pfNativeError,
+	SQLCHAR*     szErrorMsg,
+	SQLSMALLINT  cbErrorMsgMax,
+	SQLSMALLINT* pcbErrorMsg)
+{
+	throw Poco::NotImplementedException("SQLError is obsolete. "
+		"Use SQLGetDiagRec instead.");
+}
+
+
+inline SQLRETURN SQLExecDirect(SQLHSTMT hstmt,
+	SQLCHAR*   szSqlStr,
+	SQLINTEGER cbSqlStr)
+{
+	return ::SQLExecDirectA(hstmt, szSqlStr, cbSqlStr);
+}
+
+
+inline SQLRETURN SQLGetConnectAttr(SQLHDBC hdbc,
+	SQLINTEGER  fAttribute,
+	SQLPOINTER  rgbValue,
+	SQLINTEGER  cbValueMax,
+	SQLINTEGER* pcbValue)
+{
+	return ::SQLGetConnectAttrA(hdbc,
+		fAttribute,
+		rgbValue,
+		cbValueMax,
+		pcbValue);
+}
+
+
+inline SQLRETURN SQLGetCursorName(SQLHSTMT hstmt,
+	SQLCHAR*     szCursor,
+	SQLSMALLINT  cbCursorMax,
+	SQLSMALLINT* pcbCursor)
+{
+	throw Poco::NotImplementedException("Not implemented");
+}
+
+
+inline SQLRETURN SQLSetDescField(SQLHDESC DescriptorHandle,
+	SQLSMALLINT RecNumber,
+	SQLSMALLINT FieldIdentifier,
+	SQLPOINTER  Value,
+	SQLINTEGER  BufferLength)
+{
+	return ::SQLSetDescField(DescriptorHandle,
+		RecNumber,
+		FieldIdentifier,
+		Value,
+		BufferLength);
+}
+
+
+inline SQLRETURN SQLGetDescField(SQLHDESC hdesc,
+	SQLSMALLINT iRecord,
+	SQLSMALLINT iField,
+	SQLPOINTER  rgbValue,
+	SQLINTEGER	cbValueMax,
+	SQLINTEGER* pcbValue)
+{
+	return ::SQLGetDescFieldA(hdesc,
+		iRecord,
+		iField,
+		rgbValue,
+		cbValueMax,
+		pcbValue);
+}
+
+
+inline SQLRETURN SQLGetDescRec(SQLHDESC hdesc,
+	SQLSMALLINT  iRecord,
+	SQLCHAR*     szName,
+	SQLSMALLINT  cbNameMax,
+	SQLSMALLINT* pcbName,
+	SQLSMALLINT* pfType,
+	SQLSMALLINT* pfSubType,
+	SQLLEN*      pLength,
+	SQLSMALLINT* pPrecision,
+	SQLSMALLINT* pScale,
+	SQLSMALLINT* pNullable)
+{
+	return ::SQLGetDescRecA(hdesc,
+		iRecord,
+		szName,
+		cbNameMax,
+		pcbName,
+		pfType,
+		pfSubType,
+		pLength,
+		pPrecision,
+		pScale,
+		pNullable);
+}
+
+
+inline SQLRETURN SQLGetDiagField(SQLSMALLINT fHandleType,
+	SQLHANDLE    handle,
+	SQLSMALLINT  iRecord,
+	SQLSMALLINT  fDiagField,
+	SQLPOINTER   rgbDiagInfo,
+	SQLSMALLINT  cbDiagInfoMax,
+	SQLSMALLINT* pcbDiagInfo)
+{
+	return ::SQLGetDiagFieldA(fHandleType,
+		handle,
+		iRecord,
+		fDiagField,
+		rgbDiagInfo,
+		cbDiagInfoMax,
+		pcbDiagInfo);
+}
+
+
+inline SQLRETURN SQLGetDiagRec(SQLSMALLINT fHandleType,
+	SQLHANDLE    handle,
+	SQLSMALLINT  iRecord,
+	SQLCHAR*     szSqlState,
+	SQLINTEGER*  pfNativeError,
+	SQLCHAR*     szErrorMsg,
+	SQLSMALLINT  cbErrorMsgMax,
+	SQLSMALLINT* pcbErrorMsg)
+{
+	return ::SQLGetDiagRecA(fHandleType,
+		handle,
+		iRecord,
+		szSqlState,
+		pfNativeError,
+		szErrorMsg,
+		cbErrorMsgMax,
+		pcbErrorMsg);
+}
+
+
+inline SQLRETURN SQLPrepare(SQLHSTMT hstmt,
+	SQLCHAR*   szSqlStr,
+	SQLINTEGER cbSqlStr)
+{
+	return ::SQLPrepareA(hstmt,	szSqlStr, cbSqlStr);
+}
+
+
+inline SQLRETURN SQLSetConnectAttr(SQLHDBC hdbc,
+	SQLINTEGER fAttribute,
+	SQLPOINTER rgbValue,
+	SQLINTEGER cbValue)
+{
+	return ::SQLSetConnectAttrA(hdbc,	fAttribute,	rgbValue, cbValue);
+}
+
+
+inline SQLRETURN SQLSetCursorName(SQLHSTMT hstmt,
+	SQLCHAR*    szCursor,
+	SQLSMALLINT cbCursor)
+{
+	throw Poco::NotImplementedException("Not implemented");
+}
+
+
+inline SQLRETURN SQLSetStmtAttr(SQLHSTMT hstmt,
+	SQLINTEGER fAttribute,
+	SQLPOINTER rgbValue,
+	SQLINTEGER cbValueMax)
+{
+	return ::SQLSetStmtAttr(hstmt, fAttribute, rgbValue, cbValueMax);
+}
+
+
+inline SQLRETURN SQLGetStmtAttr(SQLHSTMT hstmt,
+	SQLINTEGER  fAttribute,
+	SQLPOINTER  rgbValue,
+	SQLINTEGER  cbValueMax,
+	SQLINTEGER* pcbValue)
+{
+	return ::SQLGetStmtAttrA(hstmt,
+		fAttribute,
+		rgbValue,
+		cbValueMax,
+		pcbValue);
+}
+
+
+inline SQLRETURN SQLColumns(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName,
+	SQLCHAR*    szColumnName,
+	SQLSMALLINT cbColumnName)
+{
+	return ::SQLColumnsA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName,
+		szColumnName,
+		cbColumnName);
+}
+
+
+inline SQLRETURN SQLGetConnectOption(SQLHDBC hdbc,
+	SQLUSMALLINT fOption,
+	SQLPOINTER   pvParam)
+{
+	return ::SQLGetConnectOptionA(hdbc, fOption, pvParam);
+}
+
+
+inline SQLRETURN SQLGetInfo(SQLHDBC hdbc,
+	SQLUSMALLINT fInfoType,
+	SQLPOINTER   rgbInfoValue,
+	SQLSMALLINT  cbInfoValueMax,
+	SQLSMALLINT* pcbInfoValue)
+{
+	return ::SQLGetInfoA(hdbc,
+		fInfoType,
+		rgbInfoValue,
+		cbInfoValueMax,
+		pcbInfoValue);
+}
+
+
+inline SQLRETURN SQLGetTypeInfo(SQLHSTMT StatementHandle,
+	SQLSMALLINT	DataType)
+{
+	return ::SQLGetTypeInfoA(StatementHandle, DataType);
+}
+
+
+inline SQLRETURN SQLSetConnectOption(SQLHDBC hdbc,
+	SQLUSMALLINT fOption,
+	SQLULEN      vParam)
+{
+	return ::SQLSetConnectOptionA(hdbc, fOption, vParam);
+}
+
+
+inline SQLRETURN SQLSpecialColumns(SQLHSTMT hstmt,
+	SQLUSMALLINT fColType,
+	SQLCHAR*     szCatalogName,
+	SQLSMALLINT  cbCatalogName,
+	SQLCHAR*     szSchemaName,
+	SQLSMALLINT  cbSchemaName,
+	SQLCHAR*     szTableName,
+	SQLSMALLINT  cbTableName,
+	SQLUSMALLINT fScope,
+	SQLUSMALLINT fNullable)
+{
+	return ::SQLSpecialColumnsA(hstmt,
+		fColType,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName,
+		fScope,
+		fNullable);
+}
+
+
+inline SQLRETURN SQLStatistics(SQLHSTMT hstmt,
+	SQLCHAR*     szCatalogName,
+	SQLSMALLINT  cbCatalogName,
+	SQLCHAR*     szSchemaName,
+	SQLSMALLINT  cbSchemaName,
+	SQLCHAR*     szTableName,
+	SQLSMALLINT  cbTableName,
+	SQLUSMALLINT fUnique,
+	SQLUSMALLINT fAccuracy)
+{
+	return ::SQLStatisticsA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName,
+		fUnique,
+		fAccuracy);
+}
+
+
+inline SQLRETURN SQLTables(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName,
+	SQLCHAR*    szTableType,
+	SQLSMALLINT cbTableType)
+{
+	return ::SQLTablesA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName,
+		szTableType,
+		cbTableType);
+}
+
+
+inline SQLRETURN SQLDataSources(SQLHENV henv,
+	SQLUSMALLINT fDirection,
+	SQLCHAR*     szDSN,
+	SQLSMALLINT  cbDSNMax,
+	SQLSMALLINT* pcbDSN,
+	SQLCHAR*     szDescription,
+	SQLSMALLINT  cbDescriptionMax,
+	SQLSMALLINT* pcbDescription)
+{
+	return ::SQLDataSourcesA(henv,
+		fDirection,
+		szDSN,
+		cbDSNMax,
+		pcbDSN,
+		szDescription,
+		cbDescriptionMax,
+		pcbDescription);
+}
+
+
+inline SQLRETURN SQLDriverConnect(SQLHDBC hdbc,
+	SQLHWND      hwnd,
+	SQLCHAR*     szConnStrIn,
+	SQLSMALLINT  cbConnStrIn,
+	SQLCHAR*     szConnStrOut,
+	SQLSMALLINT  cbConnStrOutMax,
+	SQLSMALLINT* pcbConnStrOut,
+	SQLUSMALLINT fDriverCompletion)
+{
+	return ::SQLDriverConnectA(hdbc,
+		hwnd,
+		szConnStrIn,
+		cbConnStrIn,
+		szConnStrOut,
+		cbConnStrOutMax,
+		pcbConnStrOut,
+		fDriverCompletion);
+}
+
+
+inline SQLRETURN SQLBrowseConnect(SQLHDBC hdbc,
+	SQLCHAR*     szConnStrIn,
+	SQLSMALLINT  cbConnStrIn,
+	SQLCHAR*     szConnStrOut,
+	SQLSMALLINT  cbConnStrOutMax,
+	SQLSMALLINT* pcbConnStrOut)
+{
+	return ::SQLBrowseConnectA(hdbc,
+		szConnStrIn,
+		cbConnStrIn,
+		szConnStrOut,
+		cbConnStrOutMax,
+		pcbConnStrOut);
+}
+
+
+inline SQLRETURN SQLColumnPrivileges(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName,
+	SQLCHAR*    szColumnName,
+	SQLSMALLINT cbColumnName)
+{
+	return ::SQLColumnPrivilegesA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName,
+		szColumnName,
+		cbColumnName);
+}
+
+
+inline SQLRETURN SQLForeignKeys(SQLHSTMT hstmt,
+	SQLCHAR*    szPkCatalogName,
+	SQLSMALLINT cbPkCatalogName,
+	SQLCHAR*    szPkSchemaName,
+	SQLSMALLINT cbPkSchemaName,
+	SQLCHAR*    szPkTableName,
+	SQLSMALLINT cbPkTableName,
+	SQLCHAR*    szFkCatalogName,
+	SQLSMALLINT cbFkCatalogName,
+	SQLCHAR*    szFkSchemaName,
+	SQLSMALLINT cbFkSchemaName,
+	SQLCHAR*    szFkTableName,
+	SQLSMALLINT cbFkTableName)
+{
+	return ::SQLForeignKeysA(hstmt,
+		szPkCatalogName,
+		cbPkCatalogName,
+		szPkSchemaName,
+		cbPkSchemaName,
+		szPkTableName,
+		cbPkTableName,
+		szFkCatalogName,
+		cbFkCatalogName,
+		szFkSchemaName,
+		cbFkSchemaName,
+		szFkTableName,
+		cbFkTableName);
+}
+
+
+inline SQLRETURN SQLNativeSql(SQLHDBC hdbc,
+	SQLCHAR*    szSqlStrIn,
+	SQLINTEGER  cbSqlStrIn,
+	SQLCHAR*    szSqlStr,
+	SQLINTEGER  cbSqlStrMax,
+	SQLINTEGER* pcbSqlStr)
+{
+	return ::SQLNativeSqlA(hdbc,
+		szSqlStrIn,
+		cbSqlStrIn,
+		szSqlStr,
+		cbSqlStrMax,
+		pcbSqlStr);
+}
+
+
+inline SQLRETURN SQLPrimaryKeys(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName)
+{
+	return ::SQLPrimaryKeysA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName);
+}
+
+
+inline SQLRETURN SQLProcedureColumns(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szProcName,
+	SQLSMALLINT cbProcName,
+	SQLCHAR*    szColumnName,
+	SQLSMALLINT cbColumnName)
+{
+	return ::SQLProcedureColumnsA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szProcName,
+		cbProcName,
+		szColumnName,
+		cbColumnName);
+}
+
+
+inline SQLRETURN SQLProcedures(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szProcName,
+	SQLSMALLINT cbProcName)
+{
+	return ::SQLProceduresA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szProcName,
+		cbProcName);
+}
+
+
+inline SQLRETURN SQLTablePrivileges(SQLHSTMT hstmt,
+	SQLCHAR*    szCatalogName,
+	SQLSMALLINT cbCatalogName,
+	SQLCHAR*    szSchemaName,
+	SQLSMALLINT cbSchemaName,
+	SQLCHAR*    szTableName,
+	SQLSMALLINT cbTableName)
+{
+	return ::SQLTablePrivilegesA(hstmt,
+		szCatalogName,
+		cbCatalogName,
+		szSchemaName,
+		cbSchemaName,
+		szTableName,
+		cbTableName);
+}
+
+
+inline SQLRETURN SQLDrivers(SQLHENV henv,
+	SQLUSMALLINT fDirection,
+	SQLCHAR*     szDriverDesc,
+	SQLSMALLINT  cbDriverDescMax,
+	SQLSMALLINT* pcbDriverDesc,
+	SQLCHAR*     szDriverAttributes,
+	SQLSMALLINT  cbDrvrAttrMax,
+	SQLSMALLINT* pcbDrvrAttr)
+{
+	return ::SQLDriversA(henv,
+		fDirection,
+		szDriverDesc,
+		cbDriverDescMax,
+		pcbDriverDesc,
+		szDriverAttributes,
+		cbDrvrAttrMax,
+		pcbDrvrAttr);
+}
+
+
+#endif // POCO_ODBC_UNICODE
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // ODBC_Unicode_INCLUDED
diff --git a/Poco/Data/ODBC/Unicode_UNIXODBC.h b/Poco/Data/ODBC/Unicode_UNIXODBC.h
new file mode 100644
index 0000000..f2e6794
--- /dev/null
+++ b/Poco/Data/ODBC/Unicode_UNIXODBC.h
@@ -0,0 +1,51 @@
+//
+// Unicode.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Unicode
+//
+// Definition of Unicode_UNIX.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Unicode_UNIX_INCLUDED
+#define Data_ODBC_Unicode_UNIX_INCLUDED
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::string& target);
+	/// Utility function for conversion from UTF-8 to UTF-16
+
+
+inline void makeUTF16(SQLCHAR* pSQLChar, SQLSMALLINT length, std::string& target)
+	/// Utility function for conversion from UTF-8 to UTF-16.
+{
+	makeUTF16(pSQLChar, (SQLINTEGER) length, target);
+}
+
+
+void makeUTF8(Poco::Buffer<SQLWCHAR>& buffer, SQLINTEGER length, SQLPOINTER pTarget, SQLINTEGER targetLength);
+	/// Utility function for conversion from UTF-16 to UTF-8.
+
+
+inline void makeUTF8(Poco::Buffer<SQLWCHAR>& buffer, int length, SQLPOINTER pTarget, SQLSMALLINT targetLength)
+	/// Utility function for conversion from UTF-16 to UTF-8.
+{
+	makeUTF8(buffer, length, pTarget, (SQLINTEGER) targetLength);
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_Unicode_UNIX_INCLUDED
diff --git a/Poco/Data/ODBC/Unicode_WIN32.h b/Poco/Data/ODBC/Unicode_WIN32.h
new file mode 100644
index 0000000..fa1abe9
--- /dev/null
+++ b/Poco/Data/ODBC/Unicode_WIN32.h
@@ -0,0 +1,57 @@
+//
+// Unicode.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Unicode
+//
+// Definition of Unicode_WIN32.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Unicode_WIN32_INCLUDED
+#define Data_ODBC_Unicode_WIN32_INCLUDED
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+inline void makeUTF16(SQLCHAR* pSQLChar, SQLINTEGER length, std::wstring& target)
+	/// Utility function for conversion from UTF-8 to UTF-16
+{
+	int len = length;
+	if (SQL_NTS == len) 
+		len = (int) std::strlen((const char *) pSQLChar);
+
+	UnicodeConverter::toUTF16((const char *) pSQLChar, len, target);
+}
+
+
+inline void makeUTF8(Poco::Buffer<wchar_t>& buffer, SQLINTEGER length, SQLPOINTER pTarget, SQLINTEGER targetLength)
+	/// Utility function for conversion from UTF-16 to UTF-8. Length is in bytes.
+{
+	if (buffer.sizeBytes() < length)
+		throw InvalidArgumentException("Specified length exceeds available length.");
+	else if ((length % 2) != 0)
+		throw InvalidArgumentException("Length must be an even number.");
+
+	length /= sizeof(wchar_t);
+	std::string result;
+	UnicodeConverter::toUTF8(buffer.begin(), length, result);
+	
+	std::memset(pTarget, 0, targetLength);
+	std::strncpy((char*) pTarget, result.c_str(), result.size() < targetLength ? result.size() : targetLength);
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif // Data_ODBC_Unicode_WIN32_INCLUDED
diff --git a/Poco/Data/ODBC/Utility.h b/Poco/Data/ODBC/Utility.h
new file mode 100644
index 0000000..28e7865
--- /dev/null
+++ b/Poco/Data/ODBC/Utility.h
@@ -0,0 +1,207 @@
+//
+// Utility.h
+//
+// Library: Data/ODBC
+// Package: ODBC
+// Module:  Utility
+//
+// Definition of Utility.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_ODBC_Utility_INCLUDED
+#define Data_ODBC_Utility_INCLUDED
+
+
+#include "Poco/Data/ODBC/ODBC.h"
+#include "Poco/Data/ODBC/TypeInfo.h"
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.h"
+#include "Poco/DateTime.h"
+#include <sstream>
+#include <map>
+#include <sqltypes.h>
+
+
+namespace Poco {
+namespace Data {
+namespace ODBC {
+
+
+class ODBC_API Utility
+	/// Various utility functions
+{
+public:
+	typedef std::map<std::string, std::string> DSNMap;
+	typedef DSNMap DriverMap;
+
+	static bool isError(SQLRETURN rc);
+		/// Returns true if return code is error
+
+	static DriverMap& drivers(DriverMap& driverMap);
+		/// Returns driver-attributes map of available ODBC drivers.
+
+	static DSNMap& dataSources(DSNMap& dsnMap);
+		/// Returns DSN-description map of available ODBC data sources.
+
+	template<typename MapType, typename KeyArgType, typename ValueArgType>
+	static typename MapType::iterator mapInsert(MapType& m, const KeyArgType& k, const ValueArgType& v)
+		/// Utility map "insert or replace" function (from S. Meyers: Effective STL, Item 24)
+	{
+		typename MapType::iterator lb = m.lower_bound(k);
+		if (lb != m.end() && !(m.key_comp()(k, lb->first)))
+		{
+			lb->second = v;
+			return lb;
+		}
+		else
+		{
+			typedef typename MapType::value_type MVT;
+			return m.insert(lb, MVT(k,v));
+		}
+	}
+
+	static int cDataType(int sqlDataType);
+		/// Returns C data type corresponding to supplied SQL data type.
+
+	static int sqlDataType(int cDataType);
+		/// Returns SQL data type corresponding to supplied C data type.
+
+	static void dateSync(Date& dt, const SQL_DATE_STRUCT& ts);
+		/// Transfers data from ODBC SQL_DATE_STRUCT to Poco::DateTime.
+
+	template <typename T, typename F>
+	static void dateSync(T& d, const F& ds)
+		/// Transfers data from ODBC SQL_DATE_STRUCT container to Poco::DateTime container.
+	{
+		std::size_t size = ds.size();
+		if (d.size() != size) d.resize(size);
+		typename T::iterator dIt = d.begin();
+		typename F::const_iterator it = ds.begin();
+		typename F::const_iterator end = ds.end();
+		for (; it != end; ++it, ++dIt) dateSync(*dIt, *it);
+	}
+
+	static void timeSync(Time& dt, const SQL_TIME_STRUCT& ts);
+		/// Transfers data from ODBC SQL_TIME_STRUCT to Poco::DateTime.
+
+	template <typename T, typename F>
+	static void timeSync(T& t, const F& ts)
+		/// Transfers data from ODBC SQL_TIME_STRUCT container to Poco::DateTime container.
+	{
+		std::size_t size = ts.size();
+		if (t.size() != size) t.resize(size);
+		typename T::iterator dIt = t.begin();
+		typename F::const_iterator it = ts.begin();
+		typename F::const_iterator end = ts.end();
+		for (; it != end; ++it, ++dIt) timeSync(*dIt, *it);
+	}
+
+	static void dateTimeSync(Poco::DateTime& dt, const SQL_TIMESTAMP_STRUCT& ts);
+		/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT to Poco::DateTime.
+
+	template <typename T, typename F>
+	static void dateTimeSync(T& dt, const F& ts)
+		/// Transfers data from ODBC SQL_TIMESTAMP_STRUCT container to Poco::DateTime container.
+	{
+		std::size_t size = ts.size();
+		if (dt.size() != size) dt.resize(size);
+		typename T::iterator dIt = dt.begin();
+		typename F::const_iterator it = ts.begin();
+		typename F::const_iterator end = ts.end();
+		for (; it != end; ++it, ++dIt) dateTimeSync(*dIt, *it);
+	}
+
+	static void dateSync(SQL_DATE_STRUCT& ts, const Date& dt);
+		/// Transfers data from Poco::Data::Date to ODBC SQL_DATE_STRUCT.
+
+	template <typename C>
+	static void dateSync(std::vector<SQL_DATE_STRUCT>& ds, const C& d)
+		/// Transfers data from Poco::Data::Date vector to ODBC SQL_DATE_STRUCT container.
+	{
+		std::size_t size = d.size();
+		if (ds.size() != size) ds.resize(size);
+		std::vector<SQL_DATE_STRUCT>::iterator dIt = ds.begin();
+		typename C::const_iterator it = d.begin();
+		typename C::const_iterator end = d.end();
+		for (; it != end; ++it, ++dIt) dateSync(*dIt, *it);
+	}
+
+	static void timeSync(SQL_TIME_STRUCT& ts, const Time& dt);
+		/// Transfers data from Poco::Data::Time to ODBC SQL_TIME_STRUCT.
+
+	template <typename C>
+	static void timeSync(std::vector<SQL_TIME_STRUCT>& ts, const C& t)
+		/// Transfers data from Poco::Data::Time container to ODBC SQL_TIME_STRUCT vector.
+	{
+		std::size_t size = t.size();
+		if (ts.size() != size) ts.resize(size);
+		std::vector<SQL_TIME_STRUCT>::iterator tIt = ts.begin();
+		typename C::const_iterator it = t.begin();
+		typename C::const_iterator end = t.end();
+		for (; it != end; ++it, ++tIt) timeSync(*tIt, *it);
+	}
+
+	static void dateTimeSync(SQL_TIMESTAMP_STRUCT& ts, const Poco::DateTime& dt);
+		/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
+
+	template <typename C>
+	static void dateTimeSync(std::vector<SQL_TIMESTAMP_STRUCT>& ts, const C& dt)
+		/// Transfers data from Poco::DateTime to ODBC SQL_TIMESTAMP_STRUCT.
+	{
+		std::size_t size = dt.size();
+		if (ts.size() != size) ts.resize(size);
+		std::vector<SQL_TIMESTAMP_STRUCT>::iterator tIt = ts.begin();
+		typename C::const_iterator it = dt.begin();
+		typename C::const_iterator end = dt.end();
+		for (; it != end; ++it, ++tIt) dateTimeSync(*tIt, *it);
+	}
+
+private:
+	static const TypeInfo _dataTypes;
+		/// C <==> SQL data type mapping
+};
+
+
+///
+/// inlines
+///
+inline bool Utility::isError(SQLRETURN rc)
+{
+	return (0 != (rc & (~1)));
+}
+
+
+inline int Utility::cDataType(int sqlDataType)
+{
+	return _dataTypes.cDataType(sqlDataType);
+}
+
+
+inline int Utility::sqlDataType(int cDataType)
+{
+	return _dataTypes.sqlDataType(cDataType);
+}
+
+
+inline void Utility::dateSync(Date& d, const SQL_DATE_STRUCT& ts)
+{
+	d.assign(ts.year, ts.month, ts.day);
+}
+
+
+inline void Utility::timeSync(Time& t, const SQL_TIME_STRUCT& ts)
+{
+	t.assign(ts.hour, ts.minute, ts.second);
+}
+
+
+} } } // namespace Poco::Data::ODBC
+
+
+#endif
diff --git a/Poco/Data/PooledSessionHolder.h b/Poco/Data/PooledSessionHolder.h
new file mode 100644
index 0000000..8924589
--- /dev/null
+++ b/Poco/Data/PooledSessionHolder.h
@@ -0,0 +1,99 @@
+//
+// PooledSessionHolder.h
+//
+// Library: Data
+// Package: SessionPooling
+// Module:  PooledSessionHolder
+//
+// Definition of the PooledSessionHolder class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_PooledSessionHolder_INCLUDED
+#define Data_PooledSessionHolder_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class SessionPool;
+
+
+class Data_API PooledSessionHolder: public Poco::RefCountedObject
+	/// This class is used by SessionPool to manage SessionImpl objects.
+{
+public:
+	PooledSessionHolder(SessionPool& owner, SessionImpl* pSessionImpl);
+		/// Creates the PooledSessionHolder.
+
+	~PooledSessionHolder();
+		/// Destroys the PooledSessionHolder.
+
+	SessionImpl* session();
+		/// Returns a pointer to the SessionImpl.
+
+	SessionPool& owner();
+		/// Returns a reference to the SessionHolder's owner.
+
+	void access();
+		/// Updates the last access timestamp.
+
+	int idle() const;
+		/// Returns the number of seconds the session has not been used.
+
+private:
+	SessionPool& _owner;
+	Poco::AutoPtr<SessionImpl> _pImpl;
+	Poco::Timestamp _lastUsed;
+	mutable Poco::FastMutex _mutex;
+};
+
+
+//
+// inlines
+//
+inline SessionImpl* PooledSessionHolder::session()
+{
+	return _pImpl;
+}
+
+
+inline SessionPool& PooledSessionHolder::owner()
+{
+	return _owner;
+}
+
+
+inline void PooledSessionHolder::access()
+{
+	Poco::FastMutex::ScopedLock lock(_mutex);
+	
+	_lastUsed.update();
+}
+
+
+inline int PooledSessionHolder::idle() const
+{
+	Poco::FastMutex::ScopedLock lock(_mutex);
+
+	return (int) (_lastUsed.elapsed()/Poco::Timestamp::resolution());
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_PooledSessionHolder_INCLUDED
diff --git a/Poco/Data/PooledSessionImpl.h b/Poco/Data/PooledSessionImpl.h
new file mode 100644
index 0000000..1d11028
--- /dev/null
+++ b/Poco/Data/PooledSessionImpl.h
@@ -0,0 +1,97 @@
+//
+// PooledSessionImpl.h
+//
+// Library: Data
+// Package: SessionPooling
+// Module:  PooledSessionImpl
+//
+// Definition of the PooledSessionImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_PooledSessionImpl_INCLUDED
+#define Data_PooledSessionImpl_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/Data/PooledSessionHolder.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class SessionPool;
+
+
+class Data_API PooledSessionImpl: public SessionImpl
+	/// PooledSessionImpl is a decorator created by
+	/// SessionPool that adds session pool
+	/// management to SessionImpl objects.
+{
+public:
+	PooledSessionImpl(PooledSessionHolder* pHolder);
+		/// Creates the PooledSessionImpl.
+
+	~PooledSessionImpl();
+		/// Destroys the PooledSessionImpl.
+
+	// SessionImpl
+	StatementImpl* createStatementImpl();
+	void begin();
+	void commit();
+	void rollback();
+	void open(const std::string& connect = "");
+	void close();
+	bool isConnected();
+	void setConnectionTimeout(std::size_t timeout);
+	std::size_t getConnectionTimeout();
+	bool canTransact();
+	bool isTransaction();
+	void setTransactionIsolation(Poco::UInt32);
+	Poco::UInt32 getTransactionIsolation();
+	bool hasTransactionIsolation(Poco::UInt32);
+	bool isTransactionIsolation(Poco::UInt32);
+	const std::string& connectorName() const;
+	void setFeature(const std::string& name, bool state);	
+	bool getFeature(const std::string& name);
+	void setProperty(const std::string& name, const Poco::Any& value);
+	Poco::Any getProperty(const std::string& name);
+	
+protected:
+	SessionImpl* access() const;
+		/// Updates the last access timestamp,
+		/// verifies validity of the session
+		/// and returns the session if it is valid.
+		///
+		/// Throws an SessionUnavailableException if the
+		/// session is no longer valid.
+		
+	SessionImpl* impl() const;
+		/// Returns a pointer to the SessionImpl.
+				
+private:	
+	mutable Poco::AutoPtr<PooledSessionHolder> _pHolder;
+};
+
+
+//
+// inlines
+//
+inline SessionImpl* PooledSessionImpl::impl() const
+{
+	return _pHolder->session();
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_PooledSessionImpl_INCLUDED
diff --git a/Poco/Data/Position.h b/Poco/Data/Position.h
new file mode 100644
index 0000000..727d27b
--- /dev/null
+++ b/Poco/Data/Position.h
@@ -0,0 +1,75 @@
+//
+// PositionExtraction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Position
+//
+// Definition of the PositionExtraction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Position_INCLUDED
+#define Data_Position_INCLUDED
+
+
+#include "Poco/Data/Limit.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API Position
+	/// Utility class wrapping unsigned integer. Used to
+	/// indicate the recordset position in batch SQL statements.
+{
+public:
+	Position(Poco::UInt32 value);
+		/// Creates the Position.
+
+	~Position();
+		/// Destroys the Position.
+
+	Poco::UInt32 value() const;
+		/// Returns the position value.
+	
+private:
+	Position();
+
+	Poco::UInt32 _value;
+};
+
+
+///
+/// inlines
+///
+inline Poco::UInt32 Position::value() const 
+{ 
+	return _value; 
+}
+
+
+namespace Keywords {
+
+
+template <typename T>
+inline Position from(const T& value)
+	/// Convenience function for creation of position.
+{
+	return Position(value);
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Position_INCLUDED
diff --git a/Poco/Data/Preparation.h b/Poco/Data/Preparation.h
new file mode 100644
index 0000000..f573a20
--- /dev/null
+++ b/Poco/Data/Preparation.h
@@ -0,0 +1,161 @@
+//
+// Preparation.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Preparation
+//
+// Definition of the Preparation class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Preparation_INCLUDED
+#define Data_Preparation_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractPreparation.h"
+#include "Poco/Data/TypeHandler.h"
+#include <cstddef>
+#include <vector>
+
+
+namespace Poco {
+namespace Data {
+
+
+template<typename T>
+class Preparation: public AbstractPreparation
+	/// Class for calling the appropriate AbstractPreparator method.
+{
+public:
+	Preparation(AbstractPreparator::Ptr& pPreparator, std::size_t pos, T& val): 
+		AbstractPreparation(pPreparator), 
+		_pos(pos), 
+		_val(val)
+		/// Creates the Preparation.
+	{
+	}
+
+	~Preparation()
+		/// Destroys the Preparation.
+	{
+	}
+
+	void prepare()
+		/// Prepares data.
+	{
+		TypeHandler<T>::prepare(_pos, _val, preparation());
+	}
+
+private:
+	std::size_t _pos;
+	T&          _val;
+};
+
+
+template<typename T>
+class Preparation<std::vector<T> >: public AbstractPreparation
+	/// Preparation specialization for std::vector.
+	/// This specialization is needed for bulk operations to enforce
+	/// the whole vector preparation, rather than only individual contained values.
+{
+public:
+	Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::vector<T>& val = std::vector<T>()): 
+		AbstractPreparation(pPreparator), 
+		_pos(pos), 
+		_val(val)
+		/// Creates the Preparation.
+	{
+	}
+
+	~Preparation()
+		/// Destroys the Preparation.
+	{
+	}
+
+	void prepare()
+		/// Prepares data.
+	{
+		TypeHandler<std::vector<T> >::prepare(_pos, _val, preparation());
+	}
+
+private:
+	std::size_t     _pos;
+	std::vector<T>& _val;
+};
+
+
+template<typename T>
+class Preparation<std::deque<T> >: public AbstractPreparation
+	/// Preparation specialization for std::deque.
+	/// This specialization is needed for bulk operations to enforce
+	/// the whole deque preparation, rather than only individual contained values.
+{
+public:
+	Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::deque<T>& val = std::deque<T>()): 
+		AbstractPreparation(pPreparator), 
+		_pos(pos), 
+		_val(val)
+		/// Creates the Preparation.
+	{
+	}
+
+	~Preparation()
+		/// Destroys the Preparation.
+	{
+	}
+
+	void prepare()
+		/// Prepares data.
+	{
+		TypeHandler<std::deque<T> >::prepare(_pos, _val, preparation());
+	}
+
+private:
+	std::size_t     _pos;
+	std::deque<T>&  _val;
+};
+
+
+template<typename T>
+class Preparation<std::list<T> >: public AbstractPreparation
+	/// Preparation specialization for std::list.
+	/// This specialization is needed for bulk operations to enforce
+	/// the whole list preparation, rather than only individual contained values.
+{
+public:
+	Preparation(AbstractPreparator::Ptr pPreparator, std::size_t pos, std::list<T>& val = std::list<T>()): 
+		AbstractPreparation(pPreparator), 
+		_pos(pos), 
+		_val(val)
+		/// Creates the Preparation.
+	{
+	}
+
+	~Preparation()
+		/// Destroys the Preparation.
+	{
+	}
+
+	void prepare()
+		/// Prepares data.
+	{
+		TypeHandler<std::list<T> >::prepare(_pos, _val, preparation());
+	}
+
+private:
+	std::size_t   _pos;
+	std::list<T>& _val;
+};
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Preparation_INCLUDED
diff --git a/Poco/Data/Range.h b/Poco/Data/Range.h
new file mode 100644
index 0000000..8f0ab04
--- /dev/null
+++ b/Poco/Data/Range.h
@@ -0,0 +1,104 @@
+//
+// Range.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Range
+//
+// Definition of the Range class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Range_INCLUDED
+#define Data_Range_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Limit.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API Range
+	/// Range stores information how many rows a query should return.
+{
+public:
+	Range(Limit::SizeT lowValue, Limit::SizeT upValue, bool hardLimit);
+		/// Creates the Range. lowValue must be smaller equal than upValue
+
+	~Range();
+		/// Destroys the Limit.
+
+	const Limit& lower() const;
+		/// Returns the lower limit
+
+	const Limit& upper() const;
+		/// Returns the upper limit
+
+private:
+	Limit _lower;
+	Limit _upper;
+};
+
+
+//
+// inlines
+//
+inline const Limit& Range::lower() const
+{
+	return _lower;
+}
+
+
+inline const Limit& Range::upper() const
+{
+	return _upper;
+}
+
+
+namespace Keywords {
+
+
+template <typename T> 
+Limit limit(T lim, bool hard = false)
+	/// Creates an upperLimit
+{
+	return Limit(static_cast<Limit::SizeT>(lim), hard, false);
+}
+
+
+template <typename T> 
+Limit upperLimit(T lim, bool hard = false)
+{
+	return limit(lim, hard);
+}
+
+
+template <typename T> 
+Limit lowerLimit(T lim)
+{
+	return Limit(static_cast<Limit::SizeT>(lim), true, true);
+}
+
+
+template <typename T> 
+Range range(T low, T upp, bool hard = false)
+{
+	return Range(static_cast<Limit::SizeT>(low), static_cast<Limit::SizeT>(upp), hard);
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Range_INCLUDED
diff --git a/Poco/Data/RecordSet.h b/Poco/Data/RecordSet.h
new file mode 100644
index 0000000..050b389
--- /dev/null
+++ b/Poco/Data/RecordSet.h
@@ -0,0 +1,653 @@
+//
+// RecordSet.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  RecordSet
+//
+// Definition of the RecordSet class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_RecordSet_INCLUDED
+#define Data_RecordSet_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Data/Extraction.h"
+#include "Poco/Data/BulkExtraction.h"
+#include "Poco/Data/Statement.h"
+#include "Poco/Data/RowIterator.h"
+#include "Poco/Data/RowFilter.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/String.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Exception.h"
+#include "Poco/AutoPtr.h"
+#include <ostream>
+#include <limits>
+
+
+namespace Poco {
+namespace Data {
+
+
+class RowFilter;
+
+
+class Data_API RecordSet: private Statement
+	/// RecordSet provides access to data returned from a query.
+	/// Data access indices (row and column) are 0-based, as usual in C++.
+	/// 
+	/// Recordset provides navigation methods to iterate through the
+	/// recordset, retrieval methods to extract data, and methods
+	/// to get metadata (type, etc.) about columns.
+	///
+	/// To work with a RecordSet, first create a Statement, execute it, and
+	/// create the RecordSet from the Statement, as follows:
+	///
+	///     Statement select(session);
+	///     select << "SELECT * FROM Person";
+	///     select.execute();
+	///     RecordSet rs(select);
+	///
+	/// The shorter way to do the above is following:
+	///
+	///     RecordSet rs(session, "SELECT * FROM Person"[, new SimpleRowFormatter]);
+	///
+	/// The third (optional) argument passed to the Recordset constructor is a RowFormatter
+	/// implementation. The formatter is used in conjunction with << operator for recordset
+	/// data formating.
+	/// 
+	/// The number of rows in the RecordSet can be limited by specifying
+	/// a limit for the Statement.
+{
+public:
+	typedef std::map<std::size_t, Row*> RowMap;
+	typedef const RowIterator           ConstIterator;
+	typedef RowIterator                 Iterator;
+
+	using Statement::isNull;
+	using Statement::subTotalRowCount;
+
+	static const std::size_t UNKNOWN_TOTAL_ROW_COUNT;
+
+	explicit RecordSet(const Statement& rStatement,
+		RowFormatter::Ptr pRowFormatter = 0);
+		/// Creates the RecordSet.
+
+	RecordSet(Session& rSession, 
+		const std::string& query,
+		RowFormatter::Ptr pRowFormatter = 0);
+		/// Creates the RecordSet.
+
+	RecordSet(Session& rSession, 
+		const std::string& query,
+		const RowFormatter& rowFormatter);
+		/// Creates the RecordSet.
+
+	template <class RF>
+	RecordSet(Session& rSession, const std::string& query, const RF& rowFormatter): 
+		Statement((rSession << query, Keywords::now)),
+		_currentRow(0),
+		_pBegin(new RowIterator(this, 0 == rowsExtracted())),
+		_pEnd(new RowIterator(this, true)),
+		_totalRowCount(UNKNOWN_TOTAL_ROW_COUNT)
+		/// Creates the RecordSet.
+	{
+		setRowFormatter(Keywords::format(rowFormatter));
+	}
+
+	RecordSet(const RecordSet& other);
+		/// Copy-creates the recordset.
+
+	~RecordSet();
+		/// Destroys the RecordSet.
+
+	void setRowFormatter(RowFormatter::Ptr pRowFormatter);
+		/// Assigns the row formatter to the statement and all recordset rows.
+
+	Statement& operator = (const Statement& stmt);
+		/// Assignment operator.
+
+	std::size_t rowCount() const;
+		/// Returns the number of rows in the RecordSet.
+		/// The number of rows reported is dependent on filtering.
+		/// Due to the need for filter conditions checking,
+		/// this function may suffer significant performance penalty
+		/// for large recordsets, so it should be used judiciously.
+		/// Use totalRowCount() to obtain the total number of rows.
+
+	std::size_t extractedRowCount() const;
+		/// Returns the number of rows extracted during the last statement
+		/// execution.
+		/// The number of rows reported is independent of filtering.
+
+	std::size_t totalRowCount() const;
+		//@ deprecated
+		/// Replaced with subTotalRowCount() and getTotalRowCount().
+
+	std::size_t getTotalRowCount() const;
+		/// Returns the total number of rows in the RecordSet.
+		/// The number of rows reported is independent of filtering.
+		/// If the total row count has not been set externally 
+		/// (either explicitly or implicitly through SQL), the value
+		/// returned shall only be accurate if the statement limit
+		/// is less or equal to the total row count.
+
+	void setTotalRowCount(std::size_t totalRowCount);
+		/// Explicitly sets the total row count.
+
+	void setTotalRowCount(const std::string& sql);
+		/// Implicitly sets the total row count.
+		/// The supplied sql must return exactly one column
+		/// and one row. The returned value must be an unsigned
+		/// integer. The value is set as the total number of rows.
+
+	std::size_t columnCount() const;
+		/// Returns the number of columns in the recordset.
+
+	template <class C>
+	const Column<C>& column(const std::string& name) const
+		/// Returns the reference to the first Column with the specified name.
+	{
+		if (isBulkExtraction())
+		{
+			typedef InternalBulkExtraction<C> E;
+			return columnImpl<C,E>(name);
+		}
+		else
+		{
+			typedef InternalExtraction<C> E;
+			return columnImpl<C,E>(name);
+		}
+	}
+
+	template <class C>
+	const Column<C>& column(std::size_t pos) const
+		/// Returns the reference to column at specified position.
+	{
+		if (isBulkExtraction())
+		{
+			typedef InternalBulkExtraction<C> E;
+			return columnImpl<C,E>(pos);
+		}
+		else
+		{
+			typedef InternalExtraction<C> E;
+			return columnImpl<C,E>(pos);
+		}
+	}
+
+	Row& row(std::size_t pos);
+		/// Returns reference to row at position pos.
+		/// Rows are lazy-created and cached.
+
+	template <class T>
+	const T& value(std::size_t col, std::size_t row, bool useFilter = true) const
+		/// Returns the reference to data value at [col, row] location.
+	{
+		if (useFilter && isFiltered() && !isAllowed(row))
+			throw InvalidAccessException("Row not allowed");
+
+		switch (storage())
+		{
+			case STORAGE_VECTOR:
+			{
+				typedef typename std::vector<T> C;
+				return column<C>(col).value(row);
+			}
+			case STORAGE_LIST:
+			{
+				typedef typename std::list<T> C;
+				return column<C>(col).value(row);
+			}
+			case STORAGE_DEQUE:
+			case STORAGE_UNKNOWN:
+			{
+				typedef typename std::deque<T> C;
+				return column<C>(col).value(row);
+			}
+			default:
+				throw IllegalStateException("Invalid storage setting.");
+		}
+	}
+
+	template <class T>
+	const T& value(const std::string& name, std::size_t row, bool useFilter = true) const
+		/// Returns the reference to data value at named column, row location.
+	{
+		if (useFilter && isFiltered() && !isAllowed(row))
+			throw InvalidAccessException("Row not allowed");
+
+		switch (storage())
+		{
+			case STORAGE_VECTOR:
+			{
+				typedef typename std::vector<T> C;
+				return column<C>(name).value(row);
+			}
+			case STORAGE_LIST:
+			{
+				typedef typename std::list<T> C;
+				return column<C>(name).value(row);
+			}
+			case STORAGE_DEQUE:
+			case STORAGE_UNKNOWN:
+			{
+				typedef typename std::deque<T> C;
+				return column<C>(name).value(row);
+			}
+			default:
+				throw IllegalStateException("Invalid storage setting.");
+		}
+	}
+
+	Poco::Dynamic::Var value(std::size_t col, std::size_t row, bool checkFiltering = true) const;
+		/// Returns the data value at column, row location.
+
+	Poco::Dynamic::Var value(const std::string& name, std::size_t row, bool checkFiltering = true) const;
+		/// Returns the data value at named column, row location.
+
+	template <typename T>
+	Poco::Dynamic::Var nvl(const std::string& name, const T& deflt = T()) const
+		/// Returns the value in the named column of the current row
+		/// if the value is not NULL, or deflt otherwise.
+	{
+		if (isNull(name))
+			return Poco::Dynamic::Var(deflt);
+		else
+			return value(name, _currentRow);
+	}
+	
+	template <typename T>
+	Poco::Dynamic::Var nvl(std::size_t index, const T& deflt = T()) const
+		/// Returns the value in the given column of the current row
+		/// if the value is not NULL, or deflt otherwise.
+	{
+		if (isNull(index, _currentRow))
+			return Poco::Dynamic::Var(deflt);
+		else
+			return value(index, _currentRow);
+	}
+
+	ConstIterator& begin() const;
+		/// Returns the const row iterator.
+
+	ConstIterator& end() const;
+		/// Returns the const row iterator.
+
+	Iterator begin();
+		/// Returns the row iterator.
+
+	Iterator end();
+		/// Returns the row iterator.
+
+	bool moveFirst();
+		/// Moves the row cursor to the first row.
+		///
+		/// Returns true if there is at least one row in the RecordSet,
+		/// false otherwise.
+
+	bool moveNext();
+		/// Moves the row cursor to the next row.
+		///
+		/// Returns true if the row is available, or false
+		/// if the end of the record set has been reached and
+		/// no more rows are available.
+
+	bool movePrevious();
+		/// Moves the row cursor to the previous row.
+		///
+		/// Returns true if the row is available, or false
+		/// if there are no more rows available.
+
+	bool moveLast();
+		/// Moves the row cursor to the last row.
+		///
+		/// Returns true if there is at least one row in the RecordSet,
+		/// false otherwise.
+
+	using Statement::reset;
+		/// Don't hide base class method.
+
+	void reset(const Statement& stmt);
+		/// Resets the RecordSet and assigns a new statement.
+		/// Should be called after the given statement has been reset,
+		/// assigned a new SQL statement, and executed.
+		///
+		/// Does not remove the associated RowFilter or RowFormatter.
+
+	Poco::Dynamic::Var value(const std::string& name);
+		/// Returns the value in the named column of the current row.
+
+	Poco::Dynamic::Var value(std::size_t index);
+		/// Returns the value in the given column of the current row.
+
+	Poco::Dynamic::Var operator [] (const std::string& name);
+		/// Returns the value in the named column of the current row.
+
+	Poco::Dynamic::Var operator [] (std::size_t index);
+		/// Returns the value in the named column of the current row.
+
+	MetaColumn::ColumnDataType columnType(std::size_t pos) const;
+		/// Returns the type for the column at specified position.
+
+	MetaColumn::ColumnDataType columnType(const std::string& name) const;
+		/// Returns the type for the column with specified name.
+
+	const std::string& columnName(std::size_t pos) const;
+		/// Returns column name for the column at specified position.
+
+	std::size_t columnLength(std::size_t pos) const;
+		/// Returns column maximum length for the column at specified position.
+
+	std::size_t columnLength(const std::string& name) const;
+		/// Returns column maximum length for the column with specified name.
+
+	std::size_t columnPrecision(std::size_t pos) const;
+		/// Returns column precision for the column at specified position.
+		/// Valid for floating point fields only (zero for other data types).
+
+	std::size_t columnPrecision(const std::string& name) const;
+		/// Returns column precision for the column with specified name.
+		/// Valid for floating point fields only (zero for other data types).
+
+	bool isNull(const std::string& name) const;
+		/// Returns true if column value of the current row is null.
+
+	std::ostream& copyNames(std::ostream& os) const;
+		/// Copies the column names to the target output stream.
+		/// Copied string is formatted by the current RowFormatter.
+
+	void formatNames() const;
+		/// Formats names using the current RowFormatter.
+
+	std::ostream& copyValues(std::ostream& os, 
+		std::size_t offset = 0, 
+		std::size_t length = RowIterator::POSITION_END) const;
+		/// Copies the data values to the supplied output stream.
+		/// The data set to be copied is starting at the specified offset 
+		/// from the recordset beginning. The number of rows to be copied
+		/// is specified by length argument.
+		/// An invalid combination of offset/length arguments shall
+		/// cause RangeException to be thrown.
+		/// Copied string is formatted by the current RowFormatter.
+
+	void formatValues(std::size_t offset, std::size_t length) const;
+		/// Formats values using the current RowFormatter.
+		/// The data set to be formatted is starting at the specified offset 
+		/// from the recordset beginning. The number of rows to be copied
+		/// is specified by length argument.
+		/// An invalid combination of offset/length arguments shall
+		/// cause RangeException to be thrown.
+
+	std::ostream& copy(std::ostream& os,
+		std::size_t offset = 0,
+		std::size_t length = RowIterator::POSITION_END) const;
+		/// Copies the column names and values to the target output stream.
+		/// Copied strings are formatted by the current RowFormatter.
+
+	bool isFiltered() const;
+		/// Returns true if recordset is filtered.
+
+private:
+	RecordSet();
+
+	template<class C, class E>
+	std::size_t columnPosition(const std::string& name) const
+		/// Returns the position of the column with specified name.
+	{
+		typedef typename C::value_type T;
+		typedef const E* ExtractionVecPtr;
+
+		bool typeFound = false;
+
+		const AbstractExtractionVec& rExtractions = extractions();
+		AbstractExtractionVec::const_iterator it = rExtractions.begin();
+		AbstractExtractionVec::const_iterator end = rExtractions.end();
+		
+		for (; it != end; ++it)
+		{
+			ExtractionVecPtr pExtraction = dynamic_cast<ExtractionVecPtr>(it->get());
+
+			if (pExtraction)
+			{
+				typeFound = true;
+				const Column<C>& col = pExtraction->column();
+				if (0 == Poco::icompare(name, col.name()))
+					return col.position();
+			}
+		}
+
+		if (typeFound)
+			throw NotFoundException(Poco::format("Column name: %s", name));
+		else
+			throw NotFoundException(Poco::format("Column type: %s, name: %s", std::string(typeid(T).name()), name));
+	}
+
+	template <class C, class E>
+	const Column<C>& columnImpl(const std::string& name) const
+		/// Returns the reference to the first Column with the specified name.
+	{
+		return columnImpl<C,E>(columnPosition<C,E>(name));
+	}
+
+	template <class C, class E>
+	const Column<C>& columnImpl(std::size_t pos) const
+		/// Returns the reference to column at specified position.
+	{
+		typedef typename C::value_type T;
+		typedef const E* ExtractionVecPtr;
+
+		const AbstractExtractionVec& rExtractions = extractions();
+
+		std::size_t s = rExtractions.size();
+		if (0 == s || pos >= s)
+			throw RangeException(Poco::format("Invalid column index: %z", pos));
+
+		ExtractionVecPtr pExtraction = dynamic_cast<ExtractionVecPtr>(rExtractions[pos].get());
+
+		if (pExtraction)
+		{
+			return pExtraction->column();
+		}
+		else 
+		{
+			throw Poco::BadCastException(Poco::format("Type cast failed!\nColumn: %z\nTarget type:\t%s",  
+				pos,
+				std::string(typeid(T).name())));
+		}
+	}
+
+	bool isAllowed(std::size_t row) const;
+		/// Returns true if the specified row is allowed by the
+		/// currently active filter.
+
+	void filter(const Poco::AutoPtr<RowFilter>& pFilter);
+		/// Sets the filter for the RecordSet.
+
+	const Poco::AutoPtr<RowFilter>& getFilter() const;
+		/// Returns the filter associated with the RecordSet.
+
+	std::size_t  _currentRow;
+	RowIterator* _pBegin;
+	RowIterator* _pEnd;
+	RowMap       _rowMap;
+	Poco::AutoPtr<RowFilter> _pFilter;
+	std::size_t  _totalRowCount;
+
+	friend class RowIterator;
+	friend class RowFilter;
+};
+
+
+///
+/// inlines
+///
+
+
+inline Data_API std::ostream& operator << (std::ostream &os, const RecordSet& rs)
+{
+	return rs.copy(os);
+}
+
+
+inline std::size_t RecordSet::getTotalRowCount() const
+{
+	if (UNKNOWN_TOTAL_ROW_COUNT == _totalRowCount)
+		return subTotalRowCount();
+	else
+		return _totalRowCount;
+}
+
+
+inline std::size_t RecordSet::totalRowCount() const
+{
+	return getTotalRowCount();
+}
+
+
+inline void RecordSet::setTotalRowCount(std::size_t totalRowCount)
+{
+	_totalRowCount = totalRowCount;
+}
+
+
+inline std::size_t RecordSet::extractedRowCount() const
+{
+	return rowsExtracted();
+}
+
+
+inline std::size_t RecordSet::columnCount() const
+{
+	return static_cast<std::size_t>(extractions().size());
+}
+
+
+inline Statement& RecordSet::operator = (const Statement& stmt)
+{
+	reset(stmt);
+	return *this;
+}
+
+
+inline Poco::Dynamic::Var RecordSet::value(const std::string& name)
+{
+	return value(name, _currentRow);
+}
+
+
+inline Poco::Dynamic::Var RecordSet::value(std::size_t index)
+{
+	return value(index, _currentRow);
+}
+
+
+inline Poco::Dynamic::Var RecordSet::operator [] (const std::string& name)
+{
+	return value(name, _currentRow);
+}
+
+
+inline Poco::Dynamic::Var RecordSet::operator [] (std::size_t index)
+{
+	return value(index, _currentRow);
+}
+
+
+inline MetaColumn::ColumnDataType RecordSet::columnType(std::size_t pos)const
+{
+	return metaColumn(static_cast<UInt32>(pos)).type();
+}
+
+
+inline MetaColumn::ColumnDataType RecordSet::columnType(const std::string& name)const
+{
+	return metaColumn(name).type();
+}
+
+
+inline const std::string& RecordSet::columnName(std::size_t pos) const
+{
+	return metaColumn(static_cast<UInt32>(pos)).name();
+}
+
+
+inline std::size_t RecordSet::columnLength(std::size_t pos) const
+{
+	return metaColumn(static_cast<UInt32>(pos)).length();
+}
+
+
+inline std::size_t RecordSet::columnLength(const std::string& name)const
+{
+	return metaColumn(name).length();
+}
+
+
+inline std::size_t RecordSet::columnPrecision(std::size_t pos) const
+{
+	return metaColumn(static_cast<UInt32>(pos)).precision();
+}
+
+
+inline std::size_t RecordSet::columnPrecision(const std::string& name)const
+{
+	return metaColumn(name).precision();
+}
+
+
+inline bool RecordSet::isNull(const std::string& name) const
+{
+	return isNull(metaColumn(name).position(), _currentRow);
+}
+
+
+inline RecordSet::ConstIterator& RecordSet::begin() const
+{
+	return *_pBegin;
+}
+
+
+inline RecordSet::ConstIterator& RecordSet::end() const
+{
+	return *_pEnd;
+}
+
+
+inline RecordSet::Iterator RecordSet::begin()
+{
+	return *_pBegin;
+}
+
+
+inline RecordSet::Iterator RecordSet::end()
+{
+	return *_pEnd;
+}
+
+
+inline const Poco::AutoPtr<RowFilter>& RecordSet::getFilter() const
+{
+	return _pFilter;
+}
+
+
+inline void RecordSet::formatNames() const
+{
+	(*_pBegin)->formatNames();
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_RecordSet_INCLUDED
diff --git a/Poco/Data/Row.h b/Poco/Data/Row.h
new file mode 100644
index 0000000..6144967
--- /dev/null
+++ b/Poco/Data/Row.h
@@ -0,0 +1,312 @@
+//
+// Row.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Row
+//
+// Definition of the Row class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Row_INCLUDED
+#define Data_Row_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/RowFormatter.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Tuple.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+#include <string>
+#include <ostream>
+
+
+namespace Poco {
+namespace Data {
+
+
+class RecordSet;
+
+
+class Data_API Row
+	/// Row class provides a data type for RecordSet iteration purposes.
+	/// Dereferencing a RowIterator returns Row.
+	/// Rows are sortable. The sortability is maintained at all times (i.e. there
+	/// is always at least one column specified as a sorting criteria) .
+	/// The default and minimal sorting criteria is the first field (position 0).
+	/// The default sorting criteria can be replaced with any other field by 
+	/// calling replaceSortField() member function.
+	/// Additional fields can be added to sorting criteria, in which case the
+	/// field precedence corresponds to addition order (i.e. later added fields
+	/// have lower sorting precedence).
+	/// These features make Row suitable for use with standard sorted 
+	/// containers and algorithms. The main constraint is that all the rows from
+	/// a set that is being sorted must have the same sorting criteria (i.e., the same
+	/// set of fields must be in sorting criteria in the same order). Since rows don't
+	/// know about each other, it is the programmer's responsibility to ensure this
+	/// constraint is satisfied.
+	/// Field names are a shared pointer to a vector of strings. For efficiency sake,
+	/// a constructor taking a shared pointer to names vector argument is provided.
+	/// The stream operator is provided for Row data type as a free-standing function.
+{
+public:
+	typedef RowFormatter::NameVec    NameVec;
+	typedef RowFormatter::NameVecPtr NameVecPtr;
+	typedef RowFormatter::ValueVec   ValueVec;
+
+	enum ComparisonType
+	{
+		COMPARE_AS_EMPTY,
+		COMPARE_AS_INTEGER,
+		COMPARE_AS_FLOAT,
+		COMPARE_AS_STRING
+	};
+
+	typedef Tuple<std::size_t, ComparisonType> SortTuple;
+	typedef std::vector<SortTuple>             SortMap;
+		/// The type for map holding fields used for sorting criteria.
+		/// Fields are added sequentially and have precedence that
+		/// corresponds to field adding sequence order (rather than field's 
+		/// position in the row).
+		/// This requirement rules out use of std::map due to its sorted nature.
+	typedef SharedPtr<SortMap> SortMapPtr;
+
+	Row();
+		/// Creates the Row.
+
+	Row(NameVecPtr pNames,
+		const RowFormatter::Ptr& pFormatter = 0);
+		/// Creates the Row.
+
+	Row(NameVecPtr pNames,
+		const SortMapPtr& pSortMap,
+		const RowFormatter::Ptr& pFormatter = 0);
+		/// Creates the Row.
+
+	~Row();
+		/// Destroys the Row.
+
+	Poco::Dynamic::Var& get(std::size_t col);
+		/// Returns the reference to data value at column location.
+
+	Poco::Dynamic::Var& operator [] (std::size_t col);
+		/// Returns the reference to data value at column location.
+
+	Poco::Dynamic::Var& operator [] (const std::string& name);
+		/// Returns the reference to data value at named column location.
+
+	template <typename T>
+	void append(const std::string& name, const T& val)
+		/// Appends the value to the row.
+	{
+		if (!_pNames) _pNames = new NameVec;
+		_values.push_back(val);
+		_pNames->push_back(name);
+		if (1 == _values.size()) addSortField(0);
+	}
+	
+	template <typename T>
+	void set(std::size_t pos, const T& val)
+		/// Assigns the value to the row.
+	{
+		try
+		{
+			_values.at(pos) = val;
+		}
+		catch (std::out_of_range&)
+		{
+			throw RangeException("Invalid column number.");
+		}
+	}
+
+	template <typename T>
+	void set(const std::string& name, const T& val)
+		/// Assigns the value to the row.
+	{
+		NameVec::iterator it = _pNames->begin();
+		NameVec::iterator end = _pNames->end();
+		for (int i = 0; it != end; ++it, ++i)
+		{
+			if (*it == name)
+				return set(i, val);
+		}
+
+		std::ostringstream os;
+		os << "Column with name " << name << " not found.";
+		throw NotFoundException(os.str());
+	}
+
+	std::size_t fieldCount() const;
+		/// Returns the number of fields in this row.
+
+	void reset();
+		/// Resets the row by clearing all field names and values.
+
+	void separator(const std::string& sep);
+		/// Sets the separator.
+
+	void addSortField(std::size_t pos);
+		/// Adds the field used for sorting.
+
+	void addSortField(const std::string& name);
+		/// Adds the field used for sorting.
+
+	void removeSortField(std::size_t pos);
+		/// Removes the field used for sorting.
+
+	void removeSortField(const std::string& name);
+		/// Removes the field used for sorting.
+
+	void replaceSortField(std::size_t oldPos, std::size_t newPos);
+		/// Replaces the field used for sorting.
+
+	void replaceSortField(const std::string& oldName, const std::string& newName);
+		/// Replaces the field used for sorting.
+
+	void resetSort();
+		/// Resets the sorting criteria to field 0 only.
+
+	const std::string& namesToString() const;
+		/// Converts the column names to string.
+
+	void formatNames() const;
+		/// Fomats the column names.
+
+	const std::string& valuesToString() const;
+		/// Converts the row values to string and returns the formated string.
+
+	void formatValues() const;
+		/// Fomats the row values.
+
+	bool operator == (const Row& other) const;
+		/// Equality operator.
+
+	bool operator != (const Row& other) const;
+		/// Inequality operator.
+
+	bool operator < (const Row& other) const;
+		/// Less-than operator.
+
+	const NameVecPtr names() const;
+		/// Returns the shared pointer to names vector.
+
+	const ValueVec& values() const;
+		/// Returns the const reference to values vector.
+
+	void setFormatter(const RowFormatter::Ptr& pFormatter = 0);
+		/// Sets the formatter for this row and takes the
+		/// shared ownership of it.
+
+	const RowFormatter& getFormatter() const;
+		/// Returns the reference to the formatter.
+
+	void setSortMap(const SortMapPtr& pSortMap = 0);
+		/// Adds the sorting fields entry and takes the
+		/// shared ownership of it.
+
+	const SortMapPtr& getSortMap() const;
+		/// Returns the reference to the sorting fields.
+
+private:
+	void init(const SortMapPtr& pSortMap, const RowFormatter::Ptr& pFormatter);
+
+	ValueVec& values();
+		/// Returns the reference to values vector.
+
+	std::size_t getPosition(const std::string& name);
+	bool isEqualSize(const Row& other) const;
+	bool isEqualType(const Row& other) const;
+
+	NameVecPtr                _pNames;
+	ValueVec                  _values;
+	SortMapPtr                _pSortMap;
+	mutable RowFormatter::Ptr _pFormatter;
+	mutable std::string       _nameStr;
+	mutable std::string       _valueStr;
+};
+
+
+Data_API std::ostream& operator << (std::ostream &os, const Row& row);
+
+
+///
+/// inlines
+///
+inline std::size_t Row::fieldCount() const
+{
+	return static_cast<std::size_t>(_values.size());
+}
+
+
+inline void Row::reset()
+{
+	_pNames->clear();
+	_values.clear();
+}
+
+
+inline const Row::NameVecPtr Row::names() const
+{
+	return _pNames;
+}
+
+
+inline const Row::ValueVec& Row::values() const
+{
+	return _values;
+}
+
+
+inline Row::ValueVec& Row::values()
+{
+	return _values;
+}
+
+
+inline Poco::Dynamic::Var& Row::operator [] (std::size_t col)
+{
+	return get(col);
+}
+
+
+inline Poco::Dynamic::Var& Row::operator [] (const std::string& name)
+{
+	return get(getPosition(name));
+}
+
+
+inline const RowFormatter& Row::getFormatter() const
+{
+	return *_pFormatter;
+}
+
+
+inline const Row::SortMapPtr& Row::getSortMap() const
+{
+	return _pSortMap;
+}
+
+
+inline const std::string& Row::valuesToString() const
+{
+	return _pFormatter->formatValues(values(), _valueStr);
+}
+
+
+inline void Row::formatValues() const
+{
+	return _pFormatter->formatValues(values());
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Row_INCLUDED
diff --git a/Poco/Data/RowFilter.h b/Poco/Data/RowFilter.h
new file mode 100644
index 0000000..0b0febd
--- /dev/null
+++ b/Poco/Data/RowFilter.h
@@ -0,0 +1,276 @@
+//
+// RowFilter.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  RowFilter
+//
+// Definition of the RowFilter class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_RowFilter_INCLUDED
+#define Data_RowFilter_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Tuple.h"
+#include "Poco/String.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <map>
+#include <list>
+#include <utility>
+
+
+namespace Poco {
+namespace Data {
+
+
+class RecordSet;
+
+
+class Data_API RowFilter: public RefCountedObject
+	/// RowFilter class provides row filtering functionality.
+	/// A filter contains a set of criteria (field name, value and
+	/// logical operation) for row filtering.
+	/// Additionally, a row filter contains a map of pointers to other
+	/// filters with related logical operations between filters.
+	/// RowFilter is typically added to recordset in order to filter
+	/// its content. Since the recordset own iteration is dependent upon
+	/// filtering, whenever the filtering criteria is changed,
+	/// the filter automatically notifies all associated recordsets
+	/// by rewinding them to the first position.
+{
+public:
+	enum Comparison
+	{
+		VALUE_LESS_THAN,
+		VALUE_LESS_THAN_OR_EQUAL,
+		VALUE_EQUAL,
+		VALUE_GREATER_THAN,
+		VALUE_GREATER_THAN_OR_EQUAL,
+		VALUE_NOT_EQUAL,
+		VALUE_IS_NULL
+	};
+
+	enum LogicOperator
+	{
+		OP_AND,
+		OP_OR,
+		OP_NOT
+	};
+
+	typedef bool (*CompT)(const Poco::Dynamic::Var&, const Poco::Dynamic::Var&);
+	typedef AutoPtr<RowFilter> Ptr;
+	typedef std::map<std::string, Comparison> Comparisons;
+	typedef Tuple<Poco::Dynamic::Var, Comparison, LogicOperator> ComparisonEntry;
+	typedef std::multimap<std::string, ComparisonEntry> ComparisonMap;
+	typedef std::map<AutoPtr<RowFilter>, LogicOperator> FilterMap;
+
+	RowFilter(RecordSet* pRecordSet);
+		/// Creates the top-level RowFilter and associates it with the recordset.
+
+	RowFilter(Ptr pParent, LogicOperator op = OP_OR);
+		/// Creates child RowFilter and associates it with the parent filter.
+
+	~RowFilter();
+		/// Destroys the RowFilter.
+
+	void addFilter(Ptr pFilter, LogicOperator comparison);
+		/// Appends another filter to this one.
+
+	void removeFilter(Ptr pFilter);
+		/// Removes filter from this filter.
+
+	bool has(Ptr pFilter) const;
+		/// Returns true if this filter is parent of pFilter;
+
+	template <typename T>
+	void add(const std::string& name, Comparison comparison, const T& value, LogicOperator op = OP_OR)
+		/// Adds value to the filter.
+	{
+		rewindRecordSet();
+		_comparisonMap.insert(ComparisonMap::value_type(toUpper(name),
+			ComparisonEntry(value, comparison, op)));
+	}
+
+	template <typename T>
+	void add(const std::string& name, const std::string& comp, const T& value, LogicOperator op = OP_OR)
+		/// Adds value to the filter.
+	{
+		add(name, getComparison(comp), value, op);
+	}
+
+	template <typename T>
+	void addAnd(const std::string& name, const std::string& comp, const T& value)
+		/// Adds logically AND-ed value to the filter.
+	{
+		add(name, getComparison(comp), value, OP_AND);
+	}
+
+	template <typename T>
+	void addOr(const std::string& name, const std::string& comp, const T& value)
+		/// Adds logically OR-ed value to the filter.
+	{
+		add(name, getComparison(comp), value, OP_OR);
+	}
+
+	int remove(const std::string& name);
+		/// Removes named comparisons from the filter.
+		/// All comparisons with specified name are removed.
+		/// Returns the number of comparisons removed.
+
+	void toggleNot();
+		/// Togless the NOT operator for this filter;
+
+	bool isNot() const;
+		/// Returns true if filter is NOT-ed, false otherwise.
+
+	bool isEmpty() const;
+		/// Returns true if there is not filtering criteria specified.
+
+	bool isAllowed(std::size_t row) const;
+		/// Returns true if name and value are allowed.
+
+	bool exists(const std::string& name) const;
+		/// Returns true if name is known to this row filter.
+
+private:
+	RowFilter();
+	RowFilter(const RowFilter&);
+	RowFilter& operator=(const RowFilter&);
+
+	void init();
+
+	static bool equal(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool notEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool less(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool greater(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool lessOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool greaterOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool logicalAnd(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool logicalOr(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2);
+	static bool isNull(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var&);
+
+	static void doCompare(Poco::Dynamic::Var& ret,
+		Poco::Dynamic::Var& val,
+		CompT comp,
+		const ComparisonEntry& ce);
+
+	RecordSet& recordSet() const;
+
+	Comparison getComparison(const std::string& comp) const;
+	
+	void rewindRecordSet();
+
+	Comparisons        _comparisons;
+	ComparisonMap      _comparisonMap;
+	mutable RecordSet* _pRecordSet;
+	Ptr                _pParent;
+	FilterMap          _filterMap;
+	bool               _not;
+
+	friend class RecordSet;
+};
+
+
+///
+/// inlines
+///
+
+
+inline bool RowFilter::has(Ptr pFilter) const
+{
+	return _filterMap.find(pFilter) != _filterMap.end();
+}
+
+
+inline bool RowFilter::isEmpty() const
+{
+	return _comparisonMap.size() == 0;
+}
+
+
+inline bool RowFilter::exists(const std::string& name) const
+{
+	return _comparisonMap.find(name) != _comparisonMap.end();
+}
+
+
+inline void RowFilter::toggleNot()
+{
+	_not = !_not;
+}
+
+
+inline bool RowFilter::isNot() const
+{
+	return _not;
+}
+
+
+inline bool RowFilter::equal(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 == p2;
+}
+
+
+inline bool RowFilter::notEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 != p2;
+}
+
+
+inline bool RowFilter::less(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 < p2;
+}
+
+
+inline bool RowFilter::greater(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 > p2;
+}
+
+
+inline bool RowFilter::lessOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 <= p2;
+}
+
+
+inline bool RowFilter::greaterOrEqual(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 >= p2;
+}
+
+
+inline bool RowFilter::logicalAnd(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 && p2;
+}
+
+
+inline bool RowFilter::logicalOr(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var& p2)
+{
+	return p1 || p2;
+}
+
+
+inline bool RowFilter::isNull(const Poco::Dynamic::Var& p1, const Poco::Dynamic::Var&)
+{
+	return p1.isEmpty();
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_RowFilter_INCLUDED
diff --git a/Poco/Data/RowFormatter.h b/Poco/Data/RowFormatter.h
new file mode 100644
index 0000000..a2a0c86
--- /dev/null
+++ b/Poco/Data/RowFormatter.h
@@ -0,0 +1,231 @@
+//
+// RowFormatter.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  RowFormatter
+//
+// Definition of the RowFormatter class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_RowFormatter_INCLUDED
+#define Data_RowFormatter_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Dynamic/Var.h"
+#include <sstream>
+#include <vector>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API RowFormatter
+	/// Row formatter is an abstract class providing definition for row formatting functionality.
+	/// For custom formatting strategies, inherit from this class and override formatNames()
+	/// and formatValues() member functions.
+	///
+	/// Row formatter can be either passed to the RecordSet at construction time,
+	/// like in the following example:
+	///
+	/// RecordSet rs(session. "SELECT * FROM Table", new MyRowFormater);
+	///
+	/// or it can be supplied to the statement as in the following example:
+	///
+	/// MyRowFormatter rf
+	/// session << "SELECT * FROM Table", format(rf);
+	///
+	/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is used.
+	/// Statement always has the ownership of the row formatter and shares
+	/// it with rows through RecordSet.
+	///
+	/// To accomodate for various formatting needs, a formatter can operate in two modes:
+	/// 
+	///	  - progressive: formatted individual row strings are gemerated and returned from each 
+	///     call to formatValues;
+	///     std::string& formatNames(const NameVecPtr, std::string&) and
+	///     std::string& formatValues(const ValueVec&, std::string&) member calls should be
+	///     used in this case; this is the default mode
+	///
+	///   - bulk: formatted resulting string is accumulated internally and obtained at
+	///     the end of iteration via toString() member function;
+	///     void formatNames(const NameVecPtr) and
+	///     void formatValues(const ValueVec&) member calls should be used in this case
+	///
+	/// When formatter is used in conjunction with Row/RecordSet, the formatting members corresponding
+	/// to the formater mode are expected to be implemented. If a call is propagated to this parent
+	/// class, the functions do nothing or silently return empty string respectively.
+	///
+{
+public:
+	typedef SharedPtr<RowFormatter>              Ptr;
+	typedef std::vector<std::string>             NameVec;
+	typedef SharedPtr<std::vector<std::string> > NameVecPtr;
+	typedef std::vector<Poco::Dynamic::Var>      ValueVec;
+
+	static const int INVALID_ROW_COUNT = -1;
+
+	enum Mode
+	{
+		FORMAT_PROGRESSIVE,
+		FORMAT_BULK
+	};
+
+	RowFormatter(const std::string& prefix = "",
+		const std::string& postfix = "",
+		Mode mode = FORMAT_PROGRESSIVE);
+		/// Creates the RowFormatter and sets the prefix and postfix to specified values.
+
+	virtual ~RowFormatter();
+		/// Destroys the RowFormatter.
+
+	virtual std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames);
+		/// Should be implemented to format the row fields names and return the formatted string.
+		/// The default implementation clears the names string and returns it.
+
+	virtual void formatNames(const NameVecPtr pNames);
+		/// Should be implemented to format the row fields names.
+		/// The default implementation does nothing.
+
+	virtual std::string& formatValues(const ValueVec& vals, std::string& formattedValues);
+		/// Should be implemented to format the row fields values and return the formatted string.
+		/// The default implementation clears the values string and returns it.
+
+	virtual void formatValues(const ValueVec& vals);
+		/// Should be implemented to format the row fields values.
+		/// The default implementation does nothing.
+
+	virtual const std::string& toString();
+		/// Throws NotImplementedException. Formatters operating in bulk mode should 
+		/// implement this member function to return valid pointer to the formatted result.
+
+	virtual int rowCount() const;
+		/// Returns INVALID_ROW_COUNT. Must be implemented by inheriting classes
+		/// which maintain count of processed rows.
+
+	int getTotalRowCount() const;
+		/// Returns zero. Must be implemented by inheriting classes.
+		/// Typically, total row count shall be set up front through
+		/// setTotalRowCount() call.
+
+	void setTotalRowCount(int count);
+		/// Sets total row count.
+
+	virtual const std::string& prefix() const;
+		/// Returns prefix string;
+
+	virtual const std::string& postfix() const;
+		/// Returns postfix string;
+
+	void reset();
+		/// Resets the formatter by setting prefix and postfix
+		/// to empty strings and row count to INVALID_ROW_COUNT.
+
+	Mode getMode() const;
+		/// Returns the formater mode.
+
+	void setMode(Mode mode);
+		/// Sets the fromatter mode.
+
+protected:
+
+	void setPrefix(const std::string& prefix);
+		/// Sets the prefix for the formatter.
+
+	void setPostfix(const std::string& postfix);
+		/// Sets the postfix for the formatter
+
+private:
+
+	mutable std::string _prefix;
+	mutable std::string _postfix;
+	Mode                _mode;
+	int                 _totalRowCount;
+};
+
+
+///
+/// inlines
+///
+inline int RowFormatter::rowCount() const
+{
+	return INVALID_ROW_COUNT;
+}
+
+
+inline int RowFormatter::getTotalRowCount() const
+{
+	return _totalRowCount;
+}
+
+
+inline void RowFormatter::setTotalRowCount(int count)
+{
+	_totalRowCount = count;
+}
+
+
+inline void RowFormatter::setPrefix(const std::string& prefix)
+{
+	_prefix = prefix;
+}
+
+
+inline void RowFormatter::setPostfix(const std::string& postfix)
+{
+	_postfix = postfix;
+}
+
+
+inline const std::string& RowFormatter::prefix() const
+{
+	return _prefix;
+}
+
+
+inline const std::string& RowFormatter::postfix() const
+{
+	return _postfix;
+}
+
+
+inline RowFormatter::Mode RowFormatter::getMode() const
+{
+	return _mode;
+}
+
+
+inline void RowFormatter::setMode(Mode mode)
+{
+	_mode = mode;
+}
+
+
+namespace Keywords {
+
+
+template <typename T>
+inline RowFormatter::Ptr format(const T& formatter)
+	/// Utility function used to pass formatter to the statement.
+{
+	return new T(formatter);
+}
+
+
+} // namespace Keywords
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_RowFormatter_INCLUDED
diff --git a/Poco/Data/RowIterator.h b/Poco/Data/RowIterator.h
new file mode 100644
index 0000000..32ca45b
--- /dev/null
+++ b/Poco/Data/RowIterator.h
@@ -0,0 +1,150 @@
+//
+// RowIterator.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  RowIterator
+//
+// Definition of the RowIterator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_RowIterator_INCLUDED
+#define Data_RowIterator_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Row.h"
+#include "Poco/Dynamic/Var.h"
+#include <iterator>
+#include <algorithm>
+
+
+namespace Poco {
+namespace Data {
+
+
+class RecordSet;
+
+
+class Data_API RowIterator
+	/// RowIterator class.
+{
+public:
+	typedef std::bidirectional_iterator_tag iterator_category;
+	typedef Row                             value_type;
+	typedef std::ptrdiff_t                  difference_type;
+	typedef Row*                            pointer;
+	typedef Row&                            reference;
+
+	static const std::size_t POSITION_END;
+		/// End position indicator.
+
+	RowIterator(RecordSet* pRecordSet, bool positionEnd);
+		/// Creates the RowIterator and positions it at the end of
+		/// the recordset if positionEnd is true. Otherwise, it is
+		/// positioned at the beginning.
+
+	RowIterator(const RowIterator& other);
+		/// Creates a copy of other RowIterator.
+
+	~RowIterator();
+		/// Destroys the RowIterator.
+
+	RowIterator& operator = (const RowIterator& other);
+		/// Assigns the other RowIterator.
+
+	bool operator == (const RowIterator& other) const;
+		/// Equality operator.
+
+	bool operator != (const RowIterator& other) const;
+		/// Inequality operator.
+
+	Row& operator * () const;
+		/// Returns reference to the current row.
+
+	Row* operator -> () const;
+		/// Returns pointer to the current row.
+
+	const RowIterator& operator ++ () const;
+		/// Advances by one position and returns current position.
+
+	RowIterator operator ++ (int) const;
+		/// Advances by one position and returns copy of the iterator with 
+		/// previous current position.
+
+	const RowIterator& operator -- () const;
+		/// Goes back by one position and returns copy of the iterator with 
+		/// previous current position.
+
+	RowIterator operator -- (int) const;
+		/// Goes back by one position and returns previous current position.
+
+	RowIterator operator + (std::size_t diff) const;
+		/// Returns a copy the RowIterator advanced by diff positions.
+
+	RowIterator operator - (std::size_t diff) const;
+		/// Returns a copy the RowIterator backed by diff positions.
+		/// Throws RangeException if diff is larger than current position.
+
+	void swap(RowIterator& other);
+		/// Swaps the RowIterator with another one.
+
+private:
+	RowIterator();
+
+	void increment() const;
+		/// Increments the iterator position by one. 
+		/// Throws RangeException if position is out of range.
+
+	void decrement() const;
+		/// Decrements the iterator position by one. 
+		/// Throws RangeException if position is out of range.
+
+	void setPosition(std::size_t pos) const;
+		/// Sets the iterator position. 
+		/// Throws RangeException if position is out of range.
+
+	RecordSet*          _pRecordSet;
+	mutable std::size_t _position;
+};
+
+
+///
+/// inlines
+///
+
+
+inline bool RowIterator::operator == (const RowIterator& other) const
+{
+	return _pRecordSet == other._pRecordSet && _position == other._position;
+}
+
+
+inline bool RowIterator::operator != (const RowIterator& other) const
+{
+	return _pRecordSet != other._pRecordSet || _position != other._position;
+}
+
+
+} } // namespace Poco::Data
+
+
+namespace std
+{
+	template<>
+	inline void swap<Poco::Data::RowIterator>(Poco::Data::RowIterator& s1, 
+		Poco::Data::RowIterator& s2)
+		/// Full template specalization of std:::swap for RowIterator
+	{
+		s1.swap(s2);
+	}
+}
+
+
+#endif // Data_RowIterator_INCLUDED
diff --git a/Poco/Data/SQLChannel.h b/Poco/Data/SQLChannel.h
new file mode 100644
index 0000000..e76d676
--- /dev/null
+++ b/Poco/Data/SQLChannel.h
@@ -0,0 +1,217 @@
+//
+// SQLChannel.h
+//
+// Library: Data
+// Package: Logging
+// Module:  SQLChannel
+//
+// Definition of the SQLChannel class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SQLChannel_INCLUDED
+#define Data_SQLChannel_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Connector.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Data/Statement.h"
+#include "Poco/Data/ArchiveStrategy.h"
+#include "Poco/Channel.h"
+#include "Poco/Message.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/String.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API SQLChannel: public Poco::Channel
+	/// This Channel implements logging to a SQL database.
+	/// The channel is dependent on the schema. The DDL for
+	/// table creation (subject to target DDL dialect dependent 
+	/// modifications) is:
+	///
+	/// "CREATE TABLE T_POCO_LOG (Source VARCHAR, 
+	///		Name VARCHAR, 
+	///		ProcessId INTEGER, 
+	///		Thread VARCHAR, 
+	///		ThreadId INTEGER, 
+	///		Priority INTEGER, 
+	///		Text VARCHAR, 
+	///		DateTime DATE)"
+	///
+	/// The table name is configurable through "table" property. 
+	/// Other than DateTime filed name used for optiona time-based archiving purposes, currently the 
+	/// field names are not mandated. However, it is recomended to use names as specified above.
+	/// 
+	/// To provide as non-intrusive operation as possbile, the log entries are cached and 
+	/// inserted into the target database asynchronously by default . The blocking, however, will occur 
+	/// before the next entry insertion with default timeout of 1 second. The default settings can be 
+	/// overriden (see async, timeout and throw properties for details).
+	/// If throw property is false, insertion timeouts are ignored, otherwise a TimeoutException is thrown.
+	/// To force insertion of every entry, set timeout to 0. This setting, however, introduces
+	/// a risk of long blocking periods in case of remote server communication delays.
+{
+public:
+	SQLChannel();
+		/// Creates SQLChannel.
+
+	SQLChannel(const std::string& connector, 
+		const std::string& connect,
+		const std::string& name = "-");
+		/// Creates a SQLChannel with the given connector, connect string, timeout, table and name.
+		/// The connector must be already registered.
+	
+	void open();
+		/// Opens the SQLChannel.
+		
+	void close();
+		/// Closes the SQLChannel.
+		
+	void log(const Message& msg);
+		/// Sends the message's text to the syslog service.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given value.
+		///
+		/// The following properties are supported:
+		///     * name:      The name used to identify the source of log messages.
+		///                  Defaults to "-".
+		///
+		///     * target:    The target data storage type ("SQLite", "ODBC", ...).
+		///
+		///     * connector: The target data storage connector name.
+		///
+		///     * connect:   The target data storage connection string.
+		///
+		///     * table:     Destination log table name. Defaults to "T_POCO_LOG".
+		///                  Table must exist in the target database.
+		///
+		///     * keep:      Max row age for the log table. To disable archiving,
+		///                  set this property to empty string or "forever".
+		///
+		///     * archive:   Archive table name. Defaults to "T_POCO_LOG_ARCHIVE".
+		///                  Table must exist in the target database. To disable archiving,
+		///                  set this property to empty string.
+		///
+		///     * async:     Indicates asynchronous execution. When excuting asynchronously,
+		///                  messages are sent to the target using asyncronous execution.
+		///                  However, prior to the next message being processed and sent to
+		///                  the target, the previous operation must have been either completed 
+		///                  or timed out (see timeout and throw properties for details on
+		///                  how abnormal conditos are handled).
+		///
+		///     * timeout:   Timeout (ms) to wait for previous log operation completion.
+		///                  Values "0" and "" mean no timeout. Only valid when logging
+		///                  is asynchronous, otherwise ignored.
+		///
+		///     * throw:     Boolean value indicating whether to throw in case of timeout.
+		///                  Setting this property to false may result in log entries being lost.
+		///                  True values are (case insensitive) "true", "t", "yes", "y".
+		///                  Anything else yields false.
+		
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+
+	std::size_t wait();
+		/// Waits for the completion of the previous operation and returns
+		/// the result. If chanel is in synchronous mode, returns 0 immediately.
+
+	static void registerChannel();
+		/// Registers the channel with the global LoggingFactory.
+
+	static const std::string PROP_CONNECT;
+	static const std::string PROP_CONNECTOR;
+	static const std::string PROP_NAME;
+	static const std::string PROP_TABLE;
+	static const std::string PROP_ARCHIVE_TABLE;
+	static const std::string PROP_MAX_AGE;
+	static const std::string PROP_ASYNC;
+	static const std::string PROP_TIMEOUT;
+	static const std::string PROP_THROW;
+
+protected:
+	~SQLChannel();
+
+private:
+	typedef Poco::SharedPtr<Session>         SessionPtr;
+	typedef Poco::SharedPtr<Statement>       StatementPtr;
+	typedef Poco::Message::Priority          Priority;
+	typedef Poco::SharedPtr<ArchiveStrategy> StrategyPtr;
+
+	void initLogStatement();
+		/// Initiallizes the log statement.
+
+	void initArchiveStatements();
+	/// Initiallizes the archive statement.
+
+	void logAsync(const Message& msg);
+		/// Waits for previous operation completion and
+		/// calls logSync(). If the previous operation times out,
+		/// and _throw is true, TimeoutException is thrown, oterwise
+		/// the timeout is ignored and log entry is lost.
+
+	void logSync(const Message& msg);
+		/// Inserts the message in the target database.
+
+	bool isTrue(const std::string& value) const;
+		/// Returns true is value is "true", "t", "yes" or "y".
+		/// Case insensitive.
+
+	std::string  _connector;
+	std::string  _connect;
+	SessionPtr   _pSession;
+	StatementPtr _pLogStatement;
+	std::string  _name;
+	std::string  _table;
+	int          _timeout;
+	bool         _throw;
+	bool         _async;
+	
+	// members for log entry cache (needed for async mode)
+	std::string _source;
+	long        _pid;
+	std::string _thread;
+	long        _tid;
+	int         _priority;
+	std::string _text;
+	DateTime    _dateTime;
+
+	StrategyPtr _pArchiveStrategy;
+};
+
+
+//
+// inlines
+//
+
+inline std::size_t SQLChannel::wait()
+{
+	if (_async && _pLogStatement) 
+		return _pLogStatement->wait(_timeout);
+	
+	return 0;
+}
+
+
+inline bool SQLChannel::isTrue(const std::string& value) const
+{
+	return ((0 == icompare(value, "true")) ||
+			(0 == icompare(value, "t")) ||
+			(0 == icompare(value, "yes")) ||
+			(0 == icompare(value, "y")));
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_SQLChannel_INCLUDED
diff --git a/Poco/Data/SQLite/Binder.h b/Poco/Data/SQLite/Binder.h
new file mode 100644
index 0000000..90618d6
--- /dev/null
+++ b/Poco/Data/SQLite/Binder.h
@@ -0,0 +1,220 @@
+//
+// Binder.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  Binder
+//
+// Definition of the Binder class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SQLite_Binder_INCLUDED
+#define Data_SQLite_Binder_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/AbstractBinder.h"
+#include "Poco/Data/LOB.h"
+#include "Poco/Any.h"
+#include "Poco/DynamicAny.h"
+#include "sqlite3.h"
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API Binder: public Poco::Data::AbstractBinder
+	/// Binds placeholders in the sql query to the provided values. Performs data types mapping.
+{
+public:
+	Binder(sqlite3_stmt* pStmt);
+		/// Creates the Binder.
+
+	~Binder();
+		/// Destroys the Binder.
+
+	void bind(std::size_t pos, const Poco::Int8 &val, Direction dir);
+		/// Binds an Int8.
+
+	void bind(std::size_t pos, const Poco::UInt8 &val, Direction dir);
+		/// Binds an UInt8.
+
+	void bind(std::size_t pos, const Poco::Int16 &val, Direction dir);
+		/// Binds an Int16.
+
+	void bind(std::size_t pos, const Poco::UInt16 &val, Direction dir);
+		/// Binds an UInt16.
+
+	void bind(std::size_t pos, const Poco::Int32 &val, Direction dir);
+		/// Binds an Int32.
+
+	void bind(std::size_t pos, const Poco::UInt32 &val, Direction dir);
+		/// Binds an UInt32.
+
+	void bind(std::size_t pos, const Poco::Int64 &val, Direction dir);
+		/// Binds an Int64.
+
+	void bind(std::size_t pos, const Poco::UInt64 &val, Direction dir);
+		/// Binds an UInt64.
+
+#ifndef POCO_LONG_IS_64_BIT
+	void bind(std::size_t pos, const long &val, Direction dir);
+		/// Binds a long
+
+	void bind(std::size_t pos, const unsigned long &val, Direction dir);
+		/// Binds an unsigned long
+#endif
+
+	void bind(std::size_t pos, const bool &val, Direction dir);
+		/// Binds a boolean.
+
+	void bind(std::size_t pos, const float &val, Direction dir);
+		/// Binds a float.
+
+	void bind(std::size_t pos, const double &val, Direction dir);
+		/// Binds a double.
+
+	void bind(std::size_t pos, const char &val, Direction dir);
+		/// Binds a single character.
+
+	void bind(std::size_t pos, const char* const &pVal, Direction dir);
+		/// Binds a const char ptr.
+
+	void bind(std::size_t pos, const std::string& val, Direction dir);
+		/// Binds a string.
+
+	void bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir);
+		/// Binds a BLOB.
+
+	void bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir);
+		/// Binds a CLOB.
+
+	void bind(std::size_t pos, const Date& val, Direction dir);
+		/// Binds a Date.
+
+	void bind(std::size_t pos, const Time& val, Direction dir);
+		/// Binds a Time.
+
+	void bind(std::size_t pos, const DateTime& val, Direction dir);
+		/// Binds a DateTime.
+
+	void bind(std::size_t pos, const NullData& val, Direction dir);
+		/// Binds a null.
+
+private:
+	void checkReturn(int rc);
+		/// Checks the SQLite return code and throws an appropriate exception
+		/// if error has occurred.
+
+	template <typename T>
+	void bindLOB(std::size_t pos, const Poco::Data::LOB<T>& val, Direction dir)
+	{
+		// convert a blob to a an unsigned char* array
+		const T* pData = reinterpret_cast<const T*>(val.rawContent());
+		int valSize = static_cast<int>(val.size());
+
+		int rc = sqlite3_bind_blob(_pStmt, static_cast<int>(pos), pData, valSize, SQLITE_STATIC); // no deep copy, do not free memory
+		checkReturn(rc);
+	}
+
+	sqlite3_stmt* _pStmt;
+};
+
+
+//
+// inlines
+//
+inline void Binder::bind(std::size_t pos, const Poco::Int8 &val, Direction dir)
+{
+	Poco::Int32 tmp = val;
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt8 &val, Direction dir)
+{
+	Poco::Int32 tmp = val;
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::Int16 &val, Direction dir)
+{
+	Poco::Int32 tmp = val;
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt16 &val, Direction dir)
+{
+	Poco::Int32 tmp = val;
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt32 &val, Direction dir)
+{
+	Poco::Int32 tmp = static_cast<Poco::Int32>(val);
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::UInt64 &val, Direction dir)
+{
+	Poco::Int64 tmp = static_cast<Poco::Int64>(val);
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const bool &val, Direction dir)
+{
+	Poco::Int32 tmp = (val ? 1 : 0);
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const float &val, Direction dir)
+{
+	double tmp = val;
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const char &val, Direction dir)
+{
+	Poco::Int32 tmp = val;
+	bind(pos, tmp, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const char* const &pVal, Direction dir)
+{
+	std::string val(pVal);
+	bind(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::Data::BLOB& val, Direction dir)
+{
+	bindLOB<Poco::Data::BLOB::ValueType>(pos, val, dir);
+}
+
+
+inline void Binder::bind(std::size_t pos, const Poco::Data::CLOB& val, Direction dir)
+{
+	bindLOB<Poco::Data::CLOB::ValueType>(pos, val, dir);
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // Data_SQLite_Binder_INCLUDED
diff --git a/Poco/Data/SQLite/Connector.h b/Poco/Data/SQLite/Connector.h
new file mode 100644
index 0000000..4d5173c
--- /dev/null
+++ b/Poco/Data/SQLite/Connector.h
@@ -0,0 +1,79 @@
+//
+// Connector.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  Connector
+//
+// Definition of the Connector class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SQLite_Connector_INCLUDED
+#define Data_SQLite_Connector_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/Connector.h"
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API Connector: public Poco::Data::Connector
+	/// Connector instantiates SqLite SessionImpl objects.
+{
+public:
+	static const std::string KEY;
+		/// Keyword for creating SQLite sessions ("sqlite").
+
+	Connector();
+		/// Creates the Connector.
+
+	~Connector();
+		/// Destroys the Connector.
+
+	const std::string& name() const;
+		/// Returns the name associated with this connector.
+
+	Poco::AutoPtr<Poco::Data::SessionImpl> createSession(const std::string& connectionString,
+		std::size_t timeout = Poco::Data::SessionImpl::LOGIN_TIMEOUT_DEFAULT);
+		/// Creates a SQLite SessionImpl object and initializes it with the given connectionString.
+
+	static void registerConnector();
+		/// Registers the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory.
+
+	static void unregisterConnector();
+		/// Unregisters the Connector under the Keyword Connector::KEY at the Poco::Data::SessionFactory.
+
+	static void enableSharedCache(bool flag = true);
+		/// Enables or disables SQlite shared cache mode
+		/// (see http://www.sqlite.org/sharedcache.html for a discussion).
+
+	static void enableSoftHeapLimit(int limit);
+		/// Sets a soft upper limit to the amount of memory allocated
+		/// by SQLite. For more information, please see the SQLite
+		/// sqlite_soft_heap_limit() function (http://www.sqlite.org/c3ref/soft_heap_limit.html).
+};
+
+
+///
+/// inlines
+///
+inline const std::string& Connector::name() const
+{
+	return KEY;
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // Data_SQLite_Connector_INCLUDED
diff --git a/Poco/Data/SQLite/Extractor.h b/Poco/Data/SQLite/Extractor.h
new file mode 100644
index 0000000..424cca4
--- /dev/null
+++ b/Poco/Data/SQLite/Extractor.h
@@ -0,0 +1,313 @@
+//
+// Extractor.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  Extractor
+//
+// Definition of the Extractor class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SQLite_Extractor_INCLUDED
+#define Data_SQLite_Extractor_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/SQLite/Utility.h"
+#include "Poco/Data/AbstractExtractor.h"
+#include "Poco/Data/MetaColumn.h"
+#include "Poco/Data/DataException.h"
+#include "Poco/Data/Constants.h"
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.h"
+#include "Poco/Data/Date.h"
+#include "Poco/Data/Time.h"
+#include "Poco/Any.h"
+#include "Poco/DynamicAny.h"
+#include "sqlite3.h"
+#include <vector>
+#include <utility>
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API Extractor: public Poco::Data::AbstractExtractor
+	/// Extracts and converts data values form the result row returned by SQLite.
+	/// If NULL is received, the incoming val value is not changed and false is returned
+{
+public:
+	typedef std::vector<std::pair<bool, bool> > NullIndVec;
+		/// Type for null indicators container.
+
+	Extractor(sqlite3_stmt* pStmt);
+		/// Creates the Extractor.
+
+	~Extractor();
+		/// Destroys the Extractor.
+
+	bool extract(std::size_t pos, Poco::Int8& val);
+		/// Extracts an Int8.
+
+	bool extract(std::size_t pos, Poco::UInt8& val);
+		/// Extracts an UInt8.
+
+	bool extract(std::size_t pos, Poco::Int16& val);
+		/// Extracts an Int16.
+
+	bool extract(std::size_t pos, Poco::UInt16& val);
+		/// Extracts an UInt16.
+
+	bool extract(std::size_t pos, Poco::Int32& val);
+		/// Extracts an Int32.
+
+	bool extract(std::size_t pos, Poco::UInt32& val);
+		/// Extracts an UInt32.
+
+	bool extract(std::size_t pos, Poco::Int64& val);
+		/// Extracts an Int64.
+
+	bool extract(std::size_t pos, Poco::UInt64& val);
+		/// Extracts an UInt64.
+
+#ifndef POCO_LONG_IS_64_BIT
+	bool extract(std::size_t pos, long& val);
+		/// Extracts a long.
+
+	bool extract(std::size_t pos, unsigned long& val);
+		/// Extracts an unsigned long.
+#endif
+
+	bool extract(std::size_t pos, bool& val);
+		/// Extracts a boolean.
+
+	bool extract(std::size_t pos, float& val);
+		/// Extracts a float.
+
+	bool extract(std::size_t pos, double& val);
+		/// Extracts a double.
+
+	bool extract(std::size_t pos, char& val);
+		/// Extracts a single character.
+
+	bool extract(std::size_t pos, std::string& val);
+		/// Extracts a string.
+
+	bool extract(std::size_t pos, Poco::Data::BLOB& val);
+		/// Extracts a BLOB.
+
+	bool extract(std::size_t pos, Poco::Data::CLOB& val);
+		/// Extracts a CLOB.
+
+	bool extract(std::size_t pos, Poco::Data::Date& val);
+		/// Extracts a Date.
+
+	bool extract(std::size_t pos, Poco::Data::Time& val);
+		/// Extracts a Time.
+
+	bool extract(std::size_t pos, Poco::DateTime& val);
+		/// Extracts a DateTime.
+
+	bool extract(std::size_t pos, Poco::Any& val);
+		/// Extracts an Any.
+
+	bool extract(std::size_t pos, Poco::DynamicAny& val);
+		/// Extracts a DynamicAny.
+
+	bool isNull(std::size_t pos, std::size_t row = POCO_DATA_INVALID_ROW);
+		/// Returns true if the current row value at pos column is null.
+		/// Because of the loss of information about null-ness of the 
+		/// underlying database values due to the nature of SQLite engine, 
+		/// (once null value is converted to default value, SQLite API 
+		/// treats it  as non-null), a null indicator container member
+		/// variable is used to cache the indicators of the underlying nulls 
+		/// thus rendering this function idempotent. 
+		/// The container is a vector of [bool, bool] pairs.
+		/// The vector index corresponds to the column position, the first
+		/// bool value in the pair is true if the null indicator has 
+		/// been set and the second bool value in the pair is true if
+		/// the column is actually null.
+		/// The row argument, needed for connectors with bulk capabilities,
+		/// is ignored in this implementation.
+
+	void reset();
+		/// Clears the cached nulls indicator vector.
+
+private:
+	template <typename T>
+	bool extractImpl(std::size_t pos, T& val)
+		/// Utility function for extraction of Any and DynamicAny.
+	{
+		if (isNull(pos)) return false;
+
+		bool ret = false;
+
+		switch (Utility::getColumnType(_pStmt, pos))
+		{
+		case MetaColumn::FDT_BOOL:
+		{
+			bool i = false;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_INT8:
+		{
+			Poco::Int8 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_UINT8:
+		{
+			Poco::UInt8 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_INT16:
+		{
+			Poco::Int16 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_UINT16:
+		{
+			Poco::UInt16 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_INT32:
+		{
+			Poco::Int32 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_UINT32:
+		{
+			Poco::UInt32 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_INT64:
+		{
+			Poco::Int64 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_UINT64:
+		{
+			Poco::UInt64 i = 0;
+			ret = extract(pos, i); 
+			val = i;
+			break;
+		}
+		case MetaColumn::FDT_STRING:
+		{
+			std::string s;
+			ret = extract(pos, s); 
+			val = s;
+			break;
+		}
+		case MetaColumn::FDT_DOUBLE:
+		{
+			double d(0.0);
+			ret = extract(pos, d); 
+			val = d;
+			break;
+		}
+		case MetaColumn::FDT_FLOAT:
+		{
+			float f(0.0);
+			ret = extract(pos, f); 
+			val = f;
+			break;
+		}
+		case MetaColumn::FDT_BLOB:
+		{
+			BLOB b;
+			ret = extract(pos, b); 
+			val = b;
+			break;
+		}
+		case MetaColumn::FDT_DATE:
+		{
+			Date d;
+			ret = extract(pos, d); 
+			val = d;
+			break;
+		}
+		case MetaColumn::FDT_TIME:
+		{
+			Time t;
+			ret = extract(pos, t); 
+			val = t;
+			break;
+		}
+		case MetaColumn::FDT_TIMESTAMP:
+		{
+			DateTime dt;
+			ret = extract(pos, dt); 
+			val = dt;
+			break;
+		}
+		default:
+			throw Poco::Data::UnknownTypeException("Unknown type during extraction");
+		}
+
+		return ret;
+	}
+
+	template <typename T>
+	bool extractLOB(std::size_t pos, Poco::Data::LOB<T>& val)
+	{
+		if (isNull(pos)) return false;
+		int size = sqlite3_column_bytes(_pStmt, (int) pos);
+		const T* pTmp = reinterpret_cast<const T*>(sqlite3_column_blob(_pStmt, (int) pos));
+		val = Poco::Data::LOB<T>(pTmp, size);
+		return true;
+	}
+
+	sqlite3_stmt* _pStmt;
+	NullIndVec    _nulls;
+};
+
+
+///
+/// inlines
+///
+inline void Extractor::reset()
+{
+	_nulls.clear();
+}
+
+
+inline bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
+{
+	return extractLOB<Poco::Data::BLOB::ValueType>(pos, val);
+}
+
+
+inline bool Extractor::extract(std::size_t pos, Poco::Data::CLOB& val)
+{
+	return extractLOB<Poco::Data::CLOB::ValueType>(pos, val);
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // Data_SQLite_Extractor_INCLUDED
diff --git a/Poco/Data/SQLite/Notifier.h b/Poco/Data/SQLite/Notifier.h
new file mode 100644
index 0000000..51f36f1
--- /dev/null
+++ b/Poco/Data/SQLite/Notifier.h
@@ -0,0 +1,195 @@
+//
+// Notifier.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  Notifier
+//
+// Definition of Notifier.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SQLite_Notifier_INCLUDED
+#define SQLite_Notifier_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/SQLite/Utility.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Mutex.h"
+#include "Poco/Types.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/BasicEvent.h"
+#include <map>
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API Notifier
+	/// Notifier is a wrapper for SQLite callback calls. It supports event callbacks
+	/// for insert, update, delete, commit and rollback events. While (un)registering 
+	/// callbacks is thread-safe, execution of the callbacks themselves are not; 
+	/// it is the user's responsibility to ensure the thread-safey of the functions 
+	/// they provide as callback target. Additionally, commit callbacks may prevent
+	/// database transactions from succeeding (see sqliteCommitCallbackFn documentation
+	/// for details). 
+	/// 
+	/// There can be only one set of callbacks per session (i.e. registering a new
+	/// callback automatically unregisters the previous one). All callbacks are 
+	/// registered and enabled at Notifier contruction time and can be disabled
+	/// at a later point time.
+{
+public:
+	typedef unsigned char EnabledEventType;
+		/// A type definition for events-enabled bitmap.
+
+	typedef Poco::BasicEvent<void> Event;
+
+	// 
+	// Events
+	// 
+	Event update;
+	Event insert;
+	Event erase;
+	Event commit;
+	Event rollback;
+
+	// Event types.
+	static const EnabledEventType SQLITE_NOTIFY_UPDATE   = 1;
+	static const EnabledEventType SQLITE_NOTIFY_COMMIT   = 2;
+	static const EnabledEventType SQLITE_NOTIFY_ROLLBACK = 4;
+
+	Notifier(const Session& session,
+		EnabledEventType enabled = SQLITE_NOTIFY_UPDATE | SQLITE_NOTIFY_COMMIT | SQLITE_NOTIFY_ROLLBACK);
+			/// Creates a Notifier and enables all callbacks.
+
+	Notifier(const Session& session,
+		const Any& value,
+		EnabledEventType enabled = SQLITE_NOTIFY_UPDATE | SQLITE_NOTIFY_COMMIT | SQLITE_NOTIFY_ROLLBACK);
+			/// Creates a Notifier, assigns the value to the internal storage and and enables all callbacks.
+
+	~Notifier();
+		/// Disables all callbacks and destroys the Notifier.
+
+	bool enableUpdate();
+		/// Enables update callbacks.
+
+	bool disableUpdate();
+		/// Disables update callbacks.
+
+	bool updateEnabled() const;
+		/// Returns true if update callbacks are enabled, false otherwise.
+
+	bool enableCommit();
+		/// Enables commit callbacks.
+
+	bool disableCommit();
+		/// Disables commit callbacks.
+
+	bool commitEnabled() const;
+		/// Returns true if update callbacks are enabled, false otherwise.
+
+	bool enableRollback();
+		/// Enables rollback callbacks.
+
+	bool disableRollback();
+		/// Disables rollback callbacks.
+
+	bool rollbackEnabled() const;
+		/// Returns true if rollback callbacks are enabled, false otherwise.
+
+	bool enableAll();
+		/// Enables all callbacks.
+
+	bool disableAll();
+		/// Disables all callbacks.
+
+	static void sqliteUpdateCallbackFn(void* pVal, int opCode, const char* pDB, const char* pTable, Poco::Int64 row);
+		/// Update callback event dispatcher. Determines the type of the event, updates the row number 
+		/// and triggers the event.
+
+	static int sqliteCommitCallbackFn(void* pVal);
+		/// Commit callback event dispatcher. If an exception occurs, it is catched inside this function,
+		/// non-zero value is returned, which causes SQLite engine to turn commit into a rollback.
+		/// Therefore, callers should check for return value - if it is zero, callback completed succesfuly
+		/// and transaction was committed.
+
+	static void sqliteRollbackCallbackFn(void* pVal);
+		/// Rollback callback event dispatcher.
+
+	bool operator == (const Notifier& other) const;
+		/// Equality operator. Compares value, row and database handles and
+		/// returns true iff all are equal.
+
+	Poco::Int64 getRow() const;
+		/// Returns the row number.
+
+	void setRow(Poco::Int64 row);
+		/// Sets the row number.
+
+	const Poco::Dynamic::Var& getValue() const;
+		/// Returns the value.
+
+	template <typename T>
+	inline void setValue(const T& val)
+		/// Sets the value.
+	{
+		_value = val;
+	}
+
+private:
+	Notifier();
+	Notifier(const Notifier&);
+	Notifier& operator=(const Notifier&);
+
+	const Session&     _session;
+	Poco::Dynamic::Var _value;
+	Poco::Int64        _row;
+	EnabledEventType   _enabledEvents;
+	Poco::Mutex        _mutex;
+};
+
+
+// 
+// inlines
+// 
+
+inline bool Notifier::operator == (const Notifier& other) const
+{
+	return _value == other._value &&
+		_row == other._row &&
+		Utility::dbHandle(_session) == Utility::dbHandle(other._session);
+}
+
+
+inline Poco::Int64 Notifier::getRow() const
+{
+	return _row;
+}
+
+
+inline void Notifier::setRow(Poco::Int64 row)
+	/// Sets the row number.
+{
+	_row = row;
+}
+
+
+inline const Poco::Dynamic::Var& Notifier::getValue() const
+{
+	return _value;
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // SQLite_Notifier_INCLUDED
diff --git a/Poco/Data/SQLite/SQLite.h b/Poco/Data/SQLite/SQLite.h
new file mode 100644
index 0000000..253d235
--- /dev/null
+++ b/Poco/Data/SQLite/SQLite.h
@@ -0,0 +1,62 @@
+//
+// SQLite.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  SQLite
+//
+// Basic definitions for the Poco SQLite library.
+// This file must be the first file included by every other SQLite
+// header file.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SQLite_SQLite_INCLUDED
+#define SQLite_SQLite_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the SQLite_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// SQLite_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(SQLite_EXPORTS)
+		#define SQLite_API __declspec(dllexport)
+	#else
+		#define SQLite_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(SQLite_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define SQLite_API __attribute__ ((visibility ("default")))
+	#else
+		#define SQLite_API
+	#endif
+#endif
+
+
+//
+// Automatically link SQLite library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(SQLite_EXPORTS)
+		#pragma comment(lib, "PocoDataSQLite" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // SQLite_SQLite_INCLUDED
diff --git a/Poco/Data/SQLite/SQLiteException.h b/Poco/Data/SQLite/SQLiteException.h
new file mode 100644
index 0000000..7c067a7
--- /dev/null
+++ b/Poco/Data/SQLite/SQLiteException.h
@@ -0,0 +1,60 @@
+//
+// SQLiteException.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  SQLiteException
+//
+// Definition of SQLiteException.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SQLite_SQLiteException_INCLUDED
+#define SQLite_SQLiteException_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/DataException.h"
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+POCO_DECLARE_EXCEPTION(SQLite_API, SQLiteException, Poco::Data::DataException)
+POCO_DECLARE_EXCEPTION(SQLite_API, InvalidSQLStatementException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, InternalDBErrorException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, DBAccessDeniedException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, ExecutionAbortedException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, DBLockedException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, TableLockedException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, NoMemoryException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, ReadOnlyException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, InterruptException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, IOErrorException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, CorruptImageException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, TableNotFoundException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, DatabaseFullException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, CantOpenDBFileException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, LockProtocolException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, SchemaDiffersException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, RowTooBigException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, ConstraintViolationException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, DataTypeMismatchException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, ParameterCountMismatchException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, InvalidLibraryUseException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, OSFeaturesMissingException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, AuthorizationDeniedException, SQLiteException)
+POCO_DECLARE_EXCEPTION(SQLite_API, TransactionException, SQLiteException)
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif
diff --git a/Poco/Data/SQLite/SQLiteStatementImpl.h b/Poco/Data/SQLite/SQLiteStatementImpl.h
new file mode 100644
index 0000000..1044beb
--- /dev/null
+++ b/Poco/Data/SQLite/SQLiteStatementImpl.h
@@ -0,0 +1,155 @@
+//
+// SQLiteStatementImpl.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  SQLiteStatementImpl
+//
+// Definition of the SQLiteStatementImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SQLite_SQLiteStatementImpl_INCLUDED
+#define Data_SQLite_SQLiteStatementImpl_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/SQLite/Binder.h"
+#include "Poco/Data/SQLite/Extractor.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/Data/MetaColumn.h"
+#include "Poco/SharedPtr.h"
+
+
+extern "C"
+{
+	typedef struct sqlite3 sqlite3;
+	typedef struct sqlite3_stmt sqlite3_stmt;
+}
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API SQLiteStatementImpl: public Poco::Data::StatementImpl
+	/// Implements statement functionality needed for SQLite
+{
+public:
+	SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB);
+		/// Creates the SQLiteStatementImpl.
+
+	~SQLiteStatementImpl();
+		/// Destroys the SQLiteStatementImpl.
+
+protected:
+	std::size_t columnsReturned() const;
+		/// Returns number of columns returned by query.
+
+	int affectedRowCount() const;
+		/// Returns the number of affected rows.
+		/// Used to find out the number of rows affected by insert, delete or update.
+		/// All changes are counted, even if they are later undone by a ROLLBACK or ABORT. 
+		/// Changes associated with creating and dropping tables are not counted.
+
+	const MetaColumn& metaColumn(std::size_t pos) const;
+		/// Returns column meta data.
+
+	bool hasNext();
+		/// Returns true if a call to next() will return data.
+
+	std::size_t next();
+		/// Retrieves the next row from the resultset and returns 1.
+		/// Will throw, if the resultset is empty.
+
+	bool canBind() const;
+		/// Returns true if a valid statement is set and we can bind.
+
+	bool canCompile() const;
+		/// Returns true if statement can compile.
+
+	void compileImpl();
+		/// Compiles the statement, doesn't bind yet.
+		/// Returns true if the statement was succesfully compiled.
+		/// The way SQLite handles batches of statmeents is by compiling
+		/// one at a time and returning a pointer to the next one.
+		/// The remainder of the statement is kept in a string
+		/// buffer pointed to by _pLeftover member.
+
+	void bindImpl();
+		/// Binds parameters
+
+	AbstractExtraction::ExtractorPtr extractor();
+		/// Returns the concrete extractor used by the statement.
+
+	AbstractBinding::BinderPtr binder();
+		/// Returns the concrete binder used by the statement.
+
+private:
+	void clear();
+		/// Removes the _pStmt
+
+	typedef Poco::SharedPtr<Binder>             BinderPtr;
+	typedef Poco::SharedPtr<Extractor>          ExtractorPtr;
+	typedef Poco::Data::AbstractBindingVec      Bindings;
+	typedef Poco::Data::AbstractExtractionVec   Extractions;
+	typedef std::vector<Poco::Data::MetaColumn> MetaColumnVec;
+	typedef std::vector<MetaColumnVec>          MetaColumnVecVec;
+	typedef Poco::SharedPtr<std::string>        StrPtr;
+	typedef Bindings::iterator                  BindIt;
+
+	sqlite3*         _pDB;
+	sqlite3_stmt*    _pStmt;
+	bool             _stepCalled;
+	int              _nextResponse;
+	BinderPtr        _pBinder;
+	ExtractorPtr     _pExtractor;
+	MetaColumnVecVec _columns;
+	int              _affectedRowCount;
+	StrPtr           _pLeftover;
+	BindIt           _bindBegin;
+	bool             _canBind;
+	bool             _isExtracted;
+	bool             _canCompile;
+
+	static const int POCO_SQLITE_INV_ROW_CNT;
+};
+
+
+//
+// inlines
+//
+inline AbstractExtraction::ExtractorPtr SQLiteStatementImpl::extractor()
+{
+	return _pExtractor;
+}
+
+
+inline AbstractBinding::BinderPtr SQLiteStatementImpl::binder()
+{
+	return _pBinder;
+}
+
+
+inline bool SQLiteStatementImpl::canBind() const
+{
+	return _canBind;
+}
+
+
+inline bool SQLiteStatementImpl::canCompile() const
+{
+	return _canCompile;
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // Data_SQLite_SQLiteStatementImpl_INCLUDED
diff --git a/Poco/Data/SQLite/SessionImpl.h b/Poco/Data/SQLite/SessionImpl.h
new file mode 100644
index 0000000..6e8c749
--- /dev/null
+++ b/Poco/Data/SQLite/SessionImpl.h
@@ -0,0 +1,168 @@
+//
+// SessionImpl.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  SessionImpl
+//
+// Definition of the SessionImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SQLite_SessionImpl_INCLUDED
+#define Data_SQLite_SessionImpl_INCLUDED
+
+
+#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"
+#include "Poco/Mutex.h"
+
+
+extern "C"
+{
+	typedef struct sqlite3 sqlite3;
+}
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API SessionImpl: public Poco::Data::AbstractSessionImpl<SessionImpl>
+	/// Implements SessionImpl interface.
+{
+public:
+	SessionImpl(const std::string& fileName,
+		std::size_t loginTimeout = LOGIN_TIMEOUT_DEFAULT);
+		/// Creates the SessionImpl. Opens a connection to the database.
+
+	~SessionImpl();
+		/// Destroys the SessionImpl.
+
+	Poco::Data::StatementImpl* createStatementImpl();
+		/// Returns an SQLite StatementImpl.
+
+	void open(const std::string& connect = "");
+		/// Opens a connection to the Database.
+		/// 
+		/// An in-memory system database (sys), with a single table (dual) 
+		/// containing single field (dummy) is attached to the database.
+		/// The in-memory system database is used to force change count
+		/// to be reset to zero on every new query (or batch of queries) 
+		/// execution. Without this functionality, select statements
+		/// executions that do not return any rows return the count of
+		/// changes effected by the most recent insert, update or delete.
+		/// In-memory system database can be queried and updated but can not
+		/// be dropped. It may be used for other purposes 
+		/// in the future.
+
+	void close();
+		/// Closes the session.
+
+	bool isConnected();
+		/// Returns true if connected, false otherwise.
+
+	void setConnectionTimeout(std::size_t timeout);
+		/// Sets the session connection timeout value.
+		/// Timeout value is in seconds.
+
+	std::size_t getConnectionTimeout();
+		/// Returns the session connection timeout value.
+		/// Timeout value is in seconds.
+
+	void begin();
+		/// Starts a transaction.
+
+	void commit();
+		/// Commits and ends a transaction.
+
+	void rollback();
+		/// Aborts a transaction.
+
+	bool canTransact();
+		/// Returns true if session has transaction capabilities.
+
+	bool isTransaction();
+		/// Returns true iff a transaction is a transaction is in progress, false otherwise.
+
+	void setTransactionIsolation(Poco::UInt32 ti);
+		/// Sets the transaction isolation level.
+
+	Poco::UInt32 getTransactionIsolation();
+		/// Returns the transaction isolation level.
+
+	bool hasTransactionIsolation(Poco::UInt32 ti);
+		/// Returns true iff the transaction isolation level corresponding
+		/// to the supplied bitmask is supported.
+
+	bool isTransactionIsolation(Poco::UInt32 ti);
+		/// Returns true iff the transaction isolation level corresponds
+		/// to the supplied bitmask.
+
+	void autoCommit(const std::string&, bool val);
+		/// Sets autocommit property for the session.
+
+	bool isAutoCommit(const std::string& name="");
+		/// Returns autocommit property value.
+
+	const std::string& connectorName() const;
+		/// Returns the name of the connector.
+
+protected:
+	void setConnectionTimeout(const std::string& prop, const Poco::Any& value);
+	Poco::Any getConnectionTimeout(const std::string& prop);
+
+private:
+	std::string _connector;
+	sqlite3*    _pDB;
+	bool        _connected;
+	bool        _isTransaction;
+	int         _timeout;
+	Poco::Mutex _mutex;
+
+	static const std::string DEFERRED_BEGIN_TRANSACTION;
+	static const std::string COMMIT_TRANSACTION;
+	static const std::string ABORT_TRANSACTION;
+};
+
+
+//
+// inlines
+//
+inline bool SessionImpl::canTransact()
+{
+	return true;
+}
+
+
+inline 	bool SessionImpl::isTransaction()
+{
+	return _isTransaction;
+}
+
+
+inline const std::string& SessionImpl::connectorName() const
+{
+	return _connector;
+}
+
+
+inline std::size_t SessionImpl::getConnectionTimeout()
+{
+	return static_cast<std::size_t>(_timeout/1000);
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // Data_SQLite_SessionImpl_INCLUDED
diff --git a/Poco/Data/SQLite/Utility.h b/Poco/Data/SQLite/Utility.h
new file mode 100644
index 0000000..5517047
--- /dev/null
+++ b/Poco/Data/SQLite/Utility.h
@@ -0,0 +1,240 @@
+//
+// Utility.h
+//
+// Library: Data/SQLite
+// Package: SQLite
+// Module:  Utility
+//
+// Definition of Utility.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SQLite_Utility_INCLUDED
+#define SQLite_Utility_INCLUDED
+
+
+#include "Poco/Data/SQLite/SQLite.h"
+#include "Poco/Data/MetaColumn.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Mutex.h"
+#include "Poco/Types.h"
+#include <map>
+
+
+extern "C"
+{
+	typedef struct sqlite3 sqlite3;
+	typedef struct sqlite3_stmt sqlite3_stmt;
+	typedef struct sqlite3_mutex* _pMutex;
+}
+
+
+namespace Poco {
+namespace Data {
+namespace SQLite {
+
+
+class SQLite_API Utility
+	/// Various utility functions for SQLite.
+{
+public:
+	static const std::string SQLITE_DATE_FORMAT;
+	static const std::string SQLITE_TIME_FORMAT;
+	typedef std::map<std::string, MetaColumn::ColumnDataType> TypeMap;
+
+	static const int THREAD_MODE_SINGLE;
+	static const int THREAD_MODE_MULTI;
+	static const int THREAD_MODE_SERIAL;
+
+	static const int OPERATION_INSERT;
+	static const int OPERATION_DELETE;
+	static const int OPERATION_UPDATE;
+
+	static sqlite3* dbHandle(const Session& session);
+		/// Returns native DB handle.
+
+	static std::string lastError(sqlite3* pDB);
+		/// Retreives the last error code from sqlite and converts it to a string.
+
+	static std::string lastError(const Session& session);
+		/// Retreives the last error code from sqlite and converts it to a string.
+
+	static void throwException(sqlite3* pDB, int rc, const std::string& addErrMsg = std::string());
+		/// Throws for an error code the appropriate exception
+
+	static MetaColumn::ColumnDataType getColumnType(sqlite3_stmt* pStmt, std::size_t pos);
+		/// Returns column data type.
+
+	static bool fileToMemory(sqlite3* pInMemory, const std::string& fileName);
+		/// Loads the contents of a database file on disk into an opened
+		/// database in memory.
+		/// 
+		/// Returns true if succesful.
+
+	static bool fileToMemory(const Session& session, const std::string& fileName);
+		/// Loads the contents of a database file on disk into an opened
+		/// database in memory.
+		/// 
+		/// Returns true if succesful.
+
+	static bool memoryToFile(const std::string& fileName, sqlite3* pInMemory);
+		/// Saves the contents of an opened database in memory to the
+		/// database on disk.
+		/// 
+		/// Returns true if succesful.
+
+	static bool memoryToFile(const std::string& fileName, const Session& session);
+		/// Saves the contents of an opened database in memory to the
+		/// database on disk.
+		/// 
+		/// Returns true if succesful.
+
+	static bool isThreadSafe();
+		/// Returns true if SQLite was compiled in multi-thread or serialized mode.
+		/// See http://www.sqlite.org/c3ref/threadsafe.html for details.
+		/// 
+		/// Returns true if succesful
+
+	static bool setThreadMode(int mode);
+		/// Sets the threading mode to single, multi or serialized.
+		/// See http://www.sqlite.org/threadsafe.html for details.
+		/// 
+		/// Returns true if succesful
+
+	static int getThreadMode();
+		/// Returns the thread mode.
+
+	typedef void(*UpdateCallbackType)(void*, int, const char*, const char*, Poco::Int64);
+		/// Update callback function type.
+ 
+	typedef int(*CommitCallbackType)(void*);
+		/// Commit callback function type.
+
+	typedef void(*RollbackCallbackType)(void*);
+		/// Rollback callback function type.
+
+	template <typename T, typename CBT>
+	static bool registerUpdateHandler(sqlite3* pDB, CBT callbackFn, T* pParam)
+		/// Registers the callback for (1)(insert, delete, update), (2)(commit) or 
+		/// or (3)(rollback) events. Only one function per group can be registered
+		/// at a time. Registration is not thread-safe. Storage pointed to by pParam
+		/// must remain valid as long as registration is active. Registering with
+		/// callbackFn set to zero disables notifications.
+		/// 
+		/// See http://www.sqlite.org/c3ref/update_hook.html and 
+		/// http://www.sqlite.org/c3ref/commit_hook.html for details.
+	{
+		typedef std::pair<CBT, T*> CBPair;
+		typedef std::multimap<sqlite3*, CBPair> CBMap;
+		typedef typename CBMap::iterator CBMapIt;
+		typedef std::pair<CBMapIt, CBMapIt> CBMapItPair;
+
+		static CBMap retMap;
+		T* pRet = reinterpret_cast<T*>(eventHookRegister(pDB, callbackFn, pParam));
+
+		if (pRet == 0)
+		{
+			if (retMap.find(pDB) == retMap.end())
+			{
+				retMap.insert(std::make_pair(pDB, CBPair(callbackFn, pParam)));
+				return true;
+			}
+		}
+		else
+		{
+			CBMapItPair retMapRange = retMap.equal_range(pDB);
+			for (CBMapIt it = retMapRange.first; it != retMapRange.second; ++it)
+			{
+				poco_assert (it->second.first != 0);
+				if ((callbackFn == 0) && (*pRet == *it->second.second))
+				{
+					retMap.erase(it);
+					return true;
+				}
+
+				if ((callbackFn == it->second.first) && (*pRet == *it->second.second))
+				{
+					it->second.second = pParam;
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	template <typename T, typename CBT>
+	static bool registerUpdateHandler(const Session& session, CBT callbackFn, T* pParam)
+		/// Registers the callback by calling registerUpdateHandler(sqlite3*, CBT, T*).
+	{
+		return registerUpdateHandler(dbHandle(session), callbackFn, pParam);
+	}
+
+	class SQLiteMutex
+	{
+	public:
+		SQLiteMutex(sqlite3* pDB);
+		~SQLiteMutex();
+
+	private:
+		SQLiteMutex();
+		sqlite3_mutex* _pMutex;
+	};
+
+private:
+	Utility();
+		/// Maps SQLite column declared types to Poco::Data types through
+		/// static TypeMap member.
+		/// 
+		/// Note: SQLite is type-agnostic and it is the end-user responsibility
+		/// to ensure that column declared data type corresponds to the type of 
+		/// data actually held in the database.
+		/// 
+		/// Column types are case-insensitive.
+
+	Utility(const Utility&);
+	Utility& operator = (const Utility&);
+
+	static void* eventHookRegister(sqlite3* pDB, UpdateCallbackType callbackFn, void* pParam);
+	static void* eventHookRegister(sqlite3* pDB, CommitCallbackType callbackFn, void* pParam);
+	static void* eventHookRegister(sqlite3* pDB, RollbackCallbackType callbackFn, void* pParam);
+
+	static TypeMap     _types;
+	static Poco::Mutex _mutex;
+	static int         _threadMode;
+};
+
+
+//
+// inlines
+//
+inline std::string Utility::lastError(const Session& session)
+{
+	poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
+	return lastError(dbHandle(session));
+}
+
+
+inline bool Utility::memoryToFile(const std::string& fileName, const Session& session)
+{
+	poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
+	return memoryToFile(fileName, dbHandle(session));
+}
+
+
+inline bool Utility::fileToMemory(const Session& session, const std::string& fileName)
+{
+	poco_assert_dbg ((0 == icompare(session.connector(), 0, 6, "sqlite")));
+	return fileToMemory(dbHandle(session), fileName);
+}
+
+
+} } } // namespace Poco::Data::SQLite
+
+
+#endif // SQLite_Utility_INCLUDED
diff --git a/Poco/Data/Session.h b/Poco/Data/Session.h
new file mode 100644
index 0000000..bf96efe
--- /dev/null
+++ b/Poco/Data/Session.h
@@ -0,0 +1,494 @@
+//
+// Session.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Session
+//
+// Definition of the Session class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Session_INCLUDED
+#define Data_Session_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/Data/Statement.h"
+#include "Poco/Data/StatementCreator.h"
+#include "Poco/Data/Binding.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Any.h"
+#include <algorithm>
+
+
+namespace Poco {
+namespace Data {
+
+
+class StatementImpl;
+
+
+class Data_API Session
+	/// A Session holds a connection to a Database and creates Statement objects.
+	///
+	/// Sessions are always created via the SessionFactory:
+	///    
+	///     Session ses(SessionFactory::instance().create(connectorKey, connectionString));
+	///    
+	/// where the first param presents the type of session one wants to create (e.g., for SQLite one would choose "SQLite",
+	/// for ODBC the key is "ODBC") and the second param is the connection string that the session implementation 
+	/// requires to connect to the database. The format of the connection string is specific to the actual connector.
+	///
+	/// A simpler form to create the session is to pass the connector key and connection string directly to
+	/// the Session constructor.
+	///
+	/// A concrete example to open an SQLite database stored in the file "dummy.db" would be
+	///    
+	///     Session ses("SQLite", "dummy.db");
+	///    
+	/// Via a Session one can create two different types of statements. First, statements that should only be executed once and immediately, and
+	/// second, statements that should be executed multiple times, using a separate execute() call.
+	/// The simple one is immediate execution:
+	///    
+	///     ses << "CREATE TABLE Dummy (data INTEGER(10))", now;
+	///
+	/// The now at the end of the statement is required, otherwise the statement
+	/// would not be executed.
+	///    
+	/// If one wants to reuse a Statement (and avoid the overhead of repeatedly parsing an SQL statement)
+	/// one uses an explicit Statement object and its execute() method:
+	///    
+	///     int i = 0;
+	///     Statement stmt = (ses << "INSERT INTO Dummy VALUES(:data)", use(i));
+	///    
+	///     for (i = 0; i < 100; ++i)
+	///     {
+	///         stmt.execute();
+	///     }
+	///    
+	/// The above example assigns the variable i to the ":data" placeholder in the SQL query. The query is parsed and compiled exactly
+	/// once, but executed 100 times. At the end the values 0 to 99 will be present in the Table "DUMMY".
+	///
+	/// A faster implementaton of the above code will simply create a vector of int
+	/// and use the vector as parameter to the use clause (you could also use set or multiset instead):
+	///    
+	///     std::vector<int> data;
+	///     for (int i = 0; i < 100; ++i)
+	///     {
+	///         data.push_back(i);
+	///     }
+	///     ses << "INSERT INTO Dummy VALUES(:data)", use(data);
+	///
+	/// NEVER try to bind to an empty collection. This will give a BindingException at run-time!
+	///
+	/// Retrieving data from a database works similar, you could use simple data types, vectors, sets or multiset as your targets:
+	///
+	///     std::set<int> retData;
+	///     ses << "SELECT * FROM Dummy", into(retData));
+	///
+	/// Due to the blocking nature of the above call it is possible to partition the data retrieval into chunks by setting a limit to
+	/// the maximum number of rows retrieved from the database:
+	///
+	///     std::set<int> retData;
+	///     Statement stmt = (ses << "SELECT * FROM Dummy", into(retData), limit(50));
+	///     while (!stmt.done())
+	///     {
+	///         stmt.execute();
+	///     }
+	///
+	/// The "into" keyword is used to inform the statement where output results should be placed. The limit value ensures
+	/// that during each run at most 50 rows are retrieved. Assuming Dummy contains 100 rows, retData will contain 50 
+	/// elements after the first run and 100 after the second run, i.e.
+	/// the collection is not cleared between consecutive runs. After the second execute stmt.done() will return true.
+	///
+	/// A prepared Statement will behave exactly the same but a further call to execute() will simply reset the Statement, 
+	/// execute it again and append more data to the result set.
+	///
+	/// Note that it is possible to append several "bind" or "into" clauses to the statement. Theoretically, one could also have several
+	/// limit clauses but only the last one that was added will be effective. 
+	/// Also several preconditions must be met concerning binds and intos.
+	/// Take the following example:
+	///
+	///     ses << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))";
+	///     std::vector<std::string> nameVec; // [...] add some elements
+	///     std::vector<int> ageVec; // [...] add some elements
+	///     ses << "INSERT INTO Person (LastName, Age) VALUES(:ln, :age)", use(nameVec), use(ageVec);
+	///
+	/// The size of all use parameters MUST be the same, otherwise an exception is thrown. Furthermore,
+	/// the amount of use clauses must match the number of wildcards in the query (to be more precise: 
+	/// each binding has a numberOfColumnsHandled() value which defaults to 1. The sum of all these values 
+	/// must match the wildcard count in the query.
+	/// However, this is only important if you have written your own TypeHandler specializations.
+	/// If you plan to map complex object types to tables see the TypeHandler documentation.
+	/// For now, we simply assume we have written one TypeHandler for Person objects. Instead of having n different vectors,
+	/// we have one collection:
+	///
+	///     std::vector<Person> people; // [...] add some elements
+	///     ses << "INSERT INTO Person (LastName, FirstName, Age) VALUES(:ln, :fn, :age)", use(people);
+	///
+	/// which will insert all Person objects from the people vector to the database (and again, you can use set, multiset too,
+	/// even map and multimap if Person provides an operator() which returns the key for the map).
+	/// The same works for a SELECT statement with "into" clauses:
+	///
+	///     std::vector<Person> people;
+	///     ses << "SELECT * FROM PERSON", into(people);
+	/// 
+	/// Mixing constants or variables with manipulators is allowed provided there are corresponding placeholders for the constants provided in
+	/// the SQL string, such as in following example:
+	///
+	///     std::vector<Person> people;
+	///     ses << "SELECT * FROM %s", into(people), "PERSON";
+	/// 
+	/// Formatting only kicks in if there are values to be injected into the SQL string, otherwise it is skipped.
+	/// If the formatting will occur and the percent sign is part of the query itself, it can be passed to the query by entering it twice (%%).
+	/// However, if no formatting is used, one percent sign is sufficient as the string will be passed unaltered.
+	/// For complete list of supported data types with their respective specifications, see the documentation for format in Foundation.
+{
+public:
+	static const std::size_t LOGIN_TIMEOUT_DEFAULT = SessionImpl::LOGIN_TIMEOUT_DEFAULT;
+	static const Poco::UInt32 TRANSACTION_READ_UNCOMMITTED = 0x00000001L;
+	static const Poco::UInt32 TRANSACTION_READ_COMMITTED   = 0x00000002L;
+	static const Poco::UInt32 TRANSACTION_REPEATABLE_READ  = 0x00000004L;
+	static const Poco::UInt32 TRANSACTION_SERIALIZABLE     = 0x00000008L;
+
+	Session(Poco::AutoPtr<SessionImpl> ptrImpl);
+		/// Creates the Session.
+
+	Session(const std::string& connector,
+		const std::string& connectionString,
+		std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
+		/// Creates a new session, using the given connector (which must have
+		/// been registered), and connectionString.
+
+	Session(const std::string& connection,
+		std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
+		/// Creates a new session, using the given connection (must be in
+		/// "connection:///connectionString" format).
+
+	Session(const Session&);
+		/// Creates a session by copying another one.
+
+	Session& operator = (const Session&);
+		/// Assignment operator.
+
+	~Session();
+		/// Destroys the Session.
+
+	void swap(Session& other);
+		/// Swaps the session with another one.
+
+	template <typename T>
+	Statement operator << (const T& t)
+		/// Creates a Statement with the given data as SQLContent
+	{
+		return _statementCreator << t;
+	}
+
+	StatementImpl* createStatementImpl();
+		/// Creates a StatementImpl.
+
+	void open(const std::string& connect = "");
+		/// Opens the session using the supplied string.
+		/// Can also be used with default empty string to 
+		/// reconnect a disconnected session.
+		/// If the connection is not established, 
+		/// a ConnectionFailedException is thrown. 
+		/// Zero timout means indefinite
+
+	void close();
+		/// Closes the session.
+
+	bool isConnected();
+		/// Returns true iff session is connected, false otherwise.
+
+	void reconnect();
+		/// Closes the session and opens it.
+
+	void setLoginTimeout(std::size_t timeout);
+		/// Sets the session login timeout value.
+
+	std::size_t getLoginTimeout() const;
+		/// Returns the session login timeout value.
+
+	void setConnectionTimeout(std::size_t timeout);
+		/// Sets the session connection timeout value.
+
+	std::size_t getConnectionTimeout();
+		/// Returns the session connection timeout value.
+
+	void begin();
+		/// Starts a transaction.
+
+	void commit();
+		/// Commits and ends a transaction.
+
+	void rollback();
+		/// Rolls back and ends a transaction.
+
+	bool canTransact();
+		/// Returns true if session has transaction capabilities.
+
+	bool isTransaction();
+		/// Returns true iff a transaction is in progress, false otherwise.
+
+	void setTransactionIsolation(Poco::UInt32);
+		/// Sets the transaction isolation level.
+
+	Poco::UInt32 getTransactionIsolation();
+		/// Returns the transaction isolation level.
+
+	bool hasTransactionIsolation(Poco::UInt32 ti);
+		/// Returns true iff the transaction isolation level corresponding
+		/// to the supplied bitmask is supported.
+
+	bool isTransactionIsolation(Poco::UInt32 ti);
+		/// Returns true iff the transaction isolation level corresponds
+		/// to the supplied bitmask.
+
+	std::string connector() const;
+		/// Returns the connector name for this session.
+
+	std::string uri() const;
+		/// Returns the URI for this session.
+
+	static std::string uri(const std::string& connector,
+		const std::string& connectionString);
+		/// Utility function that teturns the URI formatted from supplied 
+		/// arguments as "connector:///connectionString".
+
+	void setFeature(const std::string& name, bool state);
+		/// Set the state of a feature.
+		///
+		/// Features are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested feature is
+		/// not supported by the underlying implementation.
+	
+	bool getFeature(const std::string& name) const;
+		/// Look up the state of a feature.
+		///
+		/// Features are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested feature is
+		/// not supported by the underlying implementation.
+
+	void setProperty(const std::string& name, const Poco::Any& value);
+		/// Set the value of a property.
+		///
+		/// Properties are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested property is
+		/// not supported by the underlying implementation.
+
+	Poco::Any getProperty(const std::string& name) const;
+		/// Look up the value of a property.
+		///
+		/// Properties are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested property is
+		/// not supported by the underlying implementation.
+
+	SessionImpl* impl();
+		/// Returns a pointer to the underlying SessionImpl.
+
+private:
+	Session();
+
+	Poco::AutoPtr<SessionImpl> _pImpl;
+	StatementCreator           _statementCreator;
+};
+
+
+//
+// inlines
+//
+inline StatementImpl* Session::createStatementImpl()
+{
+	return _pImpl->createStatementImpl();
+}
+
+
+inline void Session::open(const std::string& connect)
+{
+	_pImpl->open(connect);
+}
+
+
+inline void Session::close()
+{
+	_pImpl->close();
+}
+
+
+inline bool Session::isConnected()
+{
+	return _pImpl->isConnected();
+}
+
+
+inline void Session::reconnect()
+{
+	_pImpl->reconnect();
+}
+
+
+inline void Session::setLoginTimeout(std::size_t timeout)
+{
+	_pImpl->setLoginTimeout(timeout);
+}
+
+
+inline std::size_t Session::getLoginTimeout() const
+{
+	return _pImpl->getLoginTimeout();
+}
+
+
+inline void Session::setConnectionTimeout(std::size_t timeout)
+{
+	_pImpl->setConnectionTimeout(timeout);
+}
+
+
+inline std::size_t Session::getConnectionTimeout()
+{
+	return _pImpl->getConnectionTimeout();
+}
+
+
+inline void Session::begin()
+{
+	return _pImpl->begin();
+}
+
+
+inline void Session::commit()
+{
+	return _pImpl->commit();
+}
+
+
+inline void Session::rollback()
+{
+	return _pImpl->rollback();
+}
+
+
+inline bool Session::canTransact()
+{
+	return _pImpl->canTransact();
+}
+
+
+inline bool Session::isTransaction()
+{
+	return _pImpl->isTransaction();
+}
+
+
+inline void Session::setTransactionIsolation(Poco::UInt32 ti)
+{
+	_pImpl->setTransactionIsolation(ti);
+}
+
+
+inline Poco::UInt32 Session::getTransactionIsolation()
+{
+	return _pImpl->getTransactionIsolation();
+}
+
+
+inline bool Session::hasTransactionIsolation(Poco::UInt32 ti)
+{
+	return _pImpl->hasTransactionIsolation(ti);
+}
+
+
+inline bool Session::isTransactionIsolation(Poco::UInt32 ti)
+{
+	return _pImpl->isTransactionIsolation(ti);
+}
+
+
+inline std::string Session::connector() const
+{
+	return _pImpl->connectorName();
+}
+
+
+inline std::string Session::uri(const std::string& connector,
+	const std::string& connectionString)
+{
+	return SessionImpl::uri(connector, connectionString);
+}
+
+
+inline std::string Session::uri() const
+{
+	return _pImpl->uri();
+}
+
+
+inline void Session::setFeature(const std::string& name, bool state)
+{
+	_pImpl->setFeature(name, state);
+}
+
+
+inline bool Session::getFeature(const std::string& name) const
+{
+	return const_cast<SessionImpl*>(_pImpl.get())->getFeature(name);
+}
+
+
+inline void Session::setProperty(const std::string& name, const Poco::Any& value)
+{
+	_pImpl->setProperty(name, value);
+}
+
+
+inline Poco::Any Session::getProperty(const std::string& name) const
+{
+	return const_cast<SessionImpl*>(_pImpl.get())->getProperty(name);
+}
+
+
+inline SessionImpl* Session::impl()
+{
+	return _pImpl;
+}
+
+
+inline void swap(Session& s1, Session& s2)
+{
+	s1.swap(s2);
+}
+
+
+} } // namespace Poco::Data
+
+
+namespace std
+{
+	template<>
+	inline void swap<Poco::Data::Session>(Poco::Data::Session& s1, 
+		Poco::Data::Session& s2)
+		/// Full template specalization of std:::swap for Session
+	{
+		s1.swap(s2);
+	}
+}
+
+
+#endif // Data_Session_INCLUDED
diff --git a/Poco/Data/SessionFactory.h b/Poco/Data/SessionFactory.h
new file mode 100644
index 0000000..0185a8a
--- /dev/null
+++ b/Poco/Data/SessionFactory.h
@@ -0,0 +1,99 @@
+//
+// SessionFactory.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  SessionFactory
+//
+// Definition of the SessionFactory class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SessionFactory_INCLUDED
+#define Data_SessionFactory_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Connector.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Mutex.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/String.h"
+#include <map>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API SessionFactory
+	/// A SessionFactory is a singleton class that stores Connectors and allows to 
+	/// create Sessions of the required type:
+	///    
+	///     Session ses(SessionFactory::instance().create(connector, connectionString));
+	///    
+	/// where the first param presents the type of session one wants to create (e.g. for SQLite one would choose "SQLite")
+	/// and the second param is the connection string that the connector requires to connect to the database.
+	///
+	/// A concrete example to open an SQLite database stored in the file "dummy.db" would be
+	///    
+	///     Session ses(SessionFactory::instance().create(SQLite::Connector::KEY, "dummy.db"));
+	///
+	/// An even simpler way to create a session is to use the two argument constructor of Session, which
+	/// automatically invokes the SessionFactory:
+	///
+	///      Session ses("SQLite", "dummy.db");
+{
+public:
+	
+	static SessionFactory& instance();
+		/// returns the static instance of the singleton.
+
+	void add(Connector* pIn);
+		/// Registers a Connector under its key at the factory. If a registration for that
+		/// key is already active, the first registration will be kept, only its reference count will be increased.
+		/// Always takes ownership of parameter pIn.
+
+	void remove(const std::string& key);
+		/// Lowers the reference count for the Connector registered under that key. If the count reaches zero,
+		/// the object is removed.
+
+	Session create(const std::string& key,
+		const std::string& connectionString,
+		std::size_t timeout = Session::LOGIN_TIMEOUT_DEFAULT);
+		/// Creates a Session for the given key with the connectionString. Throws an Poco:Data::UnknownDataBaseException
+		/// if no Connector is registered for that key.
+
+	Session create(const std::string& uri,
+		std::size_t timeout = Session::LOGIN_TIMEOUT_DEFAULT);
+		/// Creates a Session for the given URI (must be in key:///connectionString format). 
+		/// Throws a Poco:Data::UnknownDataBaseException if no Connector is registered for the key.
+
+private:
+	SessionFactory();
+	~SessionFactory();
+	SessionFactory(const SessionFactory&);
+	SessionFactory& operator = (const SessionFactory&);
+
+	struct SessionInfo
+	{
+		int cnt;
+		Poco::SharedPtr<Connector> ptrSI;
+		SessionInfo(Connector* pSI);
+	};
+	
+	typedef std::map<std::string, SessionInfo, Poco::CILess> Connectors;
+	Connectors      _connectors;
+	Poco::FastMutex _mutex;
+};
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_SessionFactory_INCLUDED
diff --git a/Poco/Data/SessionImpl.h b/Poco/Data/SessionImpl.h
new file mode 100644
index 0000000..223c2bf
--- /dev/null
+++ b/Poco/Data/SessionImpl.h
@@ -0,0 +1,221 @@
+//
+// SessionImpl.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  SessionImpl
+//
+// Definition of the SessionImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SessionImpl_INCLUDED
+#define Data_SessionImpl_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/String.h"
+#include "Poco/Format.h"
+#include "Poco/Any.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class StatementImpl;
+
+
+class Data_API SessionImpl: public Poco::RefCountedObject
+	/// Interface for Session functionality that subclasses must extend. 
+	/// SessionImpl objects are noncopyable.
+{
+public:
+	static const std::size_t LOGIN_TIMEOUT_INFINITE = 0;
+		/// Infinite connection/login timeout.
+
+	static const std::size_t LOGIN_TIMEOUT_DEFAULT = 60;
+		/// Default connection/login timeout in seconds.
+
+	static const std::size_t CONNECTION_TIMEOUT_INFINITE = 0;
+		/// Infinite connection/login timeout.
+
+	static const std::size_t CONNECTION_TIMEOUT_DEFAULT = CONNECTION_TIMEOUT_INFINITE;
+		/// Default connection/login timeout in seconds.
+
+	SessionImpl(const std::string& connectionString,
+		std::size_t timeout = LOGIN_TIMEOUT_DEFAULT);
+		/// Creates the SessionImpl.
+
+	virtual ~SessionImpl();
+		/// Destroys the SessionImpl.
+
+	virtual StatementImpl* createStatementImpl() = 0;
+		/// Creates a StatementImpl.
+
+	virtual void open(const std::string& connectionString = "") = 0;
+		/// Opens the session using the supplied string.
+		/// Can also be used with default empty string to reconnect 
+		/// a disconnected session.
+		/// If the connection is not established within requested timeout 
+		/// (specified in seconds), a ConnectionFailedException is thrown. 
+		/// Zero timout means indefinite
+
+	virtual void close() = 0;
+		/// Closes the connection.
+
+	virtual bool isConnected() = 0;
+		/// Returns true if session is connected, false otherwise.
+
+	void setLoginTimeout(std::size_t timeout);
+		/// Sets the session login timeout value.
+
+	std::size_t getLoginTimeout() const;
+		/// Returns the session login timeout value.
+
+	virtual void setConnectionTimeout(std::size_t timeout) = 0;
+		/// Sets the session connection timeout value.
+
+	virtual std::size_t getConnectionTimeout() = 0;
+		/// Returns the session connection timeout value.
+
+	void reconnect();
+		/// Closes the connection and opens it again.
+
+	virtual void begin() = 0;
+		/// Starts a transaction.
+
+	virtual void commit() = 0;
+		/// Commits and ends a transaction.
+
+	virtual void rollback() = 0;
+		/// Aborts a transaction.
+
+	virtual bool canTransact() = 0;
+		/// Returns true if session has transaction capabilities.
+
+	virtual bool isTransaction() = 0;
+		/// Returns true iff a transaction is a transaction is in progress, false otherwise.
+
+	virtual void setTransactionIsolation(Poco::UInt32) = 0;
+		/// Sets the transaction isolation level.
+
+	virtual Poco::UInt32 getTransactionIsolation() = 0;
+		/// Returns the transaction isolation level.
+
+	virtual bool hasTransactionIsolation(Poco::UInt32) = 0;
+		/// Returns true iff the transaction isolation level corresponding
+		/// to the supplied bitmask is supported.
+
+	virtual bool isTransactionIsolation(Poco::UInt32) = 0;
+		/// Returns true iff the transaction isolation level corresponds
+		/// to the supplied bitmask.
+
+	virtual const std::string& connectorName() const = 0;
+		/// Returns the name of the connector.
+
+	const std::string& connectionString() const;
+		/// Returns the connection string.
+
+	static std::string uri(const std::string& connector, const std::string& connectionString);
+		/// Returns formatted URI.
+
+	std::string uri() const;
+		/// Returns the URI for this session.
+
+	virtual void setFeature(const std::string& name, bool state) = 0;
+		/// Set the state of a feature.
+		///
+		/// Features are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested feature is
+		/// not supported by the underlying implementation.
+	
+	virtual bool getFeature(const std::string& name) = 0;
+		/// Look up the state of a feature.
+		///
+		/// Features are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested feature is
+		/// not supported by the underlying implementation.
+
+	virtual void setProperty(const std::string& name, const Poco::Any& value) = 0;
+		/// Set the value of a property.
+		///
+		/// Properties are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested property is
+		/// not supported by the underlying implementation.
+
+	virtual Poco::Any getProperty(const std::string& name) = 0;
+		/// Look up the value of a property.
+		///
+		/// Properties are a generic extension mechanism for session implementations.
+		/// and are defined by the underlying SessionImpl instance.
+		///
+		/// Throws a NotSupportedException if the requested property is
+		/// not supported by the underlying implementation.
+
+protected:
+	void setConnectionString(const std::string& connectionString);
+		/// Sets the connection string. Should only be called on
+		/// disconnetced sessions. Throws InvalidAccessException when called on
+		/// a connected session.
+
+private:
+	SessionImpl();
+	SessionImpl(const SessionImpl&);
+	SessionImpl& operator = (const SessionImpl&);
+
+	std::string _connectionString;
+	std::size_t _loginTimeout;
+};
+
+
+//
+// inlines
+//
+inline const std::string& SessionImpl::connectionString() const
+{
+	return _connectionString;
+}
+
+
+inline void SessionImpl::setLoginTimeout(std::size_t timeout)
+{
+	_loginTimeout = timeout;
+}
+
+
+inline std::size_t SessionImpl::getLoginTimeout() const
+{
+	return _loginTimeout;
+}
+
+
+inline std::string SessionImpl::uri(const std::string& connector,
+	const std::string& connectionString)
+{
+	return format("%s:///%s", connector, connectionString);
+}
+
+
+inline std::string SessionImpl::uri() const
+{
+	return uri(connectorName(), connectionString());
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_SessionImpl_INCLUDED
diff --git a/Poco/Data/SessionPool.h b/Poco/Data/SessionPool.h
new file mode 100644
index 0000000..6994c33
--- /dev/null
+++ b/Poco/Data/SessionPool.h
@@ -0,0 +1,233 @@
+//
+// SessionPool.h
+//
+// Library: Data
+// Package: SessionPooling
+// Module:  SessionPool
+//
+// Definition of the SessionPool class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SessionPool_INCLUDED
+#define Data_SessionPool_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/PooledSessionHolder.h"
+#include "Poco/Data/PooledSessionImpl.h"
+#include "Poco/Data/Session.h"
+#include "Poco/HashMap.h"
+#include "Poco/Any.h"
+#include "Poco/Timer.h"
+#include "Poco/Mutex.h"
+#include <list>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API SessionPool: public RefCountedObject
+	/// This class implements session pooling for POCO Data.
+	///
+	/// Creating a connection to a database is often a time consuming
+	/// operation. Therefore it makes sense to reuse a session object
+	/// once it is no longer needed.
+	///
+	/// A SessionPool manages a collection of SessionImpl objects 
+	/// (decorated with a PooledSessionImpl).
+	///
+	/// When a SessionImpl object is requested, the SessionPool first
+	/// looks in its set of already initialized SessionImpl for an
+	/// available object. If one is found, it is returned to the
+	/// client and marked as "in-use". If no SessionImpl is available,
+	/// the SessionPool attempts to create a new one for the client.
+	/// To avoid excessive creation of SessionImpl objects, a limit
+	/// can be set on the maximum number of objects.
+	/// Sessions found not to be connected to the database are purged
+	/// from the pool whenever one of the following events occurs:
+	/// 
+	///   - JanitorTimer event
+	///   - get() request
+	///   - putBack() request
+	///
+	/// Not connected idle sessions can not exist.
+	///
+	/// Usage example:
+	///
+	///     SessionPool pool("ODBC", "...");
+	///     ...
+	///     Session sess(pool.get());
+	///     ...
+{
+public:
+	SessionPool(const std::string& connector, 
+		const std::string& connectionString, 
+		int minSessions = 1, 
+		int maxSessions = 32, 
+		int idleTime = 60);
+		/// Creates the SessionPool for sessions with the given connector
+		/// and connectionString.
+		///
+		/// The pool allows for at most maxSessions sessions to be created.
+		/// If a session has been idle for more than idleTime seconds, and more than
+		/// minSessions sessions are in the pool, the session is automatically destroyed.
+
+	~SessionPool();
+		/// Destroys the SessionPool.
+		
+	Session get();
+		/// Returns a Session.
+		///
+		/// If there are unused sessions available, one of the
+		/// unused sessions is recycled. Otherwise, a new session
+		/// is created. 
+		///
+		/// If the maximum number of sessions for this pool has
+		/// already been created, a SessionPoolExhaustedException
+		/// is thrown.
+	
+	template <typename T>
+	Session get(const std::string& name, const T& value)
+		/// Returns a Session with requested property set.
+		/// The property can be different from the default pool
+		/// value, in which case it is reset back to the pool 
+		/// value when the session is reclaimed by the pool.
+	{
+		Session s = get();
+		_addPropertyMap.insert(AddPropertyMap::value_type(s.impl(),
+			std::make_pair(name, s.getProperty(name))));
+		s.setProperty(name, value);
+
+		return s;
+	}
+
+	Session get(const std::string& name, bool value);
+		/// Returns a Session with requested feature set.
+		/// The feature can be different from the default pool
+		/// value, in which case it is reset back to the pool 
+		/// value when the session is reclaimed by the pool.
+
+	int capacity() const;
+		/// Returns the maximum number of sessions the SessionPool will manage.
+		
+	int used() const;
+		/// Returns the number of sessions currently in use.
+		
+	int idle() const;
+		/// Returns the number of idle sessions.
+		
+	int dead();
+		/// Returns the number of not connected active sessions.
+
+	int allocated() const;
+		/// Returns the number of allocated sessions.
+		
+	int available() const;
+		/// Returns the number of available (idle + remaining capacity) sessions.
+
+	std::string name() const;
+		/// Returns the name for this pool.
+
+	static std::string name(const std::string& connector,
+		const std::string& connectionString);
+	/// Returns the name formatted from supplied arguments as "connector:///connectionString".
+
+	void setFeature(const std::string& name, bool state);
+		/// Sets feature for all the sessions.
+
+	bool getFeature(const std::string& name);
+		/// Returns the requested feature.
+
+	void setProperty(const std::string& name, const Poco::Any& value);
+		/// Sets property for all sessions.
+
+	Poco::Any getProperty(const std::string& name);
+		/// Returns the requested property.
+
+	void shutdown();
+		/// Shuts down the session pool.
+
+	bool isActive() const;
+		/// Returns true if session pool is active (not shut down).
+
+protected:
+	virtual void customizeSession(Session& session);
+		/// Can be overridden by subclass to perform custom initialization
+		/// of a newly created database session.
+		///
+		/// The default implementation does nothing.
+
+	typedef Poco::AutoPtr<PooledSessionHolder>    PooledSessionHolderPtr;
+	typedef Poco::AutoPtr<PooledSessionImpl>      PooledSessionImplPtr;
+	typedef std::list<PooledSessionHolderPtr>     SessionList;
+	typedef Poco::HashMap<std::string, bool>      FeatureMap;
+	typedef Poco::HashMap<std::string, Poco::Any> PropertyMap;
+
+	void purgeDeadSessions();
+	int deadImpl(SessionList& rSessions);
+	void applySettings(SessionImpl* pImpl);
+	void putBack(PooledSessionHolderPtr pHolder);
+	void onJanitorTimer(Poco::Timer&);
+
+private:
+	typedef std::pair<std::string, Poco::Any> PropertyPair; 
+	typedef std::pair<std::string, bool> FeaturePair; 
+	typedef std::map<SessionImpl*, PropertyPair> AddPropertyMap;
+	typedef std::map<SessionImpl*, FeaturePair> AddFeatureMap;
+
+	SessionPool(const SessionPool&);
+	SessionPool& operator = (const SessionPool&);
+		
+	void closeAll(SessionList& sessionList);
+
+	std::string    _connector;
+	std::string    _connectionString;
+	int            _minSessions;
+	int            _maxSessions;
+	int            _idleTime;
+	int            _nSessions;
+	SessionList    _idleSessions;
+	SessionList    _activeSessions;
+	Poco::Timer    _janitorTimer;
+	FeatureMap     _featureMap;
+	PropertyMap    _propertyMap;
+	bool           _shutdown;
+	AddPropertyMap _addPropertyMap;
+	AddFeatureMap  _addFeatureMap;
+	mutable
+	Poco::Mutex _mutex;
+	
+	friend class PooledSessionImpl;
+};
+
+
+inline std::string SessionPool::name(const std::string& connector,
+	const std::string& connectionString)
+{
+	return Session::uri(connector, connectionString);
+}
+
+
+inline std::string SessionPool::name() const
+{
+	return name(_connector, _connectionString);
+}
+
+
+inline bool SessionPool::isActive() const
+{
+	return !_shutdown;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_SessionPool_INCLUDED
diff --git a/Poco/Data/SessionPoolContainer.h b/Poco/Data/SessionPoolContainer.h
new file mode 100644
index 0000000..15c3e83
--- /dev/null
+++ b/Poco/Data/SessionPoolContainer.h
@@ -0,0 +1,114 @@
+//
+// SessionPoolContainer.h
+//
+// Library: Data
+// Package: SessionPooling
+// Module:  SessionPoolContainer
+//
+// Definition of the SessionPoolContainer class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SessionPoolContainer_INCLUDED
+#define Data_SessionPoolContainer_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Data/SessionPool.h"
+#include "Poco/String.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API SessionPoolContainer
+	/// This class implements container of session pools.
+{
+public:
+	SessionPoolContainer();
+		/// Creates the SessionPoolContainer for sessions with the given session parameters.
+
+	~SessionPoolContainer();
+		/// Destroys the SessionPoolContainer.
+	
+	void add(SessionPool* pPool);
+		/// Adds existing session pool to the container.
+		/// Throws SessionPoolExistsException if pool already exists.
+
+	Session add(const std::string& sessionKey, 
+		const std::string& connectionString,
+		int minSessions = 1, 
+		int maxSessions = 32, 
+		int idleTime = 60);
+		/// Adds a new session pool to the container and returns a Session from
+		/// newly created pool. If pool already exists, request to add is silently
+		/// ignored and session is returned from the existing pool.
+
+	bool has(const std::string& name) const;
+		/// Returns true if the requested name exists, false otherwise.
+
+	bool isActive(const std::string& sessionKey,
+		const std::string& connectionString = "") const;
+		/// Returns true if the session is active (i.e. not shut down).
+		/// If connectionString is empty string, sessionKey must be a 
+		/// fully qualified session name as registered with the pool
+		/// container.
+
+	Session get(const std::string& name);
+		/// Returns the requested Session.
+		/// Throws NotFoundException if session is not found.
+
+	SessionPool& getPool(const std::string& name);
+		/// Returns a SessionPool reference.
+		/// Throws NotFoundException if session is not found.
+
+	void remove(const std::string& name);
+		/// Removes a SessionPool.
+		
+	int count() const;
+		/// Returns the number of session pols in the container.
+
+	void shutdown();
+		/// Shuts down all the held pools.
+
+private:
+	typedef std::map<std::string, AutoPtr<SessionPool>, Poco::CILess> SessionPoolMap;
+
+	SessionPoolContainer(const SessionPoolContainer&);
+	SessionPoolContainer& operator = (const SessionPoolContainer&);
+		
+	SessionPoolMap  _sessionPools;
+	Poco::FastMutex _mutex;
+};
+
+
+inline bool SessionPoolContainer::has(const std::string& name) const
+{
+	return _sessionPools.find(name) != _sessionPools.end();
+}
+
+
+inline void SessionPoolContainer::remove(const std::string& name)
+{
+	_sessionPools.erase(name);
+}
+
+
+inline int SessionPoolContainer::count() const
+{
+	return static_cast<int>(_sessionPools.size());
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_SessionPoolContainer_INCLUDED
diff --git a/Poco/Data/SimpleRowFormatter.h b/Poco/Data/SimpleRowFormatter.h
new file mode 100644
index 0000000..2ddfdac
--- /dev/null
+++ b/Poco/Data/SimpleRowFormatter.h
@@ -0,0 +1,122 @@
+//
+// RowFormatter.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  SimpleRowFormatter
+//
+// Definition of the RowFormatter class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_SimpleRowFormatter_INCLUDED
+#define Data_SimpleRowFormatter_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/RowFormatter.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API SimpleRowFormatter: public RowFormatter
+	/// A simple row formatting class.
+{
+public:
+	//typedef RowFormatter::NameVec    NameVec;
+	//typedef RowFormatter::NameVecPtr NameVecPtr;
+	//typedef RowFormatter::ValueVec   ValueVec;
+
+	static const int DEFAULT_COLUMN_WIDTH = 16;
+	static const int DEFAULT_SPACING = 1;
+
+	SimpleRowFormatter(std::streamsize columnWidth = DEFAULT_COLUMN_WIDTH, std::streamsize spacing = DEFAULT_SPACING);
+		/// Creates the SimpleRowFormatter and sets the column width to specified value.
+
+	SimpleRowFormatter(const SimpleRowFormatter& other);
+		/// Creates the copy of the supplied SimpleRowFormatter.
+
+	SimpleRowFormatter& operator = (const SimpleRowFormatter& row);
+		/// Assignment operator.
+
+	~SimpleRowFormatter();
+		/// Destroys the SimpleRowFormatter.
+
+	void swap(SimpleRowFormatter& other);
+		/// Swaps the row formatter with another one.
+
+	std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames);
+		/// Formats the row field names.
+
+	std::string& formatValues(const ValueVec& vals, std::string& formattedValues);
+		/// Formats the row values.
+
+	int rowCount() const;
+		/// Returns row count.
+
+	void setColumnWidth(std::streamsize width);
+		/// Sets the column width.
+
+	std::streamsize getColumnWidth() const;
+		/// Returns the column width.
+		
+	std::streamsize getSpacing() const;
+		/// Returns the spacing.
+
+private:
+	std::streamsize _colWidth;
+	std::streamsize _spacing;
+	int             _rowCount;
+};
+
+
+///
+/// inlines
+///
+inline int SimpleRowFormatter::rowCount() const
+{
+	return _rowCount;
+}
+
+
+inline void SimpleRowFormatter::setColumnWidth(std::streamsize columnWidth)
+{
+	_colWidth = columnWidth;
+}
+
+
+inline std::streamsize SimpleRowFormatter::getColumnWidth() const
+{
+	return _colWidth;
+}
+
+
+inline std::streamsize SimpleRowFormatter::getSpacing() const
+{
+	return _spacing;
+}
+
+
+} } // namespace Poco::Data
+
+
+namespace std
+{
+	template<>
+	inline void swap<Poco::Data::SimpleRowFormatter>(Poco::Data::SimpleRowFormatter& s1, 
+		Poco::Data::SimpleRowFormatter& s2)
+		/// Full template specalization of std:::swap for SimpleRowFormatter
+	{
+		s1.swap(s2);
+	}
+}
+
+
+#endif // Data_SimpleRowFormatter_INCLUDED
diff --git a/Poco/Data/Statement.h b/Poco/Data/Statement.h
new file mode 100644
index 0000000..5373e09
--- /dev/null
+++ b/Poco/Data/Statement.h
@@ -0,0 +1,822 @@
+//
+// Statement.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Statement
+//
+// Definition of the Statement class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Statement_INCLUDED
+#define Data_Statement_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/StatementImpl.h"
+#include "Poco/Data/Binding.h"
+#include "Poco/Data/Range.h"
+#include "Poco/Data/Bulk.h"
+#include "Poco/Data/Row.h"
+#include "Poco/Data/SimpleRowFormatter.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Mutex.h"
+#include "Poco/ActiveMethod.h"
+#include "Poco/ActiveResult.h"
+#include "Poco/Format.h"
+#include <algorithm>
+
+
+namespace Poco {
+namespace Data {
+
+
+class AbstractBinding;
+class AbstractExtraction;
+class Session;
+class Limit;
+
+
+class Data_API Statement
+	/// A Statement is used to execute SQL statements.
+	/// It does not contain code of its own.
+	/// Its main purpose is to forward calls to the concrete StatementImpl stored inside.
+	/// Statement execution can be synchronous or asynchronous.
+	/// Synchronous ececution is achieved through execute() call, while asynchronous is
+	/// achieved through executeAsync() method call.
+	/// An asynchronously executing statement should not be copied during the execution.
+	///
+	/// Note:
+	///
+	/// Once set as asynchronous through 'async' manipulator, statement remains
+	/// asynchronous for all subsequent execution calls, both execute() and executeAsync().
+	/// However, calling executAsync() on a synchronous statement shall execute
+	/// asynchronously but without altering the underlying statement's synchronous nature.
+	///
+	/// Once asynchronous, a statement can be reverted back to synchronous state in two ways:
+	///
+	///   1) By calling setAsync(false)
+	///   2) By means of 'sync' or 'reset' manipulators
+	///
+	/// See individual functions documentation for more details.
+	///
+	/// Statement owns the RowFormatter, which can be provided externaly through setFormatter()
+	/// member function.
+	/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is lazy
+	/// created and used.
+{
+public:
+	typedef void (*Manipulator)(Statement&);
+
+	typedef ActiveResult<std::size_t>                      Result;
+	typedef SharedPtr<Result>                              ResultPtr;
+	typedef ActiveMethod<std::size_t, bool, StatementImpl> AsyncExecMethod;
+	typedef SharedPtr<AsyncExecMethod>                     AsyncExecMethodPtr;
+
+	static const int WAIT_FOREVER = -1;
+
+	enum Storage
+	{
+		STORAGE_DEQUE   = StatementImpl::STORAGE_DEQUE_IMPL,
+		STORAGE_VECTOR  = StatementImpl::STORAGE_VECTOR_IMPL,
+		STORAGE_LIST    = StatementImpl::STORAGE_LIST_IMPL,
+		STORAGE_UNKNOWN = StatementImpl::STORAGE_UNKNOWN_IMPL
+	};
+
+	Statement(StatementImpl::Ptr pImpl);
+		/// Creates the Statement.
+
+	explicit Statement(Session& session);
+		/// Creates the Statement for the given Session.
+		///
+		/// The following:
+		///
+		///     Statement stmt(sess);
+		///     stmt << "SELECT * FROM Table", ...
+		///
+		/// is equivalent to:
+		///
+		///     Statement stmt(sess << "SELECT * FROM Table", ...);
+		///
+		/// but in some cases better readable.
+
+	~Statement();
+		/// Destroys the Statement.
+
+	Statement(const Statement& stmt);
+		/// Copy constructor.
+		/// If the statement has been executed asynchronously and has not been
+		/// synchronized prior to copy operation (i.e. is copied while executing),
+		/// this constructor shall synchronize it.
+
+	Statement& operator = (const Statement& stmt);
+		/// Assignment operator.
+
+	void swap(Statement& other);
+		/// Swaps the statement with another one.
+
+	template <typename T>
+	Statement& operator << (const T& t)
+		/// Concatenates data with the SQL statement string.
+	{
+		_pImpl->add(t);
+		return *this;
+	}
+
+	Statement& operator , (Manipulator manip);
+		/// Handles manipulators, such as now, async, etc.
+
+	Statement& operator , (AbstractBinding::Ptr pBind);
+		/// Registers the Binding with the Statement by calling addBind().
+
+	Statement& addBind(AbstractBinding::Ptr pBind);
+		/// Registers a single binding with the statement.
+
+	void removeBind(const std::string& name);
+		/// Removes the all the bindings with specified name from the statement.
+
+	Statement& operator , (AbstractBindingVec& bindVec);
+		/// Registers the Binding vector with the Statement.
+
+	template <typename C>
+	Statement& addBinding(C& bindingCont, bool reset)
+		/// Registers binding container with the Statement.
+	{
+		if (reset) _pImpl->resetBinding();
+		typename C::iterator itAB = bindingCont.begin();
+		typename C::iterator itABEnd = bindingCont.end();
+		for (; itAB != itABEnd; ++itAB) addBind(*itAB);
+		return *this;
+	}
+
+	template <typename C>
+	Statement& bind(const C& value)
+		/// Adds a binding to the Statement. This can be used to implement
+		/// generic binding mechanisms and is a nicer syntax for:
+		///
+		///     statement , bind(value);
+	{
+		(*this) , Keywords::bind(value);
+		return *this;
+	}
+
+	Statement& operator , (AbstractExtraction::Ptr extract);
+		/// Registers objects used for extracting data with the Statement by
+		/// calling addExtract().
+
+	Statement& operator , (AbstractExtractionVec& extVec);
+		/// Registers the extraction vector with the Statement.
+		/// The vector is registered at position 0 (i.e. for the first returned data set).
+
+	Statement& operator , (AbstractExtractionVecVec& extVecVec);
+		/// Registers the vector of extraction vectors with the Statement.
+
+	template <typename C>
+	Statement& addExtraction(C& val, bool reset)
+		/// Registers extraction container with the Statement.
+	{
+		if (reset) _pImpl->resetExtraction();
+		typename C::iterator itAE = val.begin();
+		typename C::iterator itAEEnd = val.end();
+		for (; itAE != itAEEnd; ++itAE) addExtract(*itAE);
+		return *this;
+	}
+
+	template <typename C>
+	Statement& addExtractions(C& val)
+		/// Registers container of extraction containers with the Statement.
+	{
+		_pImpl->resetExtraction();
+		typename C::iterator itAEV = val.begin();
+		typename C::iterator itAEVEnd = val.end();
+		for (; itAEV != itAEVEnd; ++itAEV) addExtraction(*itAEV, false);
+		return *this;
+	}
+
+	Statement& addExtract(AbstractExtraction::Ptr pExtract);
+		/// Registers a single extraction with the statement.
+
+	Statement& operator , (const Bulk& bulk);
+		/// Sets the bulk execution mode (both binding and extraction) for this
+		/// statement.Statement must not have any extractors or binders set at the
+		/// time when this operator is applied.
+		/// Failure to adhere to the above constraint shall result in
+		/// InvalidAccessException.
+
+	Statement& operator , (BulkFnType);
+		/// Sets the bulk execution mode (both binding and extraction) for this
+		/// statement.Statement must not have any extractors or binders set at the
+		/// time when this operator is applied.
+		/// Additionally, this function requires limit to be set in order to
+		/// determine the bulk size.
+		/// Failure to adhere to the above constraints shall result in
+		/// InvalidAccessException.
+
+	Statement& operator , (const Limit& extrLimit);
+		/// Sets a limit on the maximum number of rows a select is allowed to return.
+		///
+		/// Set per default to zero to Limit::LIMIT_UNLIMITED, which disables the limit.
+
+	Statement& operator , (RowFormatter::Ptr pRowFformatter);
+		/// Sets the row formatter for the statement.
+
+	Statement& operator , (const Range& extrRange);
+		/// Sets a an extraction range for the maximum number of rows a select is allowed to return.
+		///
+		/// Set per default to Limit::LIMIT_UNLIMITED which disables the range.
+
+	Statement& operator , (char value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::UInt8 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::Int8 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::UInt16 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::Int16 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::UInt32 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::Int32 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+#ifndef POCO_LONG_IS_64_BIT
+	Statement& operator , (long value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (unsigned long value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+#endif
+	Statement& operator , (Poco::UInt64 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (Poco::Int64 value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (double value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (float value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (bool value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (const std::string& value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	Statement& operator , (const char* value);
+		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
+
+	const std::string& toString() const;
+		/// Creates a string from the accumulated SQL statement.
+
+	std::size_t execute(bool reset = true);
+		/// Executes the statement synchronously or asynchronously.
+		/// Stops when either a limit is hit or the whole statement was executed.
+		/// Returns the number of rows extracted from the database (for statements
+		/// returning data) or number of rows affected (for all other statements).
+		/// If reset is true (default), associated storage is reset and reused.
+		/// Otherwise, the results from this execution step are appended.
+		/// Reset argument has no meaning for unlimited statements that return all rows.
+		/// If isAsync() returns  true, the statement is executed asynchronously
+		/// and the return value from this function is zero.
+		/// The result of execution (i.e. number of returned or affected rows) can be
+		/// obtained by calling wait() on the statement at a later point in time.
+
+	const Result& executeAsync(bool reset = true);
+		/// Executes the statement asynchronously.
+		/// Stops when either a limit is hit or the whole statement was executed.
+		/// Returns immediately. Calling wait() (on either the result returned from this
+		/// call or the statement itself) returns the number of rows extracted or number
+		/// of rows affected by the statement execution.
+		/// When executed on a synchronous statement, this method does not alter the
+		/// statement's synchronous nature.
+
+	void setAsync(bool async = true);
+		/// Sets the asynchronous flag. If this flag is true, executeAsync() is called
+		/// from the now() manipulator. This setting does not affect the statement's
+		/// capability to be executed synchronously by directly calling execute().
+
+	bool isAsync() const;
+		/// Returns true if statement was marked for asynchronous execution.
+
+	std::size_t wait(long milliseconds = WAIT_FOREVER);
+		/// Waits for the execution completion for asynchronous statements or
+		/// returns immediately for synchronous ones. The return value for
+		/// asynchronous statement is the execution result (i.e. number of
+		/// rows retrieved). For synchronous statements, the return value is zero.
+
+	bool initialized();
+		/// Returns true if the statement was initialized (i.e. not executed yet).
+
+	bool paused();
+		/// Returns true if the statement was paused (a range limit stopped it
+		/// and there is more work to do).
+
+	bool done();
+		/// Returns true if the statement was completely executed or false if a range limit stopped it
+		/// and there is more work to do. When no limit is set, it will always return true after calling execute().
+
+	Statement& reset(Session& session);
+		/// Resets the Statement so that it can be filled with a new SQL command.
+
+	bool canModifyStorage();
+		/// Returns true if statement is in a state that allows the internal storage to be modified.
+
+	Storage storage() const;
+		/// Returns the internal storage type for the statement.
+
+	void setStorage(const std::string& storage);
+		/// Sets the internal storage type for the statement.
+
+	const std::string& getStorage() const;
+		/// Returns the internal storage type for the statement.
+
+	std::size_t columnsExtracted(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
+		/// Returns the number of columns returned for current data set.
+		/// Default value indicates current data set (if any).
+
+	std::size_t rowsExtracted(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
+		/// Returns the number of rows returned for current data set during last statement
+		/// execution. Default value indicates current data set (if any).
+
+	std::size_t subTotalRowCount(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
+		/// Returns the number of rows extracted so far for the data set.
+		/// Default value indicates current data set (if any).
+
+	std::size_t extractionCount() const;
+		/// Returns the number of extraction storage buffers associated
+		/// with the current data set.
+
+	std::size_t dataSetCount() const;
+		/// Returns the number of data sets associated with the statement.
+
+	std::size_t nextDataSet();
+		/// Returns the index of the next data set.
+
+	std::size_t previousDataSet();
+		/// Returns the index of the previous data set.
+
+	bool hasMoreDataSets() const;
+		/// Returns false if the current data set index points to the last
+		/// data set. Otherwise, it returns true.
+
+	void setRowFormatter(RowFormatter::Ptr pRowFormatter);
+		/// Sets the row formatter for this statement.
+		/// Statement takes the ownership of the formatter.
+
+protected:
+	typedef StatementImpl::Ptr ImplPtr;
+
+	const AbstractExtractionVec& extractions() const;
+		/// Returns the extractions vector.
+
+	const MetaColumn& metaColumn(std::size_t pos) const;
+		/// Returns the type for the column at specified position.
+
+	const MetaColumn& metaColumn(const std::string& name) const;
+		/// Returns the type for the column with specified name.
+
+	 bool isNull(std::size_t col, std::size_t row) const;
+		/// Returns true if the current row value at column pos is null.
+
+	 bool isBulkExtraction() const;
+		/// Returns true if this statement extracts data in bulk.
+
+	ImplPtr impl() const;
+		/// Returns pointer to statement implementation.
+
+	const RowFormatter::Ptr& getRowFormatter();
+		/// Returns the row formatter for this statement.
+
+	Session session();
+		/// Returns the underlying session.
+
+private:
+
+	const Result& doAsyncExec(bool reset = true);
+		/// Asynchronously executes the statement.
+
+	template <typename T>
+	Statement& commaPODImpl(const T& val)
+	{
+		_arguments.push_back(val);
+		return *this;
+	}
+
+	StatementImpl::Ptr _pImpl;
+
+	// asynchronous execution related members
+	bool                _async;
+	mutable ResultPtr   _pResult;
+	Mutex               _mutex;
+	AsyncExecMethodPtr  _pAsyncExec;
+	std::vector<Any>    _arguments;
+	RowFormatter::Ptr   _pRowFormatter;
+	mutable std::string _stmtString;
+};
+
+//
+// inlines
+
+inline std::size_t Statement::subTotalRowCount(int dataSet) const
+{
+	return _pImpl->subTotalRowCount(dataSet);
+}
+
+
+namespace Keywords {
+
+
+//
+// Manipulators
+//
+
+inline void Data_API now(Statement& statement)
+	/// Enforces immediate execution of the statement.
+	/// If _isAsync flag has been set, execution is invoked asynchronously.
+{
+	statement.execute();
+}
+
+
+inline void Data_API sync(Statement& statement)
+	/// Sets the _isAsync flag to false, signalling synchronous execution.
+	/// Synchronous execution is default, so specifying this manipulator
+	/// only makes sense if async() was called for the statement before.
+{
+	statement.setAsync(false);
+}
+
+
+inline void Data_API async(Statement& statement)
+	/// Sets the _async flag to true, signalling asynchronous execution.
+{
+	statement.setAsync(true);
+}
+
+
+inline void Data_API deque(Statement& statement)
+	/// Sets the internal storage to std::deque.
+	/// std::deque is default storage, so specifying this manipulator
+	/// only makes sense if list() or deque() were called for the statement before.
+{
+	if (!statement.canModifyStorage())
+		throw InvalidAccessException("Storage not modifiable.");
+
+	statement.setStorage("deque");
+}
+
+
+inline void Data_API vector(Statement& statement)
+	/// Sets the internal storage to std::vector.
+{
+	if (!statement.canModifyStorage())
+		throw InvalidAccessException("Storage not modifiable.");
+
+	statement.setStorage("vector");
+}
+
+
+inline void Data_API list(Statement& statement)
+	/// Sets the internal storage to std::list.
+{
+	if (!statement.canModifyStorage())
+		throw InvalidAccessException("Storage not modifiable.");
+
+	statement.setStorage("list");
+}
+
+
+inline void Data_API reset(Statement& statement)
+	/// Sets all internal settings to their respective default values.
+{
+	if (!statement.canModifyStorage())
+		throw InvalidAccessException("Storage not modifiable.");
+
+	statement.setStorage("deque");
+	statement.setAsync(false);
+}
+
+
+} // namespace Keywords
+
+
+//
+// inlines
+//
+
+inline Statement& Statement::operator , (RowFormatter::Ptr pRowFformatter)
+{
+	_pRowFormatter = pRowFformatter;
+	return *this;
+}
+
+
+inline Statement& Statement::operator , (char value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::UInt8 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::Int8 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::UInt16 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::Int16 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::UInt32 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::Int32 value)
+{
+	return commaPODImpl(value);
+}
+
+
+#ifndef POCO_LONG_IS_64_BIT
+inline Statement& Statement::operator , (long value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (unsigned long value)
+{
+	return commaPODImpl(value);
+}
+#endif
+
+
+inline Statement& Statement::operator , (Poco::UInt64 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (Poco::Int64 value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (double value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (float value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (bool value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (const std::string& value)
+{
+	return commaPODImpl(value);
+}
+
+
+inline Statement& Statement::operator , (const char* value)
+{
+	return commaPODImpl(std::string(value));
+}
+
+
+inline void Statement::removeBind(const std::string& name)
+{
+	_pImpl->removeBind(name);
+}
+
+
+inline Statement& Statement::operator , (AbstractBinding::Ptr pBind)
+{
+	return addBind(pBind);
+}
+
+
+inline Statement& Statement::operator , (AbstractBindingVec& bindVec)
+{
+	return addBinding(bindVec, false);
+}
+
+
+inline Statement& Statement::operator , (AbstractExtraction::Ptr pExtract)
+{
+	return addExtract(pExtract);
+}
+
+
+inline Statement& Statement::operator , (AbstractExtractionVec& extVec)
+{
+	return addExtraction(extVec, false);
+}
+
+
+inline Statement& Statement::operator , (AbstractExtractionVecVec& extVecVec)
+{
+	return addExtractions(extVecVec);
+}
+
+
+inline Statement::ImplPtr Statement::impl() const
+{
+	return _pImpl;
+}
+
+
+inline const std::string& Statement::toString() const
+{
+	return _stmtString = _pImpl->toString();
+}
+
+inline const AbstractExtractionVec& Statement::extractions() const
+{
+	return _pImpl->extractions();
+}
+
+
+inline const MetaColumn& Statement::metaColumn(std::size_t pos) const
+{
+	return _pImpl->metaColumn(pos);
+}
+
+
+inline const MetaColumn& Statement::metaColumn(const std::string& name) const
+{
+	return _pImpl->metaColumn(name);
+}
+
+
+inline void Statement::setStorage(const std::string& storage)
+{
+	_pImpl->setStorage(storage);
+}
+
+
+inline std::size_t Statement::extractionCount() const
+{
+	return _pImpl->extractionCount();
+}
+
+
+inline std::size_t Statement::columnsExtracted(int dataSet) const
+{
+	return _pImpl->columnsExtracted(dataSet);
+}
+
+
+inline std::size_t Statement::rowsExtracted(int dataSet) const
+{
+	return _pImpl->rowsExtracted(dataSet);
+}
+
+
+inline std::size_t Statement::dataSetCount() const
+{
+	return _pImpl->dataSetCount();
+}
+
+
+inline std::size_t Statement::nextDataSet()
+{
+	return _pImpl->activateNextDataSet();
+}
+
+
+inline std::size_t Statement::previousDataSet()
+{
+	return _pImpl->activatePreviousDataSet();
+}
+
+
+inline bool Statement::hasMoreDataSets() const
+{
+	return _pImpl->hasMoreDataSets();
+}
+
+
+inline Statement::Storage Statement::storage() const
+{
+	return static_cast<Storage>(_pImpl->getStorage());
+}
+
+
+inline bool Statement::canModifyStorage()
+{
+	return (0 == extractionCount()) && (initialized() || done());
+}
+
+
+inline bool Statement::initialized()
+{
+	return _pImpl->getState() == StatementImpl::ST_INITIALIZED;
+}
+
+
+inline bool Statement::paused()
+{
+	return _pImpl->getState() == StatementImpl::ST_PAUSED;
+}
+
+
+inline bool Statement::done()
+{
+	return _pImpl->getState() == StatementImpl::ST_DONE;
+}
+
+
+inline bool Statement::isNull(std::size_t col, std::size_t row) const
+{
+	return _pImpl->isNull(col, row);
+}
+
+
+inline bool Statement::isBulkExtraction() const
+{
+	return _pImpl->isBulkExtraction();
+}
+
+
+inline bool Statement::isAsync() const
+{
+	return _async;
+}
+
+
+inline void Statement::setRowFormatter(RowFormatter::Ptr pRowFormatter)
+{
+	_pRowFormatter = pRowFormatter;
+}
+
+
+inline const RowFormatter::Ptr& Statement::getRowFormatter()
+{
+	if (!_pRowFormatter) _pRowFormatter = new SimpleRowFormatter;
+	return _pRowFormatter;
+}
+
+
+inline void swap(Statement& s1, Statement& s2)
+{
+	s1.swap(s2);
+}
+
+
+} } // namespace Poco::Data
+
+
+namespace std
+{
+	template<>
+	inline void swap<Poco::Data::Statement>(Poco::Data::Statement& s1,
+		Poco::Data::Statement& s2)
+		/// Full template specalization of std:::swap for Statement
+	{
+		s1.swap(s2);
+	}
+}
+
+
+#endif // Data_Statement_INCLUDED
diff --git a/Poco/Data/StatementCreator.h b/Poco/Data/StatementCreator.h
new file mode 100644
index 0000000..ca27804
--- /dev/null
+++ b/Poco/Data/StatementCreator.h
@@ -0,0 +1,73 @@
+//
+// StatementCreator.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  StatementCreator
+//
+// Definition of the StatementCreator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_StatementCreator_INCLUDED
+#define Data_StatementCreator_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/Data/Statement.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API StatementCreator
+	/// A StatementCreator creates Statements.
+{
+public:
+	StatementCreator();
+		/// Creates an unitialized StatementCreator.
+		
+	StatementCreator(Poco::AutoPtr<SessionImpl> ptrImpl);
+		/// Creates a StatementCreator.
+
+	StatementCreator(const StatementCreator& other);
+		/// Creates a StatementCreator by copying another one.
+
+	~StatementCreator();
+		/// Destroys the StatementCreator.
+
+	StatementCreator& operator = (const StatementCreator& other);
+		/// Assignment operator.
+		
+	void swap(StatementCreator& other);
+		/// Swaps the StatementCreator with another one.	
+		
+	template <typename T>
+	Statement operator << (const T& t)
+		/// Creates a Statement.
+	{
+		if (!_ptrImpl->isConnected())
+			throw NotConnectedException(_ptrImpl->connectionString());
+
+		Statement stmt(_ptrImpl->createStatementImpl());
+		stmt << t;
+		return stmt;
+	}
+
+private:
+	Poco::AutoPtr<SessionImpl> _ptrImpl;
+};
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_StatementCreator_INCLUDED
diff --git a/Poco/Data/StatementImpl.h b/Poco/Data/StatementImpl.h
new file mode 100644
index 0000000..d9371a7
--- /dev/null
+++ b/Poco/Data/StatementImpl.h
@@ -0,0 +1,632 @@
+//
+// StatementImpl.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  StatementImpl
+//
+// Definition of the StatementImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_StatementImpl_INCLUDED
+#define Data_StatementImpl_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractBinding.h"
+#include "Poco/Data/AbstractExtraction.h"
+#include "Poco/Data/Range.h"
+#include "Poco/Data/Bulk.h"
+#include "Poco/Data/Column.h"
+#include "Poco/Data/Extraction.h"
+#include "Poco/Data/BulkExtraction.h"
+#include "Poco/Data/SessionImpl.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/String.h"
+#include "Poco/Format.h"
+#include "Poco/Exception.h"
+#include <vector>
+#include <list>
+#include <deque>
+#include <string>
+#include <sstream>
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API StatementImpl
+	/// StatementImpl interface that subclasses must implement to define database dependent query execution.
+	///
+	/// StatementImpl's are noncopyable.
+{
+public:
+	typedef Poco::SharedPtr<StatementImpl> Ptr;
+
+	enum State
+	{
+		ST_INITIALIZED,
+		ST_COMPILED,
+		ST_BOUND,
+		ST_PAUSED,
+		ST_DONE,
+		ST_RESET
+	};
+
+	enum Storage
+	{
+		STORAGE_DEQUE_IMPL,
+		STORAGE_VECTOR_IMPL,
+		STORAGE_LIST_IMPL,
+		STORAGE_UNKNOWN_IMPL
+	};
+
+	enum BulkType
+	{
+		BULK_UNDEFINED,     
+			/// Bulk mode not defined yet.
+		BULK_BINDING,       
+			/// Binding in bulk mode.
+			/// If extraction is present in the same statement, 
+			/// it must also be bulk.
+		BULK_EXTRACTION,    
+			/// Extraction in bulk mode.
+			/// If binding is present in the same statement, 
+			/// it must also be bulk.
+		BULK_FORBIDDEN     
+			/// Bulk forbidden. 
+			/// Happens when the statement has already been 
+			/// configured as non-bulk.
+	};
+
+	static const std::string DEQUE;
+	static const std::string VECTOR;
+	static const std::string LIST;
+	static const std::string UNKNOWN;
+
+	static const int USE_CURRENT_DATA_SET = -1;
+
+	StatementImpl(SessionImpl& rSession);
+		/// Creates the StatementImpl.
+
+	virtual ~StatementImpl();
+		/// Destroys the StatementImpl.
+
+	template <typename T> 
+	void add(const T& t)
+		/// Appends SQL statement (fragments).
+	{
+		_ostr << t;
+	}
+
+	void addBind(AbstractBinding::Ptr pBinding);
+		/// Registers the Binding with the StatementImpl.
+
+	void removeBind(const std::string& name);
+		/// Unregisters all the bindings having specified name with the StatementImpl.
+		/// Bindings are released and, if this class was the sole owner, deleted.
+
+	void addExtract(AbstractExtraction::Ptr pExtraction);
+		/// Registers objects used for extracting data with the StatementImpl.
+
+	void setExtractionLimit(const Limit& extrLimit);
+		/// Changes the extractionLimit to extrLimit. 
+		/// Per default no limit (EXTRACT_UNLIMITED) is set.
+
+	std::string toString() const;
+		/// Create a string version of the SQL statement.
+
+	std::size_t execute(const bool& reset = true);
+		/// Executes a statement. Returns the number of rows 
+		/// extracted for statements returning data or number of rows 
+		/// affected for all other statements (insert, update, delete).
+		/// If reset is true (default), the underlying bound storage is
+		/// reset and reused. In case of containers, this means they are
+		/// cleared and resized to accomodate the number of rows returned by
+		/// this execution step. When reset is false, data is appended to the
+		/// bound containers during multiple execute calls.
+
+	void reset();
+		/// Resets the statement, so that we can reuse all bindings and re-execute again.
+
+	State getState() const;
+		/// Returns the state of the Statement.
+
+	void setStorage(Storage storage);
+		/// Sets the storage type for this statement;
+
+	void setStorage(const std::string& storage);
+		/// Sets the storage type for this statement;
+
+	Storage getStorage() const;
+		/// Returns the storage type for this statement.
+
+	std::size_t extractionCount() const;
+		/// Returns the number of extraction storage buffers associated
+		/// with the statement.
+
+	std::size_t dataSetCount() const;
+		/// Returns the number of data sets associated with the statement.
+		
+protected:
+	virtual std::size_t columnsReturned() const = 0;
+		/// Returns number of columns returned by query. 
+
+	virtual int affectedRowCount() const = 0;
+		/// Returns the number of affected rows.
+		/// Used to find out the number of rows affected by insert, delete or update.
+		/// 
+		/// Some back-ends may return a negative number in certain circumstances (e.g.
+		/// some ODBC drivers when this function is called after a select statement
+		/// execution).
+
+	virtual const MetaColumn& metaColumn(std::size_t pos) const = 0;
+		/// Returns column meta data.
+
+	const MetaColumn& metaColumn(const std::string& name) const;
+		/// Returns column meta data.
+
+	virtual bool hasNext() = 0;
+		/// Returns true if a call to next() will return data. 
+		///
+		/// Note that the implementation must support
+		/// several consecutive calls to hasNext without data getting lost, 
+		/// ie. hasNext(); hasNext(); next() must be equal to hasNext(); next();
+
+	virtual std::size_t next() = 0;
+		/// Retrieves the next row or set of rows from the resultset and
+		/// returns the number of rows retreved.
+		///
+		/// Will throw, if the resultset is empty.
+		/// Expects the statement to be compiled and bound.
+
+	virtual bool canBind() const = 0;
+		/// Returns true if another bind is possible.
+
+	virtual bool canCompile() const = 0;
+		/// Returns true if another compile is possible.
+
+	virtual void compileImpl() = 0;
+		/// Compiles the statement, doesn't bind yet.
+
+	virtual void bindImpl() = 0;
+		/// Binds parameters.
+
+	virtual AbstractExtraction::ExtractorPtr extractor() = 0;
+		/// Returns the concrete extractor used by the statement.
+
+	const AbstractExtractionVec& extractions() const;
+		/// Returns the const reference to extractions vector.
+
+	AbstractExtractionVec& extractions();
+		/// Returns the reference to extractions vector.
+
+	void fixupExtraction();
+		/// Sets the AbstractExtractor at the extractors.
+
+	Limit::SizeT getExtractionLimit();
+		/// Returns the extraction limit value.
+
+	const Limit& extractionLimit() const;
+		/// Returns the extraction limit.
+
+	std::size_t columnsExtracted(int dataSet = USE_CURRENT_DATA_SET) const;
+		/// Returns the number of columns that the extractors handle.
+
+	std::size_t rowsExtracted(int dataSet = USE_CURRENT_DATA_SET) const;
+		/// Returns the number of rows extracted for current data set.
+		/// Default value (USE_CURRENT_DATA_SET) indicates current data set (if any).
+
+	std::size_t subTotalRowCount(int dataSet = USE_CURRENT_DATA_SET) const;
+		/// Returns the number of rows extracted so far for the data set.
+		/// Default value indicates current data set (if any).
+
+	void makeExtractors(std::size_t count);
+		/// Determines the type of the internal extraction container and
+		/// calls the extraction creation function (addInternalExtract)
+		/// with appropriate data type and container type arguments.
+		/// 
+		/// This function is only called in cases when there is data 
+		/// returned by query, but no data storage supplied by user.
+		///
+		/// The type of the internal container is determined in the
+		/// following order:
+		/// 1. If statement has the container type set, the type is used.
+		/// 2. If statement does not have the container type set,
+		///    session is queried for container type setting. If the
+		///    session container type setting is found, it is used.
+		/// 3. If neither session nor statement have the internal
+		///    container type set, std::deque is used.
+		///
+		/// Supported internal extraction container types are:
+		/// - std::deque (default)
+		/// - std::vector
+		/// - std::list
+
+	SessionImpl& session();
+		/// Rteurns session associated with this statement.
+
+	virtual AbstractBinding::BinderPtr binder() = 0;
+		/// Returns the concrete binder used by the statement.
+
+	const AbstractBindingVec& bindings() const;
+		/// Returns the const reference to bindings vector.
+
+	AbstractBindingVec& bindings();
+		/// Returns the reference to bindings.
+
+	void fixupBinding();
+		/// Sets the AbstractBinder at the bindings.
+
+	void resetBinding();
+		/// Resets binding so it can be reused again.
+
+	virtual bool isStoredProcedure() const;
+		/// Returns true if the statement is stored procedure.
+		/// Used as a help to determine whether to automatically create the
+		/// internal extractions when no outside extraction is supplied.
+		/// The reason for this function is to prevent unnecessary internal
+		/// extraction creation in cases (behavior exhibited by some ODBC drivers) 
+		/// when there is data available from the stored procedure call 
+		/// statement execution but no external extraction is supplied (as is 
+		/// usually the case when stored procedures are called). In such cases
+		/// no storage is needed because output parameters serve as storage.
+		/// At the Data framework level, this function always returns false.
+		/// When connector-specific behavior is desired, it should be overriden 
+		/// by the statement implementation.
+
+	std::size_t currentDataSet() const;
+		/// Returns the current data set.
+
+	std::size_t activateNextDataSet();
+		/// Returns the next data set index, or throws NoDataException if the last 
+		/// data set was reached.
+
+	std::size_t activatePreviousDataSet();
+		/// Returns the previous data set index, or throws NoDataException if the last 
+		/// data set was reached.
+
+	bool hasMoreDataSets() const;
+		/// Returns true if there are data sets not activated yet.
+
+private:
+	void compile();
+		/// Compiles the statement.
+
+	void bind();
+		/// Binds the statement, if not yet bound.
+
+	std::size_t executeWithLimit();
+		/// Executes with an upper limit set. Returns the number of rows 
+		/// extracted for statements returning data or number of rows 
+		/// affected for all other statements (insert, update, delete).
+
+	std::size_t executeWithoutLimit();
+		/// Executes without an upper limit set. Returns the number of rows 
+		/// extracted for statements returning data or number of rows 
+		/// affected for all other statements (insert, update, delete).
+
+	void resetExtraction();
+		/// Resets extraction so it can be reused again.
+
+	template <class C>
+	SharedPtr<InternalExtraction<C> > createExtract(const MetaColumn& mc)
+	{
+		C* pData = new C;
+		Column<C>* pCol = new Column<C>(mc, pData);
+		return new InternalExtraction<C>(*pData, pCol, Poco::UInt32(currentDataSet()));
+	}
+
+	template <class C>
+	SharedPtr<InternalBulkExtraction<C> > createBulkExtract(const MetaColumn& mc)
+	{
+		C* pData = new C;
+		Column<C>* pCol = new Column<C>(mc, pData);
+		return new InternalBulkExtraction<C>(*pData,
+			pCol,
+			static_cast<Poco::UInt32>(getExtractionLimit()),
+			Position(static_cast<Poco::UInt32>(currentDataSet())));
+	}
+
+	template <class T>
+	void addInternalExtract(const MetaColumn& mc)
+		/// Creates and adds the internal extraction.
+		///
+		/// The decision about internal extraction container is done 
+		/// in a following way:
+		///
+		/// If this statement has _storage member set, that setting
+		/// overrides the session setting for storage, otherwise the
+		/// session setting is used.
+		/// If neither this statement nor the session have the storage
+		/// type set, std::deque is the default container type used.
+	{
+		std::string storage;
+	
+		switch (_storage)
+		{
+		case STORAGE_DEQUE_IMPL:  
+			storage = DEQUE; break;
+		case STORAGE_VECTOR_IMPL: 
+			storage = VECTOR; break;
+		case STORAGE_LIST_IMPL:   
+			storage = LIST; break;
+		case STORAGE_UNKNOWN_IMPL:
+			storage = AnyCast<std::string>(session().getProperty("storage")); 
+			break;
+		}
+
+		if (storage.empty()) storage = DEQUE;
+
+		if (0 == icompare(DEQUE, storage))
+		{
+			if (!isBulkExtraction())
+				addExtract(createExtract<std::deque<T> >(mc));
+			else
+				addExtract(createBulkExtract<std::deque<T> >(mc));
+		}
+		else if (0 == icompare(VECTOR, storage))
+		{
+			if (!isBulkExtraction())
+				addExtract(createExtract<std::vector<T> >(mc));
+			else
+				addExtract(createBulkExtract<std::vector<T> >(mc));
+		}
+		else if (0 == icompare(LIST, storage))
+		{
+			if (!isBulkExtraction())
+				addExtract(createExtract<std::list<T> >(mc));
+			else
+				addExtract(createBulkExtract<std::list<T> >(mc));
+		}
+	}
+
+	bool isNull(std::size_t col, std::size_t row) const;
+		/// Returns true if the value in [col, row] is null.
+		
+	void forbidBulk();
+		/// Forbids bulk operations.
+
+	void setBulkBinding();
+		/// Sets the bulk binding flag.
+
+	void setBulkExtraction(const Bulk& l);
+		/// Sets the bulk extraction flag and extraction limit.
+	
+	void resetBulk();
+		/// Resets the bulk extraction and binding flag.
+
+	bool bulkBindingAllowed() const;
+		/// Returns true if statement can be set to bind data in bulk.
+		/// Once bulk binding is set for a statement, it can be
+		/// neither altered nor mixed with non-bulk mode binding.
+
+	bool bulkExtractionAllowed() const;
+		/// Returns true if statement can be set to extract data in bulk.
+		/// Once bulk extraction is set for a statement, it can be
+		/// neither altered nor mixed with non-bulk mode extraction.
+
+	bool isBulkBinding() const;
+		/// Returns true if statement is set to bind data in bulk.
+
+	bool isBulkExtraction() const;
+		/// Returns true if statement is set to extract data in bulk.
+
+	bool isBulkSupported() const;
+		/// Returns true if connector and session support bulk operation.
+
+	void formatSQL(std::vector<Any>& arguments);
+		/// Formats the SQL string by filling in placeholders with values from supplied vector.
+
+	void assignSubTotal(bool reset);
+
+	StatementImpl(const StatementImpl& stmt);
+	StatementImpl& operator = (const StatementImpl& stmt);
+
+	typedef std::vector<std::size_t> CountVec;
+
+	State                    _state;
+	Limit                    _extrLimit;
+	std::size_t              _lowerLimit;
+	std::vector<int>         _columnsExtracted;
+	SessionImpl&             _rSession;
+	Storage                  _storage;
+	std::ostringstream       _ostr;
+	AbstractBindingVec       _bindings;
+	AbstractExtractionVecVec _extractors;
+	std::size_t              _curDataSet;
+	BulkType                 _bulkBinding;
+	BulkType                 _bulkExtraction;
+	CountVec                 _subTotalRowCount;
+
+	friend class Statement; 
+};
+
+
+//
+// inlines
+//
+
+
+inline void StatementImpl::addBind(AbstractBinding::Ptr pBinding)
+{
+	poco_check_ptr (pBinding);
+	_bindings.push_back(pBinding);
+}
+
+
+inline std::string StatementImpl::toString() const
+{
+	return _ostr.str();
+}
+
+
+inline const AbstractBindingVec& StatementImpl::bindings() const
+{
+	return _bindings;
+}
+
+
+inline AbstractBindingVec& StatementImpl::bindings()
+{
+	return _bindings;
+}
+
+
+inline const AbstractExtractionVec& StatementImpl::extractions() const
+{
+	poco_assert (_curDataSet < _extractors.size());
+	return _extractors[_curDataSet];
+}
+
+
+inline AbstractExtractionVec& StatementImpl::extractions()
+{
+	poco_assert (_curDataSet < _extractors.size());
+	return _extractors[_curDataSet];
+}
+
+
+inline StatementImpl::State StatementImpl::getState() const
+{
+	return _state;
+}
+
+
+inline SessionImpl& StatementImpl::session()
+{
+	return _rSession;
+}
+
+
+inline void StatementImpl::setStorage(Storage storage)
+{
+	_storage = storage;
+}
+
+
+inline StatementImpl::Storage StatementImpl::getStorage() const
+{
+	return _storage;
+}
+
+
+inline std::size_t StatementImpl::extractionCount() const
+{
+	return static_cast<std::size_t>(extractions().size());
+}
+
+
+inline std::size_t StatementImpl::dataSetCount() const
+{
+	return static_cast<std::size_t>(_extractors.size());
+}
+
+
+inline bool StatementImpl::isStoredProcedure() const
+{
+	return false;
+}
+
+
+inline bool StatementImpl::isNull(std::size_t col, std::size_t row) const
+{
+	try 
+	{
+		return extractions().at(col)->isNull(row);
+	}
+	catch (std::out_of_range& ex)
+	{ 
+		throw RangeException(ex.what()); 
+	}
+}
+
+
+inline std::size_t StatementImpl::currentDataSet() const
+{
+	return _curDataSet;
+}
+
+
+inline Limit::SizeT StatementImpl::getExtractionLimit()
+{
+	return _extrLimit.value();
+}
+
+
+inline const Limit& StatementImpl::extractionLimit() const
+{
+	return _extrLimit;
+}
+
+
+inline void StatementImpl::forbidBulk()
+{
+	_bulkBinding = BULK_FORBIDDEN;
+	_bulkExtraction = BULK_FORBIDDEN;
+}
+
+
+inline void StatementImpl::setBulkBinding()
+{
+	_bulkBinding = BULK_BINDING;
+}
+
+
+inline bool StatementImpl::bulkBindingAllowed() const
+{
+	return BULK_UNDEFINED == _bulkBinding ||
+		BULK_BINDING == _bulkBinding;
+}
+
+
+inline bool StatementImpl::bulkExtractionAllowed() const
+{
+	return BULK_UNDEFINED == _bulkExtraction ||
+		BULK_EXTRACTION == _bulkExtraction;
+}
+
+
+inline bool StatementImpl::isBulkBinding() const
+{
+	return BULK_BINDING == _bulkBinding;
+}
+
+
+inline bool StatementImpl::isBulkExtraction() const
+{
+	return BULK_EXTRACTION == _bulkExtraction;
+}
+
+	
+inline void StatementImpl::resetBulk()
+{
+	_bulkExtraction = BULK_UNDEFINED;
+	_bulkBinding = BULK_UNDEFINED;\
+	setExtractionLimit(Limit(Limit::LIMIT_UNLIMITED, false, false));
+}
+
+
+inline bool StatementImpl::isBulkSupported() const
+{
+	return _rSession.getFeature("bulk");
+}
+
+
+inline bool StatementImpl::hasMoreDataSets() const
+{
+	return currentDataSet() + 1 < dataSetCount();
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_StatementImpl_INCLUDED
diff --git a/Poco/Data/Time.h b/Poco/Data/Time.h
new file mode 100644
index 0000000..0711690
--- /dev/null
+++ b/Poco/Data/Time.h
@@ -0,0 +1,229 @@
+//
+// Time.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Time
+//
+// Definition of the Time class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_Time_INCLUDED
+#define Data_Time_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Dynamic/VarHolder.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+
+namespace Dynamic {
+
+class Var;
+
+}
+
+class DateTime;
+
+namespace Data {
+
+
+class Date;
+
+
+class Data_API Time
+	/// Time class wraps a DateTime and exposes time related interface.
+	/// The purpose of this class is binding/extraction support for time fields.
+{
+public:
+	Time();
+		/// Creates the Time
+
+	Time(int hour, int minute, int second);
+		/// Creates the Time
+
+	Time(const DateTime& dt);
+		/// Creates the Time from DateTime
+
+	~Time();
+		/// Destroys the Time.
+
+	int hour() const;
+		/// Returns the hour.
+
+	int minute() const;
+		/// Returns the minute.
+
+	int second() const;
+		/// Returns the second.
+
+	void assign(int hour, int minute, int second);
+		/// Assigns time.
+
+	Time& operator = (const Time& t);
+		/// Assignment operator for Time.
+
+	Time& operator = (const DateTime& dt);
+		/// Assignment operator for DateTime.
+
+	Time& operator = (const Poco::Dynamic::Var& var);
+		/// Assignment operator for Var.
+
+	bool operator == (const Time& time) const;
+		/// Equality operator.
+
+	bool operator != (const Time& time) const;
+		/// Inequality operator.
+
+	bool operator < (const Time& time) const;
+		/// Less then operator.
+
+	bool operator > (const Time& time) const;
+		/// Greater then operator.
+
+private:
+	int _hour;
+	int _minute;
+	int _second;
+};
+
+
+//
+// inlines
+//
+inline int Time::hour() const
+{
+	return _hour;
+}
+
+
+inline int Time::minute() const
+{
+	return _minute;
+}
+
+
+inline  int Time::second() const
+{
+	return _second;
+}
+
+
+inline Time& Time::operator = (const Time& t)
+{
+	assign(t.hour(), t.minute(), t.second());
+	return *this;
+}
+
+
+inline Time& Time::operator = (const DateTime& dt)
+{
+	assign(dt.hour(), dt.minute(), dt.second());
+	return *this;
+}
+
+
+inline bool Time::operator == (const Time& time) const
+{
+	return _hour == time.hour() &&
+		_minute == time.minute() &&
+		_second == time.second();
+}
+
+
+inline bool Time::operator != (const Time& time) const
+{
+	return !(*this == time);
+}
+
+
+inline bool Time::operator > (const Time& time) const
+{
+	return !(*this == time) && !(*this < time);
+}
+
+
+} } // namespace Poco::Data
+
+
+//
+// VarHolderImpl<Time>
+//
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <>
+class VarHolderImpl<Poco::Data::Time>: public VarHolder
+{
+public:
+	VarHolderImpl(const Poco::Data::Time& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Poco::Data::Time);
+	}
+
+	void convert(Poco::Timestamp& val) const
+	{
+		Poco::DateTime dt;
+		dt.assign(dt.year(), dt.month(), dt.day(), _val.hour(), _val.minute(), _val.second());
+		val = dt.timestamp();
+	}
+
+	void convert(Poco::DateTime& val) const
+	{
+		Poco::DateTime dt;
+		dt.assign(dt.year(), dt.month(), dt.day(), _val.hour(), _val.minute(), _val.second());
+		val = dt;
+	}
+
+	void convert(Poco::LocalDateTime& val) const
+	{
+		Poco::LocalDateTime ldt;
+		ldt.assign(ldt.year(), ldt.month(), ldt.day(), _val.hour(), _val.minute(), _val.second());
+		val = ldt;
+	}
+
+	void convert(std::string& val) const
+	{
+		DateTime dt(0, 1, 1, _val.hour(), _val.minute(), _val.second());
+		val = DateTimeFormatter::format(dt, "%H:%M:%S");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Poco::Data::Time& value() const
+	{
+		return _val;
+	}
+
+private:
+	VarHolderImpl();
+	Poco::Data::Time _val;
+};
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // Data_Time_INCLUDED
diff --git a/Poco/Data/Transaction.h b/Poco/Data/Transaction.h
new file mode 100644
index 0000000..a8fdc46
--- /dev/null
+++ b/Poco/Data/Transaction.h
@@ -0,0 +1,194 @@
+//
+// Transaction.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  Transaction
+//
+// Definition of the Transaction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+
+#ifndef Data_Transaction_INCLUDED
+#define Data_Transaction_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/Session.h"
+#include "Poco/Logger.h"
+
+
+namespace Poco {
+namespace Data {
+
+
+class Data_API Transaction
+	/// Transaction helps with transactions in domain logic.
+	/// When an Transaction object is created, it first checks whether a
+	/// transaction is in progress. If not, a new transaction is created.
+	/// When the Transaction is destroyed, and commit() has been called,
+	/// nothing is done. Otherwise, the current transaction is rolled back.
+	/// See Transaction for more details and purpose of this template.
+{
+public:
+	Transaction(Poco::Data::Session& session, Poco::Logger* pLogger = 0);
+		/// Creates the Transaction and starts it, using the given database session and logger.
+
+	Transaction(Poco::Data::Session& session, bool start);
+		/// Creates the Transaction, using the given database session.
+		/// If start is true, transaction is started, otherwise begin() must be called
+		/// to start the transaction.
+		
+	template <typename T>
+	Transaction(Poco::Data::Session& rSession, T& t, Poco::Logger* pLogger = 0): 
+		_rSession(rSession),
+		_pLogger(pLogger)
+		/// Creates the Transaction, using the given database session, transactor and logger.
+		/// The transactor type must provide operator () overload taking non-const Session 
+		/// reference as an argument.
+		///
+		/// When transaction is created using this constructor, it is executed and
+		/// commited automatically. If no error occurs, rollback is disabled and does
+		/// not occur at destruction time. If an error occurs resulting in exception being
+		/// thrown, the transaction is rolled back and exception propagated to calling code.
+		/// 
+		/// Example usage:
+		/// 
+		/// struct Transactor
+		/// {
+		///		void operator () (Session& session) const
+		///		{
+		///			// do something ...
+		///		}
+		/// };
+		/// 
+		/// Transactor tr;
+		/// Transaction tn(session, tr); 
+	{
+		try { transact(t); }
+		catch (...)
+		{
+			if (_pLogger) _pLogger->error("Error executing transaction.");
+			rollback();
+			throw;
+		}
+	}
+
+	~Transaction();
+		/// Destroys the Transaction.
+		/// Rolls back the current database transaction if it has not been commited
+		/// (by calling commit()), or rolled back (by calling rollback()).
+		///
+		/// If an exception is thrown during rollback, the exception is logged
+		/// and no further action is taken. 
+
+	void setIsolation(Poco::UInt32 ti);
+		/// Sets the transaction isolation level.
+
+	Poco::UInt32 getIsolation();
+		/// Returns the transaction isolation level.
+
+	bool hasIsolation(Poco::UInt32 ti);
+		/// Returns true iff the transaction isolation level corresponding
+		/// to the supplied bitmask is supported.
+
+	bool isIsolation(Poco::UInt32 ti);
+		/// Returns true iff the transaction isolation level corresponds
+		/// to the supplied bitmask.
+
+	void execute(const std::string& sql, bool doCommit = true);
+		/// Executes and, if doCommit is true, commits the transaction.
+		/// Passing true value for commit disables rollback during destruction
+		/// of this Transaction object.
+
+	void execute(const std::vector<std::string>& sql);
+		/// Executes all the SQL statements supplied in the vector and, after the last
+		/// one is sucesfully executed, commits the transaction.
+		/// If an error occurs during execution, transaction is rolled back.
+		/// Passing true value for commit disables rollback during destruction
+		/// of this Transaction object.
+
+	template <typename T>
+	void transact(T& t)
+		/// Executes the transactor and, unless transactor throws an exception, 
+		/// commits the transaction.
+	{
+		if (!isActive()) begin();
+		t(_rSession);
+		commit();
+	}
+
+	void commit();
+		/// Commits the current transaction.
+		
+	void rollback();
+		/// Rolls back the current transaction.
+		
+	bool isActive();
+		/// Returns false after the transaction has been committed or rolled back,
+		/// true if the transaction is ongoing.
+
+	void setLogger(Poco::Logger* pLogger);
+		/// Sets the logger for this transaction.
+		/// Transaction does not take the ownership of the pointer.
+
+private:
+	Transaction();
+	Transaction(const Transaction&);
+	Transaction& operator = (const Transaction&);
+	
+	void begin();
+		/// Begins the transaction if the session is already not in transaction.
+		/// Otherwise does nothing.
+
+	Session _rSession;
+	Logger* _pLogger;
+};
+
+
+inline bool Transaction::isActive()
+{
+	return _rSession.isTransaction();
+}
+
+
+inline void Transaction::setIsolation(Poco::UInt32 ti)
+{
+	_rSession.setTransactionIsolation(ti);
+}
+
+
+inline Poco::UInt32 Transaction::getIsolation()
+{
+	return _rSession.getTransactionIsolation();
+}
+
+
+inline bool Transaction::hasIsolation(Poco::UInt32 ti)
+{
+	return _rSession.isTransactionIsolation(ti);
+}
+
+
+inline bool Transaction::isIsolation(Poco::UInt32 ti)
+{
+	return _rSession.isTransactionIsolation(ti);
+}
+
+
+inline void Transaction::setLogger(Poco::Logger* pLogger)
+{
+	_pLogger = pLogger;
+}
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_Transaction_INCLUDED
diff --git a/Poco/Data/TypeHandler.h b/Poco/Data/TypeHandler.h
new file mode 100644
index 0000000..4a2424c
--- /dev/null
+++ b/Poco/Data/TypeHandler.h
@@ -0,0 +1,2090 @@
+//
+// TypeHandler.h
+//
+// Library: Data
+// Package: DataCore
+// Module:  TypeHandler
+//
+// Definition of the TypeHandler class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Data_TypeHandler_INCLUDED
+#define Data_TypeHandler_INCLUDED
+
+
+#include "Poco/Data/Data.h"
+#include "Poco/Data/AbstractBinder.h"
+#include "Poco/Data/AbstractExtractor.h"
+#include "Poco/Data/AbstractPreparator.h"
+#include "Poco/Nullable.h"
+#include "Poco/Tuple.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/SharedPtr.h"
+#include <cstddef>
+
+
+namespace Poco {
+namespace Data {
+
+
+class AbstractTypeHandler
+	/// Parent class for type handlers. 
+	/// The reason for this class is to prevent instantiations of type handlers.
+	/// For documentation on type handlers, see TypeHandler class.
+{
+protected:
+	AbstractTypeHandler();
+	~AbstractTypeHandler();
+	AbstractTypeHandler(const AbstractTypeHandler&);
+	AbstractTypeHandler& operator = (const AbstractTypeHandler&);
+};
+
+
+template <class T>
+class TypeHandler: public AbstractTypeHandler
+	/// Converts Rows to a Type and the other way around. Provide template specializations to support your own complex types.
+	///
+	/// Take as example the following (simplified) class:
+	///	class Person
+	///	{
+	///	private:
+	///		std::string _lastName;
+	///		std::string _firstName;
+	///		int		 _age;
+	///	public:
+	///		const std::string& getLastName();
+	///		[...] // other set/get methods (returning const reference), a default constructor, 
+	///		[...] // optional < operator (for set, multiset) or function operator (for map, multimap)
+	///	};
+	///
+	/// The TypeHandler must provide a custom bind, size, prepare and extract method:
+	///	
+	///	template <>
+	///	class TypeHandler<struct Person>
+	///	{
+	///	public:
+	///		static std::size_t size()
+	///		{
+	///			return 3; // lastName + firstname + age occupy three columns
+	///		}
+	///	
+	///		static void bind(std::size_t pos, const Person& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	///		{
+	///			// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
+	///			// Note that we advance pos by the number of columns the datatype uses! For string/int this is one.
+	///			poco_assert_dbg (!pBinder.isNull());
+	///			TypeHandler<std::string>::bind(pos++, obj.getLastName(), pBinder, dir);
+	///			TypeHandler<std::string>::bind(pos++, obj.getFirstName(), pBinder, dir);
+	///			TypeHandler<int>::bind(pos++, obj.getAge(), pBinder, dir);
+	///		}
+	///	
+	///		static void prepare(std::size_t pos, const Person& obj, AbstractPreparator::Ptr pPreparator)
+	///		{
+	///			// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
+	///			poco_assert_dbg (!pPreparator.isNull());
+	///			TypeHandler<std::string>::prepare(pos++, obj.getLastName(), pPreparator);
+	///			TypeHandler<std::string>::prepare(pos++, obj.getFirstName(), pPreparator);
+	///			TypeHandler<int>::prepare(pos++, obj.getAge(), pPreparator);
+	///		}
+	///	
+	///		static void extract(std::size_t pos, Person& obj, const Person& defVal, AbstractExtractor::Ptr pExt)
+	///		{
+	///			// defVal is the default person we should use if we encunter NULL entries, so we take the individual fields
+	///			// as defaults. You can do more complex checking, ie return defVal if only one single entry of the fields is null etc...
+	///			poco_assert_dbg (!pExt.isNull());
+	///			std::string lastName;
+	///			std::string firstName;
+	///			int age = 0;
+	///			// the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
+	///			TypeHandler<std::string>::extract(pos++, lastName, defVal.getLastName(), pExt);
+	///			TypeHandler<std::string>::extract(pos++, firstName, defVal.getFirstName(), pExt);
+	///			TypeHandler<int>::extract(pos++, age, defVal.getAge(), pExt);
+	///			obj.setLastName(lastName);
+	///			obj.setFirstName(firstName);
+	///			obj.setAge(age);
+	///		}
+	///	};
+	///
+	/// Note that the TypeHandler template specialization must always be declared in the namespace Poco::Data.
+	/// Apart from that no further work is needed. One can now use Person with into and use clauses.
+{
+public:
+	static void bind(std::size_t pos, const T& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->bind(pos, obj, dir);
+	}
+
+	static std::size_t size()
+	{
+		return 1u;
+	}
+
+	static void extract(std::size_t pos, T& obj, const T& defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		if (!pExt->extract(pos, obj)) obj = defVal;
+	}
+
+	static void prepare(std::size_t pos, const T& obj, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		pPreparator->prepare(pos, obj);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+
+template <class T>
+class TypeHandler<std::deque<T> >: public AbstractTypeHandler
+	/// Specialization of type handler for std::deque.
+{
+public:
+	static void bind(std::size_t pos, const std::deque<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->bind(pos, obj, dir);
+	}
+
+	static std::size_t size()
+	{
+		return 1u;
+	}
+
+	static void extract(std::size_t pos, std::deque<T>& obj, const T& defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		if (!pExt->extract(pos, obj))
+			obj.assign(obj.size(), defVal);
+	}
+
+	static void prepare(std::size_t pos, const std::deque<T>& obj, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		pPreparator->prepare(pos, obj);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+
+template <class T>
+class TypeHandler<std::vector<T> >: public AbstractTypeHandler
+	/// Specialization of type handler for std::vector.
+{
+public:
+	static void bind(std::size_t pos, const std::vector<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->bind(pos, obj, dir);
+	}
+
+	static std::size_t size()
+	{
+		return 1u;
+	}
+
+	static void extract(std::size_t pos, std::vector<T>& obj, const T& defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		if (!pExt->extract(pos, obj))
+			obj.assign(obj.size(), defVal);
+	}
+
+	static void prepare(std::size_t pos, const std::vector<T>& obj, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		pPreparator->prepare(pos, obj);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+
+template <class T>
+class TypeHandler<std::list<T> >: public AbstractTypeHandler
+	/// Specialization of type handler for std::list.
+{
+public:
+	static void bind(std::size_t pos, const std::list<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		pBinder->bind(pos, obj, dir);
+	}
+
+	static std::size_t size()
+	{
+		return 1u;
+	}
+
+	static void extract(std::size_t pos, std::list<T>& obj, const T& defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		if (!pExt->extract(pos, obj))
+			obj.assign(obj.size(), defVal);
+	}
+
+	static void prepare(std::size_t pos, const std::list<T>& obj, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		pPreparator->prepare(pos, obj);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+template <typename T>
+class TypeHandler<Nullable<T> > 
+	/// Specialization of type handler for Nullable.
+{
+public:
+
+	static void bind(std::size_t pos, const Nullable<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) 
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		if (obj.isNull()) 
+		{
+			pBinder->bind(pos++, Poco::Data::Keywords::null, dir);
+		}
+		else 
+		{
+			pBinder->bind(pos++, obj.value(), dir);
+		}
+	}
+	
+	static void prepare(std::size_t pos, const Nullable<T>& obj, AbstractPreparator::Ptr pPreparator) 
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		if (obj.isNull()) 
+		{
+			pPreparator->prepare(pos++, Poco::Data::Keywords::null);
+		}
+		else 
+		{
+			pPreparator->prepare(pos++, obj.value());
+		}
+	}
+
+	static std::size_t size() 
+	{
+		return 1u;
+	}
+
+	static void extract(std::size_t pos, Nullable<T>& obj, const Nullable<T>& , AbstractExtractor::Ptr pExt) 
+	{
+		poco_assert_dbg (!pExt.isNull());
+		T val;
+	
+		if (pExt->extract(pos++, val)) 
+		{
+			obj = val;
+		}
+		else 
+		{
+			obj.clear();
+		}
+	}
+
+private:
+
+	TypeHandler();
+	~TypeHandler();
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+/// Poco::Tuple TypeHandler specializations
+
+// define this macro to nothing for smaller code size
+#define POCO_TUPLE_TYPE_HANDLER_INLINE inline
+
+
+template <typename TupleType, typename Type, int N>
+POCO_TUPLE_TYPE_HANDLER_INLINE
+void tupleBind(std::size_t& pos, TupleType tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+{
+	TypeHandler<Type>::bind(pos, tuple.template get<N>(), pBinder, dir);
+	pos += TypeHandler<Type>::size();
+}
+
+
+template <typename TupleType, typename Type, int N>
+POCO_TUPLE_TYPE_HANDLER_INLINE
+void tuplePrepare(std::size_t& pos, TupleType tuple, AbstractPreparator::Ptr pPreparator)
+{
+	TypeHandler<Type>::prepare(pos, tuple.template get<N>(), pPreparator);
+	pos += TypeHandler<Type>::size();
+}
+
+
+template <typename TupleType, typename DefValType, typename Type, int N>
+POCO_TUPLE_TYPE_HANDLER_INLINE
+void tupleExtract(std::size_t& pos, TupleType tuple, DefValType defVal, AbstractExtractor::Ptr pExt)
+{
+	Poco::Data::TypeHandler<Type>::extract(pos, tuple.template get<N>(),
+	defVal.template get<N>(), pExt);
+	pos += TypeHandler<Type>::size();
+}
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13, 
+	class T14, 
+	class T15, 
+	class T16, 
+	class T17, 
+	class T18, 
+	class T19>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T14, 14>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T15, 15>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T16, 16>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T17, 17>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T18, 18>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T19, 19>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T14, 14>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T15, 15>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T16, 16>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T17, 17>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T18, 18>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T19, 19>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size() +
+			TypeHandler<T14>::size() +
+			TypeHandler<T15>::size() +
+			TypeHandler<T16>::size() +
+			TypeHandler<T17>::size() +
+			TypeHandler<T18>::size() +
+			TypeHandler<T19>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T14, 14>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T15, 15>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T16, 16>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T17, 17>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T18, 18>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T19, 19>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13, 
+	class T14, 
+	class T15, 
+	class T16, 
+	class T17, 
+	class T18>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T14, 14>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T15, 15>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T16, 16>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T17, 17>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T18, 18>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T14, 14>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T15, 15>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T16, 16>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T17, 17>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T18, 18>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size() +
+			TypeHandler<T14>::size() +
+			TypeHandler<T15>::size() +
+			TypeHandler<T16>::size() +
+			TypeHandler<T17>::size() +
+			TypeHandler<T18>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T14, 14>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T15, 15>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T16, 16>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T17, 17>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T18, 18>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13, 
+	class T14, 
+	class T15, 
+	class T16, 
+	class T17>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T14, 14>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T15, 15>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T16, 16>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T17, 17>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T14, 14>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T15, 15>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T16, 16>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T17, 17>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size() +
+			TypeHandler<T14>::size() +
+			TypeHandler<T15>::size() +
+			TypeHandler<T16>::size() +
+			TypeHandler<T17>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T14, 14>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T15, 15>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T16, 16>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T17, 17>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13, 
+	class T14, 
+	class T15, 
+	class T16>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T14, 14>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T15, 15>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T16, 16>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T14, 14>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T15, 15>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T16, 16>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size() +
+			TypeHandler<T14>::size() +
+			TypeHandler<T15>::size() +
+			TypeHandler<T16>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T14, 14>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T15, 15>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T16, 16>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13, 
+	class T14, 
+	class T15>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T14, 14>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T15, 15>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T14, 14>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T15, 15>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size() +
+			TypeHandler<T14>::size() +
+			TypeHandler<T15>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T14, 14>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T15, 15>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13, 
+	class T14>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T14, 14>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T14, 14>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size() +
+			TypeHandler<T14>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T14, 14>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12, 
+	class T13>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T13, 13>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T13, 13>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size() +
+			TypeHandler<T13>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T13, 13>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11, 
+	class T12>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T12, 12>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T12, 12>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size() +
+			TypeHandler<T12>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T12, 12>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10, 
+	class T11>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T11, 11>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T11, 11>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size() +
+			TypeHandler<T11>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T11, 11>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, 
+	class T1, 
+	class T2, 
+	class T3, 
+	class T4, 
+	class T5, 
+	class T6, 
+	class T7, 
+	class T8, 
+	class T9, 
+	class T10>
+class TypeHandler<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T10, 10>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T10, 10>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size() +
+			TypeHandler<T10>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T10, 10>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T9, 9>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T9, 9>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size() +
+			TypeHandler<T9>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T9, 9>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T8, 8>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T8, 8>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size() +
+			TypeHandler<T8>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T8, 8>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, T7, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T7, 7>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T7, 7>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size() +
+			TypeHandler<T7>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T7, 7>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3, class T4, class T5, class T6>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, T6, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T6, 6>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T6, 6>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size() +
+			TypeHandler<T6>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T6, 6>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3, class T4, class T5>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, T4, T5, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, T5, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T5, 5>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T5, 5>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size() +
+			TypeHandler<T5>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T5, 5>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3, class T4>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, T4, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, T4, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T4, 4>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T4, 4>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size() +
+			TypeHandler<T4>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T4, 4>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2, class T3>
+class TypeHandler<Poco::Tuple<T0, T1, T2, T3, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, T3, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T3, 3>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T3, 3>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size() +
+			TypeHandler<T3>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T3, 3>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1, class T2>
+	class TypeHandler<Poco::Tuple<T0, T1, T2, NullTypeList> >
+{
+public:
+		typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, T2, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T2, 2>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T2, 2>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size() +
+			TypeHandler<T2>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T2, 2>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0, class T1>
+class TypeHandler<Poco::Tuple<T0, T1, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, T1, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+		tupleBind<TupleConstRef, T1, 1>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+		tuplePrepare<TupleConstRef, T1, 1>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size() +
+			TypeHandler<T1>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+		tupleExtract<TupleRef, TupleConstRef, T1, 1>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class T0>
+class TypeHandler<Poco::Tuple<T0, NullTypeList> >
+{
+public:
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, NullTypeList> >::CONSTREFTYPE TupleConstRef;
+	typedef typename Poco::TypeWrapper<Poco::Tuple<T0, NullTypeList> >::REFTYPE	  TupleRef;
+
+	static void bind(std::size_t pos, TupleConstRef tuple, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		poco_assert_dbg (!pBinder.isNull());
+		tupleBind<TupleConstRef, T0, 0>(pos, tuple, pBinder, dir);
+	}
+
+	static void prepare(std::size_t pos, TupleConstRef tuple, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		tuplePrepare<TupleConstRef, T0, 0>(pos, tuple, pPreparator);
+	}
+
+	static std::size_t size()
+	{
+		return TypeHandler<T0>::size();
+	}
+
+	static void extract(std::size_t pos, TupleRef tuple, TupleConstRef defVal, 
+		AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		tupleExtract<TupleRef, TupleConstRef, T0, 0>(pos, tuple, defVal, pExt);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator=(const TypeHandler&);
+};
+
+
+template <class K, class V>
+class TypeHandler<std::pair<K, V> >: public AbstractTypeHandler
+{
+public:
+	static void bind(std::size_t pos, const std::pair<K, V>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		TypeHandler<K>::bind(pos, obj.first, pBinder, dir);
+		pos += TypeHandler<K>::size();
+		TypeHandler<V>::bind(pos, obj.second, pBinder, dir);
+	}
+
+	static std::size_t size()
+	{
+		return static_cast<std::size_t>(TypeHandler<K>::size() + TypeHandler<V>::size());
+	}
+
+	static void extract(std::size_t pos, std::pair<K, V>& obj, const std::pair<K, V>& defVal, AbstractExtractor::Ptr pExt)
+	{
+		TypeHandler<K>::extract(pos, obj.first, defVal.first, pExt);
+		pos += TypeHandler<K>::size();
+		TypeHandler<V>::extract(pos, obj.second, defVal.second, pExt);
+	}
+
+	static void prepare(std::size_t pos, const std::pair<K, V>& obj, AbstractPreparator::Ptr pPreparator)
+	{
+		TypeHandler<K>::prepare(pos, obj.first, pPreparator);
+		pos += TypeHandler<K>::size();
+		TypeHandler<V>::prepare(pos, obj.second, pPreparator);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+
+template <class T>
+class TypeHandler<Poco::AutoPtr<T> >: public AbstractTypeHandler
+	/// Specialization of type handler for Poco::AutoPtr
+{
+public:
+	static void bind(std::size_t pos, const Poco::AutoPtr<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		// *obj will trigger a nullpointer exception if empty: this is on purpose
+		TypeHandler<T>::bind(pos, *obj, pBinder, dir); 
+	}
+
+	static std::size_t size()
+	{
+		return static_cast<std::size_t>(TypeHandler<T>::size());
+	}
+
+	static void extract(std::size_t pos, Poco::AutoPtr<T>& obj, const Poco::AutoPtr<T>& defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		
+		obj = Poco::AutoPtr<T>(new T());
+		if (defVal)
+			TypeHandler<T>::extract(pos, *obj, *defVal, pExt);
+		else
+			TypeHandler<T>::extract(pos, *obj, *obj, pExt);
+	}
+
+	static void prepare(std::size_t pos, const Poco::AutoPtr<T>&, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		TypeHandler<T>::prepare(pos, T(), pPreparator);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+
+
+template <class T>
+class TypeHandler<Poco::SharedPtr<T> >: public AbstractTypeHandler
+	/// Specialization of type handler for Poco::SharedPtr
+{
+public:
+	static void bind(std::size_t pos, const Poco::SharedPtr<T>& obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
+	{
+		// *obj will trigger a nullpointer exception if empty
+		TypeHandler<T>::bind(pos, *obj, pBinder, dir); 
+	}
+
+	static std::size_t size()
+	{
+		return static_cast<std::size_t>(TypeHandler<T>::size());
+	}
+
+	static void extract(std::size_t pos, Poco::SharedPtr<T>& obj, const Poco::SharedPtr<T>& defVal, AbstractExtractor::Ptr pExt)
+	{
+		poco_assert_dbg (!pExt.isNull());
+		
+		obj = Poco::SharedPtr<T>(new T());
+		if (defVal)
+			TypeHandler<T>::extract(pos, *obj, *defVal, pExt);
+		else
+			TypeHandler<T>::extract(pos, *obj, *obj, pExt);
+	}
+
+	static void prepare(std::size_t pos, const Poco::SharedPtr<T>&, AbstractPreparator::Ptr pPreparator)
+	{
+		poco_assert_dbg (!pPreparator.isNull());
+		TypeHandler<T>::prepare(pos, T(), pPreparator);
+	}
+
+private:
+	TypeHandler(const TypeHandler&);
+	TypeHandler& operator = (const TypeHandler&);
+};
+
+
+} } // namespace Poco::Data
+
+
+#endif // Data_TypeHandler_INCLUDED
diff --git a/Poco/DateTime.h b/Poco/DateTime.h
new file mode 100644
index 0000000..ab69894
--- /dev/null
+++ b/Poco/DateTime.h
@@ -0,0 +1,415 @@
+//
+// DateTime.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  DateTime
+//
+// Definition of the DateTime class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DateTime_INCLUDED
+#define Foundation_DateTime_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+
+
+class Foundation_API DateTime
+	/// This class represents an instant in time, expressed
+	/// in years, months, days, hours, minutes, seconds
+	/// and milliseconds based on the Gregorian calendar.
+	/// The class is mainly useful for conversions between
+	/// UTC, Julian day and Gregorian calendar dates.
+	///
+	/// The date and time stored in a DateTime is always in UTC
+	/// (Coordinated Universal Time) and thus independent of the 
+	/// timezone in effect on the system.
+	///
+	/// Conversion calculations are based on algorithms
+	/// collected and described by Peter Baum at
+	/// http://vsg.cape.com/~pbaum/date/date0.htm
+	///
+	/// Internally, this class stores a date/time in two
+	/// forms (UTC and broken down) for performance reasons. Only use 
+	/// this class for conversions between date/time representations.
+	/// Use the Timestamp class for everything else.
+	///
+	/// Notes:
+	///   * Zero is a valid year (in accordance with ISO 8601 and astronomical year numbering)
+	///   * Year zero (0) is a leap year
+	///   * Negative years (years preceding 1 BC) are not supported
+	///
+	/// For more information, please see:
+	///   * http://en.wikipedia.org/wiki/Gregorian_Calendar
+	///   * http://en.wikipedia.org/wiki/Julian_day
+	///   * http://en.wikipedia.org/wiki/UTC
+	///   * http://en.wikipedia.org/wiki/ISO_8601
+{
+public:
+	enum Months
+		/// Symbolic names for month numbers (1 to 12).
+	{
+		JANUARY = 1,
+		FEBRUARY,
+		MARCH,
+		APRIL,
+		MAY,
+		JUNE,
+		JULY,
+		AUGUST,
+		SEPTEMBER,
+		OCTOBER,
+		NOVEMBER,
+		DECEMBER
+	};
+	
+	enum DaysOfWeek
+		/// Symbolic names for week day numbers (0 to 6).
+	{
+		SUNDAY = 0,
+		MONDAY,
+		TUESDAY,
+		WEDNESDAY,
+		THURSDAY,
+		FRIDAY,
+		SATURDAY
+	};
+		
+	DateTime();
+		/// Creates a DateTime for the current date and time.
+
+	DateTime(const Timestamp& timestamp);
+		/// Creates a DateTime for the date and time given in
+		/// a Timestamp.
+		
+	DateTime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0);
+		/// Creates a DateTime for the given Gregorian date and time.
+		///   * year is from 0 to 9999.
+		///   * month is from 1 to 12.
+		///   * day is from 1 to 31.
+		///   * hour is from 0 to 23.
+		///   * minute is from 0 to 59.
+		///   * second is from 0 to 60 (allowing leap seconds).
+		///   * millisecond is from 0 to 999.
+		///   * microsecond is from 0 to 999.
+
+	DateTime(double julianDay);
+		/// Creates a DateTime for the given Julian day.
+
+	DateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff);
+		/// Creates a DateTime from an UtcTimeVal and a TimeDiff.
+		///
+		/// Mainly used internally by DateTime and friends.
+
+	DateTime(const DateTime& dateTime);
+		/// Copy constructor. Creates the DateTime from another one.
+
+	~DateTime();
+		/// Destroys the DateTime.
+
+	DateTime& operator = (const DateTime& dateTime);
+		/// Assigns another DateTime.
+		
+	DateTime& operator = (const Timestamp& timestamp);
+		/// Assigns a Timestamp.
+
+	DateTime& operator = (double julianDay);
+		/// Assigns a Julian day.
+
+	DateTime& assign(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microseconds = 0);
+		/// Assigns a Gregorian date and time.
+		///   * year is from 0 to 9999.
+		///   * month is from 1 to 12.
+		///   * day is from 1 to 31.
+		///   * hour is from 0 to 23.
+		///   * minute is from 0 to 59.
+		///   * second is from 0 to 60 (allowing leap seconds).
+		///   * millisecond is from 0 to 999.
+		///   * microsecond is from 0 to 999.
+
+	void swap(DateTime& dateTime);
+		/// Swaps the DateTime with another one.
+
+	int year() const;
+		/// Returns the year.
+		
+	int month() const;
+		/// Returns the month (1 to 12).
+	
+	int week(int firstDayOfWeek = MONDAY) const;
+		/// Returns the week number within the year.
+		/// FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1).
+		/// The returned week number will be from 0 to 53. Week number 1 is the week 
+		/// containing January 4. This is in accordance to ISO 8601.
+		/// 
+		/// The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started
+		/// on a Saturday, week 1 will be the week starting on Monday, January 3.
+		/// January 1 and 2 will fall within week 0 (or the last week of the previous year).
+		///
+		/// For 2007, which starts on a Monday, week 1 will be the week startung on Monday, January 1.
+		/// There will be no week 0 in 2007.
+	
+	int day() const;
+		/// Returns the day witin the month (1 to 31).
+		
+	int dayOfWeek() const;
+		/// Returns the weekday (0 to 6, where
+		/// 0 = Sunday, 1 = Monday, ..., 6 = Saturday).
+	
+	int dayOfYear() const;
+		/// Returns the number of the day in the year.
+		/// January 1 is 1, February 1 is 32, etc.
+	
+	int hour() const;
+		/// Returns the hour (0 to 23).
+		
+	int hourAMPM() const;
+		/// Returns the hour (0 to 12).
+	
+	bool isAM() const;
+		/// Returns true if hour < 12;
+
+	bool isPM() const;
+		/// Returns true if hour >= 12.
+		
+	int minute() const;
+		/// Returns the minute (0 to 59).
+		
+	int second() const;
+		/// Returns the second (0 to 59).
+		
+	int millisecond() const;
+		/// Returns the millisecond (0 to 999)
+	
+	int microsecond() const;
+		/// Returns the microsecond (0 to 999)
+	
+	double julianDay() const;
+		/// Returns the julian day for the date and time.
+		
+	Timestamp timestamp() const;
+		/// Returns the date and time expressed as a Timestamp.
+
+	Timestamp::UtcTimeVal utcTime() const;
+		/// Returns the date and time expressed in UTC-based
+		/// time. UTC base time is midnight, October 15, 1582.
+		/// Resolution is 100 nanoseconds.
+		
+	bool operator == (const DateTime& dateTime) const;	
+	bool operator != (const DateTime& dateTime) const;	
+	bool operator <  (const DateTime& dateTime) const;	
+	bool operator <= (const DateTime& dateTime) const;	
+	bool operator >  (const DateTime& dateTime) const;	
+	bool operator >= (const DateTime& dateTime) const;	
+
+	DateTime  operator +  (const Timespan& span) const;
+	DateTime  operator -  (const Timespan& span) const;
+	Timespan  operator -  (const DateTime& dateTime) const;
+	DateTime& operator += (const Timespan& span);
+	DateTime& operator -= (const Timespan& span);
+	
+	void makeUTC(int tzd);
+		/// Converts a local time into UTC, by applying the given time zone differential.
+		
+	void makeLocal(int tzd);
+		/// Converts a UTC time into a local time, by applying the given time zone differential.
+	
+	static bool isLeapYear(int year);
+		/// Returns true if the given year is a leap year;
+		/// false otherwise.
+		
+	static int daysOfMonth(int year, int month);
+		/// Returns the number of days in the given month
+		/// and year. Month is from 1 to 12.
+		
+	static bool isValid(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0);
+		/// Checks if the given date and time is valid
+		/// (all arguments are within a proper range).
+		///
+		/// Returns true if all arguments are valid, false otherwise.
+		
+protected:	
+	static double toJulianDay(Timestamp::UtcTimeVal utcTime);
+		/// Computes the Julian day for an UTC time.
+	
+	static double toJulianDay(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0);
+		/// Computes the Julian day for a gregorian calendar date and time.
+		/// See <http://vsg.cape.com/~pbaum/date/jdimp.htm>, section 2.3.1 for the algorithm.
+	
+	static Timestamp::UtcTimeVal toUtcTime(double julianDay);
+		/// Computes the UTC time for a Julian day.
+		
+	void computeGregorian(double julianDay);
+		/// Computes the Gregorian date for the given Julian day.
+		/// See <http://vsg.cape.com/~pbaum/date/injdimp.htm>, section 3.3.1 for the algorithm.
+
+	void computeDaytime();
+		/// Extracts the daytime (hours, minutes, seconds, etc.) from the stored utcTime.
+
+private:
+	void checkLimit(short& lower, short& higher, short limit);
+	void normalize();
+		///utility functions used to correct the overflow in computeGregorian
+
+	Timestamp::UtcTimeVal _utcTime;
+	short  _year;
+	short  _month;
+	short  _day;
+	short  _hour;
+	short  _minute;
+	short  _second;
+	short  _millisecond;
+	short  _microsecond;
+};
+
+
+//
+// inlines
+//
+inline Timestamp DateTime::timestamp() const
+{
+	return Timestamp::fromUtcTime(_utcTime);
+}
+
+
+inline Timestamp::UtcTimeVal DateTime::utcTime() const
+{
+	return _utcTime;
+}
+
+
+inline int DateTime::year() const
+{
+	return _year;
+}
+
+	
+inline int DateTime::month() const
+{
+	return _month;
+}
+
+	
+inline int DateTime::day() const
+{
+	return _day;
+}
+
+	
+inline int DateTime::hour() const
+{
+	return _hour;
+}
+
+
+inline int DateTime::hourAMPM() const
+{
+	if (_hour < 1)
+		return 12;
+	else if (_hour > 12)
+		return _hour - 12;
+	else
+		return _hour;
+}
+
+
+inline bool DateTime::isAM() const
+{
+	return _hour < 12;
+}
+
+
+inline bool DateTime::isPM() const
+{
+	return _hour >= 12;
+}
+
+	
+inline int DateTime::minute() const
+{
+	return _minute;
+}
+
+	
+inline int DateTime::second() const
+{
+	return _second;
+}
+
+	
+inline int DateTime::millisecond() const
+{
+	return _millisecond;
+}
+
+
+inline int DateTime::microsecond() const
+{
+	return _microsecond;
+}
+
+
+inline bool DateTime::operator == (const DateTime& dateTime) const
+{
+	return _utcTime == dateTime._utcTime;
+}
+
+
+inline bool DateTime::operator != (const DateTime& dateTime) const	
+{
+	return _utcTime != dateTime._utcTime;
+}
+
+
+inline bool DateTime::operator <  (const DateTime& dateTime) const	
+{
+	return _utcTime < dateTime._utcTime;
+}
+
+
+inline bool DateTime::operator <= (const DateTime& dateTime) const
+{
+	return _utcTime <= dateTime._utcTime;
+}
+
+
+inline bool DateTime::operator >  (const DateTime& dateTime) const
+{
+	return _utcTime > dateTime._utcTime;
+}
+
+
+inline bool DateTime::operator >= (const DateTime& dateTime) const	
+{
+	return _utcTime >= dateTime._utcTime;
+}
+
+
+inline bool DateTime::isLeapYear(int year)
+{
+	return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
+}
+
+
+inline void swap(DateTime& d1, DateTime& d2)
+{
+	d1.swap(d2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DateTime_INCLUDED
diff --git a/Poco/DateTimeFormat.h b/Poco/DateTimeFormat.h
new file mode 100644
index 0000000..8f222d0
--- /dev/null
+++ b/Poco/DateTimeFormat.h
@@ -0,0 +1,109 @@
+//
+// DateTimeFormat.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  DateTimeFormat
+//
+// Definition of the DateTimeFormat class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DateTimeFormat_INCLUDED
+#define Foundation_DateTimeFormat_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API DateTimeFormat
+	/// Definition of date/time formats and various
+	/// constants used by DateTimeFormatter and DateTimeParser.
+{
+public:
+	// predefined date formats
+	static const std::string ISO8601_FORMAT;
+		/// The date/time format defined in the ISO 8601 standard.
+		///
+		/// Examples: 
+		///   2005-01-01T12:00:00+01:00
+		///   2005-01-01T11:00:00Z
+
+	static const std::string ISO8601_FRAC_FORMAT;
+		/// The date/time format defined in the ISO 8601 standard,
+		/// with fractional seconds.
+		///
+		/// Examples: 
+		///   2005-01-01T12:00:00.000000+01:00
+		///   2005-01-01T11:00:00.000000Z
+	
+	static const std::string RFC822_FORMAT;
+		/// The date/time format defined in RFC 822 (obsoleted by RFC 1123).
+		///
+		/// Examples: 
+		///   Sat, 1 Jan 05 12:00:00 +0100
+		///   Sat, 1 Jan 05 11:00:00 GMT
+
+	static const std::string RFC1123_FORMAT;
+		/// The date/time format defined in RFC 1123 (obsoletes RFC 822).
+		///
+		/// Examples: 
+		///   Sat, 1 Jan 2005 12:00:00 +0100
+		///   Sat, 1 Jan 2005 11:00:00 GMT
+
+	static const std::string HTTP_FORMAT;
+		/// The date/time format defined in the HTTP specification (RFC 2616),
+		/// which is basically a variant of RFC 1036 with a zero-padded day field.
+		///
+		/// Examples: 
+		///   Sat, 01 Jan 2005 12:00:00 +0100
+		///   Sat, 01 Jan 2005 11:00:00 GMT
+
+	static const std::string RFC850_FORMAT;
+		/// The date/time format defined in RFC 850 (obsoleted by RFC 1036).
+		///
+		/// Examples: 
+		///   Saturday, 1-Jan-05 12:00:00 +0100
+		///   Saturday, 1-Jan-05 11:00:00 GMT
+
+	static const std::string RFC1036_FORMAT;
+		/// The date/time format defined in RFC 1036 (obsoletes RFC 850).
+		///
+		/// Examples: 
+		///   Saturday, 1 Jan 05 12:00:00 +0100
+		///   Saturday, 1 Jan 05 11:00:00 GMT
+
+	static const std::string ASCTIME_FORMAT;
+		/// The date/time format produced by the ANSI C asctime() function.
+		///
+		/// Example: 
+		///   Sat Jan  1 12:00:00 2005
+
+	static const std::string SORTABLE_FORMAT;
+		/// A simple, sortable date/time format.
+		///
+		/// Example:
+		///   2005-01-01 12:00:00
+
+
+	// names used by formatter and parser
+	static const std::string WEEKDAY_NAMES[7];
+		/// English names of week days (Sunday, Monday, Tuesday, ...).
+		
+	static const std::string MONTH_NAMES[12];
+		/// English names of months (January, February, ...).	
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DateTimeFormat_INCLUDED
diff --git a/Poco/DateTimeFormatter.h b/Poco/DateTimeFormatter.h
new file mode 100644
index 0000000..3d6e5ed
--- /dev/null
+++ b/Poco/DateTimeFormatter.h
@@ -0,0 +1,215 @@
+//
+// DateTimeFormatter.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  DateTimeFormatter
+//
+// Definition of the DateTimeFormatter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DateTimeFormatter_INCLUDED
+#define Foundation_DateTimeFormatter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DateTime.h"
+#include "Poco/LocalDateTime.h"
+
+
+namespace Poco {
+
+
+class Timestamp;
+class Timespan;
+
+
+class Foundation_API DateTimeFormatter
+	/// This class converts dates and times into strings, supporting a  
+	/// variety of standard and custom formats.
+	///
+	/// There are two kind of static member functions:
+	///    * format* functions return a std::string containing
+	///      the formatted value.
+	///    * append* functions append the formatted value to
+	///      an existing string.
+{
+public:
+	enum
+	{
+		UTC = 0xFFFF /// Special value for timeZoneDifferential denoting UTC. 
+	};
+
+	static std::string format(const Timestamp& timestamp, const std::string& fmt, int timeZoneDifferential = UTC);
+		/// Formats the given timestamp according to the given format.
+		/// The format string is used as a template to format the date and
+		/// is copied character by character except for the following special characters,
+		/// which are replaced by the corresponding value.
+		///
+		///   * %w - abbreviated weekday (Mon, Tue, ...)
+		///   * %W - full weekday (Monday, Tuesday, ...)
+		///   * %b - abbreviated month (Jan, Feb, ...)
+		///   * %B - full month (January, February, ...)
+		///   * %d - zero-padded day of month (01 .. 31)
+		///   * %e - day of month (1 .. 31)
+		///   * %f - space-padded day of month ( 1 .. 31)
+		///   * %m - zero-padded month (01 .. 12)
+		///   * %n - month (1 .. 12)
+		///   * %o - space-padded month ( 1 .. 12)
+		///   * %y - year without century (70)
+		///   * %Y - year with century (1970)
+		///   * %H - hour (00 .. 23)
+		///   * %h - hour (00 .. 12)
+		///   * %a - am/pm
+		///   * %A - AM/PM
+		///   * %M - minute (00 .. 59)
+		///   * %S - second (00 .. 59)
+		///   * %s - seconds and microseconds (equivalent to %S.%F)
+		///   * %i - millisecond (000 .. 999)
+		///   * %c - centisecond (0 .. 9)
+		///   * %F - fractional seconds/microseconds (000000 - 999999)
+		///   * %z - time zone differential in ISO 8601 format (Z or +NN.NN)
+		///   * %Z - time zone differential in RFC format (GMT or +NNNN)
+		///   * %% - percent sign
+		///
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+
+	static std::string format(const DateTime& dateTime, const std::string& fmt, int timeZoneDifferential = UTC);
+		/// Formats the given date and time according to the given format.
+		/// See format(const Timestamp&, const std::string&, int) for more information.
+
+	static std::string format(const LocalDateTime& dateTime, const std::string& fmt);
+		/// Formats the given local date and time according to the given format.
+		/// See format(const Timestamp&, const std::string&, int) for more information.
+
+	static std::string format(const Timespan& timespan, const std::string& fmt = "%dd %H:%M:%S.%i");
+		/// Formats the given timespan according to the given format.
+		/// The format string is used as a template to format the date and
+		/// is copied character by character except for the following special characters,
+		/// which are replaced by the corresponding value.
+		///
+		///   * %d - days
+		///   * %H - hours	 (00 .. 23)
+		///   * %h - total hours (0 .. n)
+		///   * %M - minutes (00 .. 59)
+		///   * %m - total minutes (0 .. n)
+		///   * %S - seconds (00 .. 59)
+		///   * %s - total seconds (0 .. n)
+		///   * %i - milliseconds (000 .. 999)
+		///   * %c - centisecond (0 .. 9)
+		///   * %F - fractional seconds/microseconds (000000 - 999999)
+		///   * %% - percent sign
+
+	static void append(std::string& str, const Timestamp& timestamp, const std::string& fmt, int timeZoneDifferential = UTC);
+		/// Formats the given timestamp according to the given format and appends it to str.
+		///
+		/// See format() for documentation of the formatting string.
+
+	static void append(std::string& str, const DateTime& dateTime, const std::string& fmt, int timeZoneDifferential = UTC);
+		/// Formats the given date and time according to the given format and appends it to str.
+		///
+		/// See format() for documentation of the formatting string.
+
+	static void append(std::string& str, const LocalDateTime& dateTime, const std::string& fmt);
+		/// Formats the given local date and time according to the given format and appends it to str.
+		///
+		/// See format() for documentation of the formatting string.
+
+	static void append(std::string& str, const Timespan& timespan, const std::string& fmt = "%dd %H:%M:%S.%i");
+		/// Formats the given timespan according to the given format and appends it to str.
+		///
+		/// See format() for documentation of the formatting string.
+
+	static std::string tzdISO(int timeZoneDifferential);
+		/// Formats the given timezone differential in ISO format.
+		/// If timeZoneDifferential is UTC, "Z" is returned,
+		/// otherwise, +HH.MM (or -HH.MM) is returned.
+		
+	static std::string tzdRFC(int timeZoneDifferential);
+		/// Formats the given timezone differential in RFC format.
+		/// If timeZoneDifferential is UTC, "GMT" is returned,
+		/// otherwise ++HHMM (or -HHMM) is returned.
+
+	static void tzdISO(std::string& str, int timeZoneDifferential);
+		/// Formats the given timezone differential in ISO format
+		/// and appends it to the given string.
+		/// If timeZoneDifferential is UTC, "Z" is returned,
+		/// otherwise, +HH.MM (or -HH.MM) is returned.
+		
+	static void tzdRFC(std::string& str, int timeZoneDifferential);
+		/// Formats the given timezone differential in RFC format
+		/// and appends it to the given string.
+		/// If timeZoneDifferential is UTC, "GMT" is returned,
+		/// otherwise ++HHMM (or -HHMM) is returned.
+};
+
+
+//
+// inlines
+//
+inline std::string DateTimeFormatter::format(const Timestamp& timestamp, const std::string& fmt, int timeZoneDifferential)
+{
+	DateTime dateTime(timestamp);
+	return format(dateTime, fmt, timeZoneDifferential);
+}
+
+
+inline std::string DateTimeFormatter::format(const DateTime& dateTime, const std::string& fmt, int timeZoneDifferential)
+{
+	std::string result;
+	result.reserve(64);
+	append(result, dateTime, fmt, timeZoneDifferential);
+	return result;
+}
+
+
+inline std::string DateTimeFormatter::format(const LocalDateTime& dateTime, const std::string& fmt)
+{
+	return format(dateTime._dateTime, fmt, dateTime._tzd);
+}
+
+
+inline std::string DateTimeFormatter::format(const Timespan& timespan, const std::string& fmt)
+{
+	std::string result;
+	result.reserve(32);
+	append(result, timespan, fmt);
+	return result;
+}
+
+
+inline void DateTimeFormatter::append(std::string& str, const Timestamp& timestamp, const std::string& fmt, int timeZoneDifferential)
+{
+	DateTime dateTime(timestamp);
+	append(str, dateTime, fmt, timeZoneDifferential);
+}
+
+
+inline std::string DateTimeFormatter::tzdISO(int timeZoneDifferential)
+{
+	std::string result;
+	result.reserve(8);
+	tzdISO(result, timeZoneDifferential);
+	return result;
+}
+
+
+inline std::string DateTimeFormatter::tzdRFC(int timeZoneDifferential)
+{
+	std::string result;
+	result.reserve(8);
+	tzdRFC(result, timeZoneDifferential);
+	return result;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DateTimeFormatter_INCLUDED
diff --git a/Poco/DateTimeParser.h b/Poco/DateTimeParser.h
new file mode 100644
index 0000000..28ebbe7
--- /dev/null
+++ b/Poco/DateTimeParser.h
@@ -0,0 +1,116 @@
+//
+// DateTimeParser.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  DateTimeParser
+//
+// Definition of the DateTimeParser class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DateTimeParser_INCLUDED
+#define Foundation_DateTimeParser_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DateTime.h"
+
+
+namespace Poco {
+
+
+class Foundation_API DateTimeParser
+	/// This class provides a method for parsing dates and times
+	/// from strings. All parsing methods do their best to
+	/// parse a meaningful result, even from malformed input
+	/// strings.
+	///
+	/// The returned DateTime will always contain a time in the same
+	/// timezone as the time in the string. Call DateTime::makeUTC()
+	/// with the timeZoneDifferential returned by parse() to convert
+	/// the DateTime to UTC.
+	///
+	/// Note: When parsing a time in 12-hour (AM/PM) format, the hour
+	/// (%h) must be parsed before the AM/PM designator (%a, %A),
+	/// otherwise the AM/PM designator will be ignored.
+	///
+	/// See the DateTimeFormatter class for a list of supported format specifiers.
+	/// In addition to the format specifiers supported by DateTimeFormatter, an
+	/// additional specifier is supported: %r will parse a year given by either
+	/// two or four digits. Years 69-00 are interpreted in the 20th century
+	/// (1969-2000), years 01-68 in the 21th century (2001-2068).
+	///
+	/// Note that in the current implementation all characters other than format specifiers in 
+	/// the format string are ignored/not matched against the date/time string. This may
+	/// lead to non-error results even with nonsense input strings.
+	/// This may change in a future version to a more strict behavior.
+	/// If more strict format validation of date/time strings is required, a regular
+	/// expression could be used for initial validation, before passing the string
+	/// to DateTimeParser.
+{
+public:
+	static void parse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential);
+		/// Parses a date and time in the given format from the given string.
+		/// Throws a SyntaxException if the string cannot be successfully parsed.
+		/// Please see DateTimeFormatter::format() for a description of the format string.
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+
+	static DateTime parse(const std::string& fmt, const std::string& str, int& timeZoneDifferential);
+		/// Parses a date and time in the given format from the given string.
+		/// Throws a SyntaxException if the string cannot be successfully parsed.
+		/// Please see DateTimeFormatter::format() for a description of the format string.
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+		
+	static bool tryParse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential);
+		/// Parses a date and time in the given format from the given string.
+		/// Returns true if the string has been successfully parsed, false otherwise.
+		/// Please see DateTimeFormatter::format() for a description of the format string.
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+		
+	static void parse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential);
+		/// Parses a date and time from the given dateTime string. Before parsing, the method
+		/// examines the dateTime string for a known date/time format.
+		/// Throws a SyntaxException if the string cannot be successfully parsed.
+		/// Please see DateTimeFormatter::format() for a description of the format string.
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+
+	static DateTime parse(const std::string& str, int& timeZoneDifferential);
+		/// Parses a date and time from the given dateTime string. Before parsing, the method
+		/// examines the dateTime string for a known date/time format.
+		/// Please see DateTimeFormatter::format() for a description of the format string.
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+		
+	static bool tryParse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential);
+		/// Parses a date and time from the given dateTime string. Before parsing, the method
+		/// examines the dateTime string for a known date/time format.
+		/// Please see DateTimeFormatter::format() for a description of the format string.
+		/// Class DateTimeFormat defines format strings for various standard date/time formats.
+
+	static int parseMonth(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Tries to interpret the given range as a month name. The range must be at least
+		/// three characters long. 
+		/// Returns the month number (1 .. 12) if the month name is valid. Otherwise throws
+		/// a SyntaxException.
+
+	static int parseDayOfWeek(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Tries to interpret the given range as a weekday name. The range must be at least
+		/// three characters long. 
+		/// Returns the weekday number (0 .. 6, where 0 = Synday, 1 = Monday, etc.) if the 
+		/// weekday name is valid. Otherwise throws a SyntaxException.
+		
+protected:
+	static int parseTZD(std::string::const_iterator& it, const std::string::const_iterator& end);
+	static int parseAMPM(std::string::const_iterator& it, const std::string::const_iterator& end, int hour);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DateTimeParser_INCLUDED
diff --git a/Poco/Debugger.h b/Poco/Debugger.h
new file mode 100644
index 0000000..f1de9fc
--- /dev/null
+++ b/Poco/Debugger.h
@@ -0,0 +1,70 @@
+//
+// Debugger.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Debugger
+//
+// Definition of the Debugger class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Debugger_INCLUDED
+#define Foundation_Debugger_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Debugger
+	/// The Debugger class provides an interface to the debugger.
+	/// The presence of a debugger can be checked for,
+	/// messages can be written to the debugger's log window
+	/// and a break into the debugger can be enforced.
+	/// The methods only work if the program is compiled
+	/// in debug mode (the macro _DEBUG is defined).
+{
+public:
+	static bool isAvailable();
+		/// Returns true if a debugger is available, false otherwise.
+		/// On Windows, this function uses the IsDebuggerPresent()
+		/// function.
+		/// On Unix, this function returns true if the environment
+		/// variable POCO_ENABLE_DEBUGGER is set.
+
+	static void message(const std::string& msg);
+		/// Writes a message to the debugger log, if available, otherwise to
+		/// standard error output.
+
+	static void message(const std::string& msg, const char* file, int line);
+		/// Writes a message to the debugger log, if available, otherwise to
+		/// standard error output.
+
+	static void enter();
+		/// Breaks into the debugger, if it is available.
+		/// On Windows, this is done using the DebugBreak() function.
+		/// On Unix, the SIGINT signal is raised.
+
+	static void enter(const std::string& msg);
+		/// Writes a debug message to the debugger log and breaks into it.
+
+	static void enter(const std::string& msg, const char* file, int line);
+		/// Writes a debug message to the debugger log and breaks into it.
+
+	static void enter(const char* file, int line);
+		/// Writes a debug message to the debugger log and breaks into it.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Debugger_INCLUDED
diff --git a/Poco/DefaultStrategy.h b/Poco/DefaultStrategy.h
new file mode 100644
index 0000000..6a09511
--- /dev/null
+++ b/Poco/DefaultStrategy.h
@@ -0,0 +1,226 @@
+//
+// DefaultStrategy.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  DefaultStrategy
+//
+// Implementation of the DefaultStrategy template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DefaultStrategy_INCLUDED
+#define Foundation_DefaultStrategy_INCLUDED
+
+
+#include "Poco/NotificationStrategy.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+template <class TArgs, class TDelegate> 
+class DefaultStrategy: public NotificationStrategy<TArgs, TDelegate>
+	/// Default notification strategy.
+	///
+	/// Internally, a std::vector<> is used to store
+	/// delegate objects. Delegates are invoked in the
+	/// order in which they have been registered.
+{
+public:
+	typedef TDelegate*                   DelegateHandle;
+	typedef SharedPtr<TDelegate>         DelegatePtr;
+	typedef std::vector<DelegatePtr>     Delegates;
+	typedef typename Delegates::iterator Iterator;
+
+public:
+	DefaultStrategy()
+	{
+	}
+
+	DefaultStrategy(const DefaultStrategy& s):
+		_delegates(s._delegates)
+	{
+	}
+
+	~DefaultStrategy()
+	{
+	}
+
+	void notify(const void* sender, TArgs& arguments)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->notify(sender, arguments);
+		}
+	}
+
+	DelegateHandle add(const TDelegate& delegate)
+	{
+		DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
+		_delegates.push_back(pDelegate);
+		return pDelegate.get();
+	}
+
+	void remove(const TDelegate& delegate)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (delegate.equals(**it))
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+	
+	void remove(DelegateHandle delegateHandle)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (*it == delegateHandle)
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	DefaultStrategy& operator = (const DefaultStrategy& s)
+	{
+		if (this != &s)
+		{
+			_delegates = s._delegates;
+		}
+		return *this;
+	}
+
+	void clear()
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->disable();
+		}
+		_delegates.clear();
+	}
+
+	bool empty() const
+	{
+		return _delegates.empty();
+	}
+
+protected:
+	Delegates _delegates;
+};
+
+
+template <class TDelegate>
+class DefaultStrategy<void,TDelegate>: public NotificationStrategy<void, TDelegate>
+	/// Default notification strategy.
+	///
+	/// Internally, a std::vector<> is used to store
+	/// delegate objects. Delegates are invoked in the
+	/// order in which they have been registered.
+{
+public:
+	typedef TDelegate*                   DelegateHandle;
+	typedef SharedPtr<TDelegate>         DelegatePtr;
+	typedef std::vector<DelegatePtr>     Delegates;
+	typedef typename Delegates::iterator Iterator;
+
+public:
+	DefaultStrategy()
+	{
+	}
+
+	DefaultStrategy(const DefaultStrategy& s):
+		_delegates(s._delegates)
+	{
+	}
+
+	~DefaultStrategy()
+	{
+	}
+
+	void notify(const void* sender)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->notify(sender);
+		}
+	}
+
+	DelegateHandle add(const TDelegate& delegate)
+	{
+		DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
+		_delegates.push_back(pDelegate);
+		return pDelegate.get();
+	}
+
+	void remove(const TDelegate& delegate)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (delegate.equals(**it))
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	void remove(DelegateHandle delegateHandle)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (*it == delegateHandle)
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	DefaultStrategy& operator = (const DefaultStrategy& s)
+	{
+		if (this != &s)
+		{
+			_delegates = s._delegates;
+		}
+		return *this;
+	}
+
+	void clear()
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->disable();
+		}
+		_delegates.clear();
+	}
+
+	bool empty() const
+	{
+		return _delegates.empty();
+	}
+
+protected:
+	Delegates _delegates;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DefaultStrategy_INCLUDED
diff --git a/Poco/DeflatingStream.h b/Poco/DeflatingStream.h
new file mode 100644
index 0000000..8af593e
--- /dev/null
+++ b/Poco/DeflatingStream.h
@@ -0,0 +1,201 @@
+//
+// DeflatingStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  ZLibStream
+//
+// Definition of the DeflatingStream class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DeflatingStream_INCLUDED
+#define Foundation_DeflatingStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+#if defined(POCO_UNBUNDLED)
+#include <zlib.h>
+#else
+#include "Poco/zlib.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API DeflatingStreamBuf: public BufferedStreamBuf
+	/// This is the streambuf class used by DeflatingInputStream and DeflatingOutputStream.
+	/// The actual work is delegated to zlib (see http://zlib.net).
+	/// Both zlib (deflate) streams and gzip streams are supported.
+	/// Output streams should always call close() to ensure
+	/// proper completion of compression.
+	/// A compression level (0 to 9) can be specified in the constructor.
+{
+public:
+	enum StreamType
+	{
+		STREAM_ZLIB, /// Create a zlib header, use Adler-32 checksum.
+		STREAM_GZIP  /// Create a gzip header, use CRC-32 checksum.
+	};
+
+	DeflatingStreamBuf(std::istream& istr, StreamType type, int level);
+		/// Creates a DeflatingStreamBuf for compressing data read
+		/// from the given input stream.
+
+	DeflatingStreamBuf(std::istream& istr, int windowBits, int level);
+		/// Creates a DeflatingStreamBuf for compressing data read
+		/// from the given input stream.
+		///
+		/// Please refer to the zlib documentation of deflateInit2() for a description
+		/// of the windowBits parameter.
+		
+	DeflatingStreamBuf(std::ostream& ostr, StreamType type, int level);
+		/// Creates a DeflatingStreamBuf for compressing data passed
+		/// through and forwarding it to the given output stream.
+
+	DeflatingStreamBuf(std::ostream& ostr, int windowBits, int level);
+		/// Creates a DeflatingStreamBuf for compressing data passed
+		/// through and forwarding it to the given output stream.
+		///
+		/// Please refer to the zlib documentation of deflateInit2() for a description
+		/// of the windowBits parameter.
+		
+	~DeflatingStreamBuf();
+		/// Destroys the DeflatingStreamBuf.
+		
+	int close();
+		/// Finishes up the stream. 
+		///
+		/// Must be called when deflating to an output stream.
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+	virtual int sync();
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE  = 1024,
+		DEFLATE_BUFFER_SIZE = 32768
+	};
+
+	std::istream* _pIstr;
+	std::ostream* _pOstr;
+	char*    _buffer;
+	z_stream _zstr;
+	bool     _eof;
+};
+
+
+class Foundation_API DeflatingIOS: public virtual std::ios
+	/// The base class for DeflatingOutputStream and DeflatingInputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	DeflatingIOS(std::ostream& ostr, DeflatingStreamBuf::StreamType type = DeflatingStreamBuf::STREAM_ZLIB, int level = Z_DEFAULT_COMPRESSION);
+		/// Creates a DeflatingIOS for compressing data passed
+		/// through and forwarding it to the given output stream.
+
+	DeflatingIOS(std::ostream& ostr, int windowBits, int level);
+		/// Creates a DeflatingIOS for compressing data passed
+		/// through and forwarding it to the given output stream.
+		///
+		/// Please refer to the zlib documentation of deflateInit2() for a description
+		/// of the windowBits parameter.
+
+	DeflatingIOS(std::istream& istr, DeflatingStreamBuf::StreamType type = DeflatingStreamBuf::STREAM_ZLIB, int level = Z_DEFAULT_COMPRESSION);
+		/// Creates a DeflatingIOS for compressing data read
+		/// from the given input stream.
+
+	DeflatingIOS(std::istream& istr, int windowBits, int level);
+		/// Creates a DeflatingIOS for compressing data read
+		/// from the given input stream.
+		///
+		/// Please refer to the zlib documentation of deflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~DeflatingIOS();
+		/// Destroys the DeflatingIOS.
+		
+	DeflatingStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying stream buffer.
+		
+protected:
+	DeflatingStreamBuf _buf;
+};
+
+
+class Foundation_API DeflatingOutputStream: public std::ostream, public DeflatingIOS
+	/// This stream compresses all data passing through it
+	/// using zlib's deflate algorithm.
+	/// After all data has been written to the stream, close()
+	/// must be called to ensure completion of compression.
+	/// Example:
+	///     std::ofstream ostr("data.gz", std::ios::binary);
+	///     DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP);
+	///     deflater << "Hello, world!" << std::endl;
+	///     deflater.close();
+	///     ostr.close();
+{
+public:
+	DeflatingOutputStream(std::ostream& ostr, DeflatingStreamBuf::StreamType type = DeflatingStreamBuf::STREAM_ZLIB, int level = Z_DEFAULT_COMPRESSION);
+		/// Creates a DeflatingOutputStream for compressing data passed
+		/// through and forwarding it to the given output stream.
+
+	DeflatingOutputStream(std::ostream& ostr, int windowBits, int level);
+		/// Creates a DeflatingOutputStream for compressing data passed
+		/// through and forwarding it to the given output stream.
+		///
+		/// Please refer to the zlib documentation of deflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~DeflatingOutputStream();
+		/// Destroys the DeflatingOutputStream.
+		
+	int close();
+		/// Finishes up the stream. 
+		///
+		/// Must be called when deflating to an output stream.
+
+protected:
+	virtual int sync();
+};
+
+
+class Foundation_API DeflatingInputStream: public std::istream, public DeflatingIOS
+	/// This stream compresses all data passing through it
+	/// using zlib's deflate algorithm.
+{
+public:
+	DeflatingInputStream(std::istream& istr, DeflatingStreamBuf::StreamType type = DeflatingStreamBuf::STREAM_ZLIB, int level = Z_DEFAULT_COMPRESSION);
+		/// Creates a DeflatingIOS for compressing data read
+		/// from the given input stream.
+
+	DeflatingInputStream(std::istream& istr, int windowBits, int level);
+		/// Creates a DeflatingIOS for compressing data read
+		/// from the given input stream.
+		///
+		/// Please refer to the zlib documentation of deflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~DeflatingInputStream();
+		/// Destroys the DeflatingInputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DeflatingStream_INCLUDED
diff --git a/Poco/Delegate.h b/Poco/Delegate.h
new file mode 100644
index 0000000..b0b2c76
--- /dev/null
+++ b/Poco/Delegate.h
@@ -0,0 +1,452 @@
+//
+// Delegate.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  Delegate
+//
+// Implementation of the Delegate template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Delegate_INCLUDED
+#define Foundation_Delegate_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractDelegate.h"
+#include "Poco/FunctionDelegate.h"
+#include "Poco/Expire.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class TObj, class TArgs, bool withSender = true>
+class Delegate: public AbstractDelegate<TArgs>
+{
+public:
+	typedef void (TObj::*NotifyMethod)(const void*, TArgs&);
+
+	Delegate(TObj* obj, NotifyMethod method):
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+
+	Delegate(const Delegate& delegate):
+		AbstractDelegate<TArgs>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+
+	~Delegate()
+	{
+	}
+
+	Delegate& operator = (const Delegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)(sender, arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap());
+		return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new Delegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex        _mutex;
+
+private:
+	Delegate();
+};
+
+
+template <class TObj, class TArgs>
+class Delegate<TObj, TArgs, false>: public AbstractDelegate<TArgs>
+{
+public:
+	typedef void (TObj::*NotifyMethod)(TArgs&);
+
+	Delegate(TObj* obj, NotifyMethod method):
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+
+	Delegate(const Delegate& delegate):
+		AbstractDelegate<TArgs>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+
+	~Delegate()
+	{
+	}
+
+	Delegate& operator = (const Delegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+		}
+		return *this;
+	}
+
+	bool notify(const void*, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)(arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap());
+		return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new Delegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex        _mutex;
+
+private:
+	Delegate();
+};
+
+
+template <class TObj, class TArgs>
+inline Delegate<TObj, TArgs, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&))
+{
+	return Delegate<TObj, TArgs, true>(pObj, NotifyMethod);
+}
+
+
+template <class TObj, class TArgs>
+inline Delegate<TObj, TArgs, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&))
+{
+	return Delegate<TObj, TArgs, false>(pObj, NotifyMethod);
+}
+
+
+template <class TObj, class TArgs>
+inline Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<TArgs>(Delegate<TObj, TArgs, true>(pObj, NotifyMethod), expireMillisecs);
+}
+
+
+template <class TObj, class TArgs>
+inline Expire<TArgs> delegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<TArgs>(Delegate<TObj, TArgs, false>(pObj, NotifyMethod), expireMillisecs);
+}
+
+
+template <class TArgs>
+inline Expire<TArgs> delegate(void (*NotifyMethod)(const void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<TArgs>(FunctionDelegate<TArgs, true, true>(NotifyMethod), expireMillisecs);
+}
+
+
+template <class TArgs>
+inline Expire<TArgs> delegate(void (*NotifyMethod)(void*, TArgs&), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<TArgs>(FunctionDelegate<TArgs, true, false>(NotifyMethod), expireMillisecs);
+}
+
+
+template <class TArgs>
+inline Expire<TArgs> delegate(void (*NotifyMethod)(TArgs&), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<TArgs>(FunctionDelegate<TArgs, false>(NotifyMethod), expireMillisecs);
+}
+
+
+template <class TArgs>
+inline FunctionDelegate<TArgs, true, true> delegate(void (*NotifyMethod)(const void*, TArgs&))
+{
+	return FunctionDelegate<TArgs, true, true>(NotifyMethod);
+}
+
+
+template <class TArgs>
+inline FunctionDelegate<TArgs, true, false> delegate(void (*NotifyMethod)(void*, TArgs&))
+{
+	return FunctionDelegate<TArgs, true, false>(NotifyMethod);
+}
+
+
+template <class TArgs>
+inline FunctionDelegate<TArgs, false> delegate(void (*NotifyMethod)(TArgs&))
+{
+	return FunctionDelegate<TArgs, false>(NotifyMethod);
+}
+
+
+template <class TObj>
+class Delegate<TObj,void,true>: public AbstractDelegate<void>
+{
+public:
+	typedef void (TObj::*NotifyMethod)(const void*);
+
+	Delegate(TObj* obj, NotifyMethod method):
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+
+	Delegate(const Delegate& delegate):
+		AbstractDelegate<void>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+
+	~Delegate()
+	{
+	}
+
+	Delegate& operator = (const Delegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)(sender);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap());
+		return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new Delegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex        _mutex;
+
+private:
+	Delegate();
+};
+
+
+template <class TObj>
+class Delegate<TObj, void, false>: public AbstractDelegate<void>
+{
+public:
+	typedef void (TObj::*NotifyMethod)();
+
+	Delegate(TObj* obj, NotifyMethod method):
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+
+	Delegate(const Delegate& delegate):
+		AbstractDelegate<void>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+
+	~Delegate()
+	{
+	}
+
+	Delegate& operator = (const Delegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+		}
+		return *this;
+	}
+
+	bool notify(const void*)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)();
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const Delegate* pOtherDelegate = dynamic_cast<const Delegate*>(other.unwrap());
+		return pOtherDelegate && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new Delegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex        _mutex;
+
+private:
+	Delegate();
+};
+
+
+template <class TObj>
+inline Delegate<TObj, void, true> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*))
+{
+	return Delegate<TObj, void, true>(pObj, NotifyMethod);
+}
+
+
+template <class TObj>
+inline Delegate<TObj, void, false> delegate(TObj* pObj, void (TObj::*NotifyMethod)())
+{
+	return Delegate<TObj, void, false>(pObj, NotifyMethod);
+}
+
+
+template <class TObj>
+inline Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<void>(Delegate<TObj, void, true>(pObj, NotifyMethod), expireMillisecs);
+}
+
+
+template <class TObj>
+inline Expire<void> delegate(TObj* pObj, void (TObj::*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<void>(Delegate<TObj, void, false>(pObj, NotifyMethod), expireMillisecs);
+}
+
+
+inline Expire<void> delegate(void (*NotifyMethod)(const void*), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<void>(FunctionDelegate<void, true, true>(NotifyMethod), expireMillisecs);
+}
+
+
+inline Expire<void> delegate(void (*NotifyMethod)(void*), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<void>(FunctionDelegate<void, true, false>(NotifyMethod), expireMillisecs);
+}
+
+
+inline Expire<void> delegate(void (*NotifyMethod)(), Timestamp::TimeDiff expireMillisecs)
+{
+	return Expire<void>(FunctionDelegate<void, false>(NotifyMethod), expireMillisecs);
+}
+
+
+inline FunctionDelegate<void, true, true> delegate(void (*NotifyMethod)(const void*))
+{
+	return FunctionDelegate<void, true, true>(NotifyMethod);
+}
+
+
+inline FunctionDelegate<void, true, false> delegate(void (*NotifyMethod)(void*))
+{
+	return FunctionDelegate<void, true, false>(NotifyMethod);
+}
+
+
+inline FunctionDelegate<void, false> delegate(void (*NotifyMethod)())
+{
+	return FunctionDelegate<void, false>(NotifyMethod);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Delegate_INCLUDED
diff --git a/Poco/DigestEngine.h b/Poco/DigestEngine.h
new file mode 100644
index 0000000..b22ab6d
--- /dev/null
+++ b/Poco/DigestEngine.h
@@ -0,0 +1,111 @@
+//
+// DigestEngine.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  DigestEngine
+//
+// Definition of class DigestEngine.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DigestEngine_INCLUDED
+#define Foundation_DigestEngine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API DigestEngine
+	/// This class is an abstract base class
+	/// for all classes implementing a message
+	/// digest algorithm, like MD5Engine
+	/// and SHA1Engine.
+	/// Call update() repeatedly with data to
+	/// compute the digest from. When done,
+	/// call digest() to obtain the message
+	/// digest.
+{
+public:
+	typedef std::vector<unsigned char> Digest;
+
+	DigestEngine();
+	virtual ~DigestEngine();
+
+	void update(const void* data, std::size_t length);
+	void update(char data);
+	void update(const std::string& data);
+		/// Updates the digest with the given data.
+
+	virtual std::size_t digestLength() const = 0;
+		/// Returns the length of the digest in bytes.
+
+	virtual void reset() = 0;
+		/// Resets the engine so that a new
+		/// digest can be computed.
+
+	virtual const Digest& digest() = 0;
+		/// Finishes the computation of the digest and
+		/// returns the message digest. Resets the engine
+		/// and can thus only be called once for every digest.
+		/// The returned reference is valid until the next
+		/// time digest() is called, or the engine object is destroyed.
+
+	static std::string digestToHex(const Digest& bytes);
+		/// Converts a message digest into a string of hexadecimal numbers.
+
+	static Digest digestFromHex(const std::string& digest);
+		/// Converts a string created by digestToHex back to its Digest presentation
+
+	static bool constantTimeEquals(const Digest& d1, const Digest& d2);
+		/// Compares two Digest values using a constant-time comparison
+		/// algorithm. This can be used to prevent timing attacks
+		/// (as discussed in <https://codahale.com/a-lesson-in-timing-attacks/>).
+
+protected:
+	virtual void updateImpl(const void* data, std::size_t length) = 0;
+		/// Updates the digest with the given data. Must be implemented
+		/// by subclasses.
+
+private:
+	DigestEngine(const DigestEngine&);
+	DigestEngine& operator = (const DigestEngine&);
+};
+
+
+//
+// inlines
+//
+
+
+inline void DigestEngine::update(const void* data, std::size_t length)
+{
+	updateImpl(data, length);
+}
+
+
+inline void DigestEngine::update(char data)
+{
+	updateImpl(&data, 1);
+}
+
+
+inline void DigestEngine::update(const std::string& data)
+{
+	updateImpl(data.data(), data.size());
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DigestEngine_INCLUDED
diff --git a/Poco/DigestStream.h b/Poco/DigestStream.h
new file mode 100644
index 0000000..6976e01
--- /dev/null
+++ b/Poco/DigestStream.h
@@ -0,0 +1,100 @@
+//
+// DigestStream.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  DigestStream
+//
+// Definition of classes DigestInputStream and DigestOutputStream.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DigestStream_INCLUDED
+#define Foundation_DigestStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferedStreamBuf.h"
+#include "Poco/DigestEngine.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API DigestBuf: public BufferedStreamBuf
+	/// This streambuf computes a digest of all data going
+	/// through it.
+{
+public:
+	DigestBuf(DigestEngine& eng);
+	DigestBuf(DigestEngine& eng, std::istream& istr);
+	DigestBuf(DigestEngine& eng, std::ostream& ostr);
+	~DigestBuf();	
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+	void close();
+
+private:
+	DigestEngine& _eng;
+	std::istream* _pIstr;
+	std::ostream* _pOstr;
+	static const int BUFFER_SIZE;
+};
+
+
+class Foundation_API DigestIOS: public virtual std::ios
+	/// The base class for DigestInputStream and DigestOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	DigestIOS(DigestEngine& eng);
+	DigestIOS(DigestEngine& eng, std::istream& istr);
+	DigestIOS(DigestEngine& eng, std::ostream& ostr);
+	~DigestIOS();
+	DigestBuf* rdbuf();
+
+protected:
+	DigestBuf _buf;
+};
+
+
+class Foundation_API DigestInputStream: public DigestIOS, public std::istream
+	/// This istream computes a digest of
+	/// all the data passing through it,
+	/// using a DigestEngine.
+{
+public:
+	DigestInputStream(DigestEngine& eng, std::istream& istr);
+	~DigestInputStream();
+};
+
+
+class Foundation_API DigestOutputStream: public DigestIOS, public std::ostream
+	/// This ostream computes a digest of
+	/// all the data passing through it,
+	/// using a DigestEngine.
+	/// To ensure that all data has been incorporated
+	/// into the digest, call close() or flush() before 
+	/// you obtain the digest from the digest engine.
+{
+public:
+	DigestOutputStream(DigestEngine& eng);
+	DigestOutputStream(DigestEngine& eng, std::ostream& ostr);
+	~DigestOutputStream();
+	void close();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DigestStream_INCLUDED
diff --git a/Poco/DirectoryIterator.h b/Poco/DirectoryIterator.h
new file mode 100644
index 0000000..c3cedf3
--- /dev/null
+++ b/Poco/DirectoryIterator.h
@@ -0,0 +1,153 @@
+//
+// DirectoryIterator.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  DirectoryIterator
+//
+// Definition of the DirectoryIterator class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DirectoryIterator_INCLUDED
+#define Foundation_DirectoryIterator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/File.h"
+#include "Poco/Path.h"
+
+
+namespace Poco {
+
+
+class DirectoryIteratorImpl;
+
+
+class Foundation_API DirectoryIterator
+	/// The DirectoryIterator class is used to enumerate
+	/// all files in a directory.
+	///
+	/// DirectoryIterator has some limitations:
+	///   * only forward iteration (++) is supported
+	///   * an iterator copied from another one will always
+	///     point to the same file as the original iterator,
+	///     even is the original iterator has been advanced
+	///     (all copies of an iterator share their state with
+	///     the original iterator)
+	///   * because of this you should only use the prefix 
+	///     increment operator
+{
+public:
+	DirectoryIterator();
+		/// Creates the end iterator.
+		
+	DirectoryIterator(const std::string& path);
+		/// Creates a directory iterator for the given path.
+
+	DirectoryIterator(const DirectoryIterator& iterator);
+		/// Creates a directory iterator for the given path.
+		
+	DirectoryIterator(const File& file);
+		/// Creates a directory iterator for the given file.
+
+	DirectoryIterator(const Path& path);
+		/// Creates a directory iterator for the given path.
+
+	virtual ~DirectoryIterator();
+		/// Destroys the DirectoryIterator.
+
+	const std::string& name() const;
+		/// Returns the current filename.
+		
+	const Path& path() const;
+		/// Returns the current path.
+
+	DirectoryIterator& operator = (const DirectoryIterator& it);
+	DirectoryIterator& operator = (const File& file);
+	DirectoryIterator& operator = (const Path& path);
+	DirectoryIterator& operator = (const std::string& path);
+	
+	virtual DirectoryIterator& operator ++ ();   // prefix
+	
+	//@ deprecated
+	DirectoryIterator operator ++ (int); // postfix
+		/// Please use the prefix increment operator instead.
+	
+	const File& operator * () const;
+	File& operator * ();
+	const File* operator -> () const;
+	File* operator -> ();
+	
+	bool operator == (const DirectoryIterator& iterator) const;
+	bool operator != (const DirectoryIterator& iterator) const;
+
+protected:
+	Path _path;
+	File _file;
+
+private:
+	DirectoryIteratorImpl* _pImpl;
+};
+
+
+//
+// inlines
+//
+inline const std::string& DirectoryIterator::name() const
+{
+	return _path.getFileName();
+}
+
+	
+inline const Path& DirectoryIterator::path() const
+{
+	return _path;
+}
+
+
+inline const File& DirectoryIterator::operator * () const
+{
+	return _file;
+}
+
+
+inline File& DirectoryIterator::operator * ()
+{
+	return _file;
+}
+
+
+inline const File* DirectoryIterator::operator -> () const
+{
+	return &_file;
+}
+
+
+inline File* DirectoryIterator::operator -> ()
+{
+	return &_file;
+}
+
+
+inline bool DirectoryIterator::operator == (const DirectoryIterator& iterator) const
+{
+	return name() == iterator.name();
+}
+
+
+inline bool DirectoryIterator::operator != (const DirectoryIterator& iterator) const
+{
+	return name() != iterator.name();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DirectoryIterator_INCLUDED
diff --git a/Poco/DirectoryIteratorStrategy.h b/Poco/DirectoryIteratorStrategy.h
new file mode 100644
index 0000000..7f5465d
--- /dev/null
+++ b/Poco/DirectoryIteratorStrategy.h
@@ -0,0 +1,92 @@
+//
+// RecursiveDirectoryIteratorStategies.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  RecursiveDirectoryIterator
+//
+// Definitions of the RecursiveDirectoryIterator stategy classes.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RecursiveDirectoryIteratorStrategy_INCLUDED
+#define Foundation_RecursiveDirectoryIteratorStrategy_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DirectoryIterator.h"
+#include <stack>
+#include <queue>
+#include <functional>
+
+
+namespace Poco {
+
+
+class Foundation_API TraverseBase
+{
+public:
+	typedef std::stack<DirectoryIterator> Stack;
+	typedef std::pointer_to_unary_function<const Stack&, UInt16> DepthFunPtr;
+
+	enum
+	{
+		D_INFINITE = 0 /// Special value for infinite traverse depth.
+	};
+
+	TraverseBase(DepthFunPtr depthDeterminer, UInt16 maxDepth = D_INFINITE);
+
+protected:
+	bool isFiniteDepth();
+	bool isDirectory(Poco::File& file);
+
+	DepthFunPtr _depthDeterminer;
+	UInt16 _maxDepth;
+	DirectoryIterator _itEnd;
+
+private:
+	TraverseBase();
+	TraverseBase(const TraverseBase&);
+	TraverseBase& operator=(const TraverseBase&);
+};
+
+
+class Foundation_API ChildrenFirstTraverse: public TraverseBase
+{
+public:
+	ChildrenFirstTraverse(DepthFunPtr depthDeterminer, UInt16 maxDepth = D_INFINITE);
+
+	const std::string next(Stack* itStack, bool* isFinished);
+
+private:
+	ChildrenFirstTraverse();
+	ChildrenFirstTraverse(const ChildrenFirstTraverse&);
+	ChildrenFirstTraverse& operator=(const ChildrenFirstTraverse&);
+};
+
+
+class Foundation_API SiblingsFirstTraverse: public TraverseBase
+{
+public:
+	SiblingsFirstTraverse(DepthFunPtr depthDeterminer, UInt16 maxDepth = D_INFINITE);
+
+	const std::string next(Stack* itStack, bool* isFinished);
+
+private:
+	SiblingsFirstTraverse();
+	SiblingsFirstTraverse(const SiblingsFirstTraverse&);
+	SiblingsFirstTraverse& operator=(const SiblingsFirstTraverse&);
+
+	std::stack<std::queue<std::string> > _dirsStack;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RecursiveDirectoryIteratorStrategy_INCLUDED
diff --git a/Poco/DirectoryIterator_UNIX.h b/Poco/DirectoryIterator_UNIX.h
new file mode 100644
index 0000000..d21f711
--- /dev/null
+++ b/Poco/DirectoryIterator_UNIX.h
@@ -0,0 +1,72 @@
+//
+// DirectoryIterator_UNIX.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  DirectoryIterator
+//
+// Definition of the DirectoryIteratorImpl class for UNIX.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DirectoryIterator_UNIX_INCLUDED
+#define Foundation_DirectoryIterator_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <dirent.h>
+
+
+namespace Poco {
+
+
+class Foundation_API DirectoryIteratorImpl
+{
+public:
+	DirectoryIteratorImpl(const std::string& path);
+	~DirectoryIteratorImpl();
+	
+	void duplicate();
+	void release();
+	
+	const std::string& get() const;
+	const std::string& next();
+	
+private:
+	DIR*        _pDir;
+	std::string _current;
+	int _rc;
+};
+
+
+//
+// inlines
+//
+const std::string& DirectoryIteratorImpl::get() const
+{
+	return _current;
+}
+
+
+inline void DirectoryIteratorImpl::duplicate()
+{
+	++_rc;
+}
+
+
+inline void DirectoryIteratorImpl::release()
+{
+	if (--_rc == 0)
+		delete this;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DirectoryIterator_UNIX_INCLUDED
diff --git a/Poco/DirectoryIterator_WIN32.h b/Poco/DirectoryIterator_WIN32.h
new file mode 100644
index 0000000..068cac3
--- /dev/null
+++ b/Poco/DirectoryIterator_WIN32.h
@@ -0,0 +1,73 @@
+//
+// DirectoryIterator_WIN32.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  DirectoryIterator
+//
+// Definition of the DirectoryIteratorImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DirectoryIterator_WIN32_INCLUDED
+#define Foundation_DirectoryIterator_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API DirectoryIteratorImpl
+{
+public:
+	DirectoryIteratorImpl(const std::string& path);
+	~DirectoryIteratorImpl();
+	
+	void duplicate();
+	void release();
+	
+	const std::string& get() const;
+	const std::string& next();
+	
+private:
+	HANDLE          _fh;
+	WIN32_FIND_DATA _fd;
+	std::string     _current;
+	int _rc;
+};
+
+
+//
+// inlines
+//
+const std::string& DirectoryIteratorImpl::get() const
+{
+	return _current;
+}
+
+
+inline void DirectoryIteratorImpl::duplicate()
+{
+	++_rc;
+}
+
+
+inline void DirectoryIteratorImpl::release()
+{
+	if (--_rc == 0)
+		delete this;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DirectoryIterator_WIN32_INCLUDED
diff --git a/Poco/DirectoryIterator_WIN32U.h b/Poco/DirectoryIterator_WIN32U.h
new file mode 100644
index 0000000..496842c
--- /dev/null
+++ b/Poco/DirectoryIterator_WIN32U.h
@@ -0,0 +1,73 @@
+//
+// DirectoryIterator_WIN32U.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  DirectoryIterator
+//
+// Definition of the DirectoryIteratorImpl class for WIN32.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DirectoryIterator_WIN32U_INCLUDED
+#define Foundation_DirectoryIterator_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API DirectoryIteratorImpl
+{
+public:
+	DirectoryIteratorImpl(const std::string& path);
+	~DirectoryIteratorImpl();
+	
+	void duplicate();
+	void release();
+	
+	const std::string& get() const;
+	const std::string& next();
+	
+private:
+	HANDLE           _fh;
+	WIN32_FIND_DATAW _fd;
+	std::string      _current;
+	int _rc;
+};
+
+
+//
+// inlines
+//
+const std::string& DirectoryIteratorImpl::get() const
+{
+	return _current;
+}
+
+
+inline void DirectoryIteratorImpl::duplicate()
+{
+	++_rc;
+}
+
+
+inline void DirectoryIteratorImpl::release()
+{
+	if (--_rc == 0)
+		delete this;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DirectoryIterator_WIN32U_INCLUDED
diff --git a/Poco/DirectoryWatcher.h b/Poco/DirectoryWatcher.h
new file mode 100644
index 0000000..6e3a492
--- /dev/null
+++ b/Poco/DirectoryWatcher.h
@@ -0,0 +1,232 @@
+//
+// DirectoryWatcher.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  DirectoryWatcher
+//
+// Definition of the DirectoryWatcher class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DirectoryWatcher_INCLUDED
+#define Foundation_DirectoryWatcher_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#ifndef POCO_NO_INOTIFY
+
+
+#include "Poco/File.h"
+#include "Poco/BasicEvent.h"
+#include "Poco/Runnable.h"
+#include "Poco/Thread.h"
+#include "Poco/AtomicCounter.h"
+
+
+namespace Poco {
+
+
+class DirectoryWatcherStrategy;
+
+
+class Foundation_API DirectoryWatcher: protected Runnable
+	/// This class is used to get notifications about changes
+	/// to the filesystem, more specifically, to a specific
+	/// directory. Changes to a directory are reported via
+	/// events.
+	///
+	/// A thread will be created that watches the specified
+	/// directory for changes. Events are reported in the context
+	/// of this thread. 
+	///
+	/// Note that changes to files in subdirectories of the watched
+	/// directory are not reported. Separate DirectoryWatcher objects
+	/// must be created for these directories if they should be watched.
+	///
+	/// Changes to file attributes are not reported.
+	///
+	/// On Windows, this class is implemented using FindFirstChangeNotification()/FindNextChangeNotification().
+	/// On Linux, this class is implemented using inotify.
+	/// On FreeBSD and Darwin (Mac OS X, iOS), this class uses kevent/kqueue.
+	/// On all other platforms, the watched directory is periodically scanned
+	/// for changes. This can negatively affect performance if done too often.
+	/// Therefore, the interval in which scans are done can be specified in
+	/// the constructor. Note that periodic scanning will also be done on FreeBSD
+	/// and Darwin if events for changes to files (DW_ITEM_MODIFIED) are enabled.
+	///
+	/// DW_ITEM_MOVED_FROM and DW_ITEM_MOVED_TO events will only be reported
+	/// on Linux. On other platforms, a file rename or move operation
+	/// will be reported via a DW_ITEM_REMOVED and a DW_ITEM_ADDED event.
+	/// The order of these two events is not defined.
+	///
+	/// An event mask can be specified to enable only certain events.
+{
+public:
+	enum DirectoryEventType
+	{
+		DW_ITEM_ADDED = 1,
+			/// A new item has been created and added to the directory.
+			
+		DW_ITEM_REMOVED = 2,
+			/// An item has been removed from the directory.
+
+		DW_ITEM_MODIFIED = 4,
+			/// An item has been modified.
+
+		DW_ITEM_MOVED_FROM = 8,
+			/// An item has been renamed or moved. This event delivers the old name.
+
+		DW_ITEM_MOVED_TO = 16
+			/// An item has been renamed or moved. This event delivers the new name.
+	};
+
+	enum DirectoryEventMask
+	{
+		DW_FILTER_ENABLE_ALL = 31,
+			/// Enables all event types.
+
+		DW_FILTER_DISABLE_ALL = 0
+			/// Disables all event types.
+	};
+	
+	enum
+	{
+		DW_DEFAULT_SCAN_INTERVAL = 5 /// Default scan interval for platforms that don't provide a native notification mechanism.
+	};
+	
+	struct DirectoryEvent
+	{
+		DirectoryEvent(const File& f, DirectoryEventType ev):
+			item(f),
+			event(ev)
+		{
+		}
+
+		const File& item;          /// The directory or file that has been changed.
+		DirectoryEventType event;  /// The kind of event.
+	};
+	
+	BasicEvent<const DirectoryEvent> itemAdded;
+		/// Fired when a file or directory has been created or added to the directory.
+		
+	BasicEvent<const DirectoryEvent> itemRemoved;
+		/// Fired when a file or directory has been removed from the directory.
+		
+	BasicEvent<const DirectoryEvent> itemModified;
+		/// Fired when a file or directory has been modified.
+
+	BasicEvent<const DirectoryEvent> itemMovedFrom;
+		/// Fired when a file or directory has been renamed. This event delivers the old name.
+
+	BasicEvent<const DirectoryEvent> itemMovedTo;
+		/// Fired when a file or directory has been moved. This event delivers the new name.
+		
+	BasicEvent<const Exception> scanError;
+		/// Fired when an error occurs while scanning for changes.
+	
+	DirectoryWatcher(const std::string& path, int eventMask = DW_FILTER_ENABLE_ALL, int scanInterval = DW_DEFAULT_SCAN_INTERVAL);
+		/// Creates a DirectoryWatcher for the directory given in path.
+		/// To enable only specific events, an eventMask can be specified by
+		/// OR-ing the desired event IDs (e.g., DW_ITEM_ADDED | DW_ITEM_MODIFIED).
+		/// On platforms where no native filesystem notifications are available,
+		/// scanInterval specifies the interval in seconds between scans
+		/// of the directory.
+		
+	DirectoryWatcher(const File& directory, int eventMask = DW_FILTER_ENABLE_ALL, int scanInterval = DW_DEFAULT_SCAN_INTERVAL);
+		/// Creates a DirectoryWatcher for the specified directory
+		/// To enable only specific events, an eventMask can be specified by
+		/// OR-ing the desired event IDs (e.g., DW_ITEM_ADDED | DW_ITEM_MODIFIED).
+		/// On platforms where no native filesystem notifications are available,
+		/// scanInterval specifies the interval in seconds between scans
+		/// of the directory.
+
+	~DirectoryWatcher();
+		/// Destroys the DirectoryWatcher.
+		
+	void suspendEvents();
+		/// Suspends sending of events. Can be called multiple times, but every
+		/// call to suspendEvent() must be matched by a call to resumeEvents().
+		
+	void resumeEvents();
+		/// Resumes events, after they have been suspended with a call to suspendEvents().
+		
+	bool eventsSuspended() const;
+		/// Returns true iff events are suspended.
+		
+	int eventMask() const;
+		/// Returns the value of the eventMask passed to the constructor.
+		
+	int scanInterval() const;
+		/// Returns the scan interval in seconds.
+		
+	const File& directory() const;
+		/// Returns the directory being watched.
+		
+	bool supportsMoveEvents() const;
+		/// Returns true iff the platform supports DW_ITEM_MOVED_FROM/itemMovedFrom and
+		/// DW_ITEM_MOVED_TO/itemMovedTo events.
+	
+protected:
+	void init();
+	void stop();
+	void run();
+
+private:
+	DirectoryWatcher();
+	DirectoryWatcher(const DirectoryWatcher&);
+	DirectoryWatcher& operator = (const DirectoryWatcher&);
+
+	Thread _thread;
+	File _directory;
+	int _eventMask;
+	AtomicCounter _eventsSuspended;
+	int _scanInterval;
+	DirectoryWatcherStrategy* _pStrategy;
+};
+
+
+//
+// inlines
+//
+
+
+inline bool DirectoryWatcher::eventsSuspended() const
+{
+	return _eventsSuspended.value() > 0;
+}
+
+
+inline int DirectoryWatcher::eventMask() const
+{
+	return _eventMask;
+}
+
+
+inline int DirectoryWatcher::scanInterval() const
+{
+	return _scanInterval;
+}
+
+
+inline const File& DirectoryWatcher::directory() const
+{
+	return _directory;
+}
+
+
+} // namespace Poco
+
+
+#endif // POCO_NO_INOTIFY
+
+
+#endif // Foundation_DirectoryWatcher_INCLUDED
+
diff --git a/Poco/DoubleByteEncoding.h b/Poco/DoubleByteEncoding.h
new file mode 100644
index 0000000..469458e
--- /dev/null
+++ b/Poco/DoubleByteEncoding.h
@@ -0,0 +1,122 @@
+//
+// DoubleByteEncoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  DoubleByteEncoding
+//
+// Definition of the DoubleByteEncoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Encodings_DoubleByteEncoding_INCLUDED
+#define Encodings_DoubleByteEncoding_INCLUDED
+
+
+#include "Poco/Encodings.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API DoubleByteEncoding: public TextEncoding
+	/// This abstract class is a base class for various double-byte character
+	/// set (DBCS) encodings.
+	///
+	/// Double-byte encodings are variants of multi-byte encodings
+	/// where (Unicode) each code point is represented by one or
+	/// two bytes. Unicode code points are restricted to the
+	/// Basic Multilingual Plane.
+	///
+	/// Subclasses must provide encoding names, a static CharacterMap, as well
+	/// as static Mapping and reverse Mapping tables, and provide these to the
+	/// DoubleByteEncoding constructor.
+{
+public:
+	struct Mapping
+	{
+		Poco::UInt16 from;
+		Poco::UInt16 to;
+	};
+
+	// TextEncoding
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+
+protected:
+	DoubleByteEncoding(const char** names, const TextEncoding::CharacterMap& charMap, const Mapping mappingTable[], std::size_t mappingTableSize, const Mapping reverseMappingTable[], std::size_t reverseMappingTableSize);
+		/// Creates a DoubleByteEncoding using the given mapping and reverse-mapping tables.
+		///
+		/// names must be a static array declared in the derived class,
+		/// containing the names of this encoding, declared as:
+		///
+		///     const char* MyEncoding::_names[] =
+		///     {
+		///         "myencoding",
+		///         "MyEncoding",
+		///         NULL
+		///     };
+		///
+		/// The first entry in names must be the canonical name.
+		///
+		/// charMap must be a static CharacterMap giving information about double-byte
+		/// character sequences.
+		///
+		/// For each mappingTable item, from must be a value in range 0x0100 to
+		//  0xFFFF for double-byte mappings, which the most significant (upper) byte
+		/// representing the first character in the sequence and the lower byte
+		/// representing the second character in the sequence.
+		///
+		/// For each reverseMappingTable item, from must be Unicode code point from the
+		/// Basic Multilingual Plane, and to is a one-byte or two-byte sequence.
+		/// As with mappingTable, a one-byte sequence is in range 0x00 to 0xFF, and a
+		/// two-byte sequence is in range 0x0100 to 0xFFFF.
+		///
+		/// Unicode code points are restricted to the Basic Multilingual Plane
+		/// (code points 0x0000 to 0xFFFF).
+		///
+		/// Items in both tables must be sorted by from, in ascending order.
+
+	~DoubleByteEncoding();
+		/// Destroys the DoubleByteEncoding.
+
+	int map(Poco::UInt16 encoded) const;
+		/// Maps a double-byte encoded character to its Unicode code point.
+		///
+		/// Returns the Unicode code point, or -1 if the encoded character is bad
+		/// and cannot be mapped.
+
+	int reverseMap(int cp) const;
+		/// Maps a Unicode code point to its double-byte representation.
+		///
+		/// Returns -1 if the code point cannot be mapped, otherwise
+		/// a value in range 0 to 0xFF for single-byte mappings, or
+		/// 0x0100 to 0xFFFF for double-byte mappings.
+
+private:
+	DoubleByteEncoding();
+
+	const char** _names;
+	const TextEncoding::CharacterMap& _charMap;
+	const Mapping* _mappingTable;
+	const std::size_t _mappingTableSize;
+	const Mapping* _reverseMappingTable;
+	const std::size_t _reverseMappingTableSize;
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_DoubleByteEncoding_INCLUDED
diff --git a/Poco/Dynamic/Pair.h b/Poco/Dynamic/Pair.h
new file mode 100644
index 0000000..c64eece
--- /dev/null
+++ b/Poco/Dynamic/Pair.h
@@ -0,0 +1,412 @@
+//
+// Pair.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Pair
+//
+// Definition of the Pair class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Pair_INCLUDED
+#define Foundation_Pair_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Dynamic/VarHolder.h"
+#include <utility>
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <typename K>
+class Pair
+	/// Pair allows to define a pair of values.
+{
+public:
+	typedef typename std::pair<K, Var> Data;
+
+	Pair(): _data()
+		/// Creates an empty Pair
+	{
+	}
+
+	Pair(const Pair& other): _data(other._data)
+		/// Creates the Pair from another pair.
+	{
+	}
+
+	Pair(const Data& val): _data(val)
+		/// Creates the Pair from the given value.
+	{
+	}
+
+	template <typename T>
+	Pair(const std::pair<K, T>& val): _data(std::make_pair(val.first, val.second))
+		/// Creates Pair form standard pair.
+	{
+	}
+
+	template <typename T>
+	Pair(const K& first, const T& second): _data(std::make_pair(first, second))
+		/// Creates pair from two values.
+	{
+	}
+
+	virtual ~Pair()
+		/// Destroys the Pair.
+	{
+	}
+
+	Pair& swap(Pair& other)
+		/// Swaps the content of the two Pairs.
+	{
+		std::swap(_data, other._data);
+		return *this;
+	}
+
+	Pair& operator = (const Pair& other)
+		/// Copy constructs Pair from another pair.
+	{
+		Pair(other).swap(*this);
+		return *this;
+	}
+
+	inline const K& first() const
+		/// Returns the first member of the pair.
+	{
+		return _data.first;
+	}
+
+	inline const Var& second() const
+		/// Returns the second member of the pair.
+	{
+		return _data.second;
+	}
+
+	std::string toString()
+	{
+		std::string str;
+		Var(*this).convert<std::string>(str);
+		return str;
+	}
+
+private:
+	Data _data;
+};
+
+
+template <>
+class VarHolderImpl<Pair<std::string> >: public VarHolder
+{
+public:
+	VarHolderImpl(const Pair<std::string>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Pair<std::string>);
+	}
+
+	void convert(Int8& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int8");
+	}
+
+	void convert(Int16& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int16");
+	}
+	
+	void convert(Int32& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int32");
+	}
+
+	void convert(Int64& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int64");
+	}
+
+	void convert(UInt8& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt8");
+	}
+
+	void convert(UInt16& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt16");
+	}
+	
+	void convert(UInt32& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt32");
+	}
+
+	void convert(UInt64& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt64");
+	}
+
+	void convert(bool& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to bool");
+	}
+
+	void convert(float& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to float");
+	}
+
+	void convert(double& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to double");
+	}
+
+	void convert(char& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to char");
+	}
+
+	void convert(std::string& val) const
+	{
+		// Serialize in JSON format: equals an object
+		// JSON format definition: { string ':' value } string:value pair n-times, sep. by ','
+		val.append("{ ");
+		Var key(_val.first());
+		Impl::appendJSONKey(val, key);
+		val.append(" : ");
+		Impl::appendJSONValue(val, _val.second());
+		val.append(" }");	
+	}
+
+	void convert(Poco::DateTime&) const
+	{
+		throw BadCastException("Pair -> Poco::DateTime");
+	}
+
+	void convert(Poco::LocalDateTime&) const
+	{
+		throw BadCastException("Pair -> Poco::LocalDateTime");
+	}
+
+	void convert(Poco::Timestamp&) const
+	{
+		throw BadCastException("Pair -> Poco::Timestamp");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Pair<std::string>& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	Pair<std::string> _val;
+};
+
+
+template <>
+class VarHolderImpl<Pair<int> >: public VarHolder
+{
+public:
+	VarHolderImpl(const Pair<int>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Pair<int>);
+	}
+
+	void convert(Int8& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int8");
+	}
+
+	void convert(Int16& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int16");
+	}
+	
+	void convert(Int32& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int32");
+	}
+
+	void convert(Int64& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to Int64");
+	}
+
+	void convert(UInt8& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt8");
+	}
+
+	void convert(UInt16& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt16");
+	}
+	
+	void convert(UInt32& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt32");
+	}
+
+	void convert(UInt64& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to UInt64");
+	}
+
+	void convert(bool& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to bool");
+	}
+
+	void convert(float& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to float");
+	}
+
+	void convert(double& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to double");
+	}
+
+	void convert(char& val) const
+	{
+		throw BadCastException("Cannot cast Pair type to char");
+	}
+
+	void convert(std::string& val) const
+	{
+		// Serialize in JSON format: equals an object
+		// JSON format definition: { string ':' value } string:value pair n-times, sep. by ','
+		val.append("{ ");
+		Var key(_val.first());
+		Impl::appendJSONKey(val, key);
+		val.append(" : ");
+		Impl::appendJSONValue(val, _val.second());
+		val.append(" }");	
+	}
+
+	void convert(Poco::DateTime&) const
+	{
+		throw BadCastException("Pair -> Poco::DateTime");
+	}
+
+	void convert(Poco::LocalDateTime&) const
+	{
+		throw BadCastException("Pair -> Poco::LocalDateTime");
+	}
+
+	void convert(Poco::Timestamp&) const
+	{
+		throw BadCastException("Pair -> Poco::Timestamp");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Pair<int>& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	Pair<int> _val;
+};
+
+
+} // namespace Dynamic
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Pair_INCLUDED
diff --git a/Poco/Dynamic/Struct.h b/Poco/Dynamic/Struct.h
new file mode 100644
index 0000000..d510115
--- /dev/null
+++ b/Poco/Dynamic/Struct.h
@@ -0,0 +1,567 @@
+//
+// Struct.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Struct
+//
+// Definition of the Struct class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Struct_INCLUDED
+#define Foundation_Struct_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Dynamic/VarHolder.h"
+#include "Poco/SharedPtr.h"
+#include <map>
+#include <set>
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <typename K>
+class Struct
+	/// Struct allows to define a named collection of Var objects.
+{
+public:
+	typedef typename std::map<K, Var> Data;
+	typedef typename std::set<K> NameSet;
+	typedef typename Data::iterator Iterator;
+	typedef typename Data::const_iterator ConstIterator;
+	typedef typename Struct<K>::Data::value_type ValueType;
+	typedef typename Struct<K>::Data::size_type SizeType;
+	typedef typename std::pair<typename Struct<K>::Iterator, bool> InsRetVal;
+	typedef typename Poco::SharedPtr<Struct<K> > Ptr;
+
+	Struct(): _data()
+		/// Creates an empty Struct
+	{
+	}
+
+	Struct(const Data& val): _data(val)
+		/// Creates the Struct from the given value.
+	{
+	}
+
+	template <typename T>
+	Struct(const std::map<K, T>& val)
+	{
+		typedef typename std::map<K, T>::const_iterator MapConstIterator;
+
+		MapConstIterator it = val.begin();
+		MapConstIterator end = val.end();
+		for (; it != end; ++it) _data.insert(ValueType(it->first, Var(it->second)));
+	}
+
+	virtual ~Struct()
+		/// Destroys the Struct.
+	{
+	}
+
+	inline Var& operator [] (const K& name)
+		/// Returns the Var with the given name, creates an entry if not found.
+	{
+		return _data[name];
+	}
+
+	const Var& operator [] (const K& name) const
+		/// Returns the Var with the given name, throws a
+		/// NotFoundException if the data member is not found.
+	{
+		ConstIterator it = find(name);
+		if (it == end()) throw NotFoundException(name);
+		return it->second;
+	}
+
+	inline bool contains(const K& name) const
+		/// Returns true if the Struct contains a member with the given name
+	{
+		return find(name) != end();
+	}
+
+	inline Iterator find(const K& name)
+		/// Returns an iterator, pointing to the <name,Var> pair containing
+		/// the element, or it returns end() if the member was not found
+	{
+		return _data.find(name);
+	}
+
+	inline ConstIterator find(const K& name) const
+		/// Returns a const iterator, pointing to the <name,Var> pair containing
+		/// the element, or it returns end() if the member was not found
+	{
+		return _data.find(name);
+	}
+
+	inline Iterator end()
+		/// Returns the end iterator for the Struct
+	{
+		return _data.end();
+	}
+
+	inline ConstIterator end() const
+		/// Returns the end const iterator for the Struct
+	{
+		return _data.end();
+	}
+
+	inline Iterator begin()
+		/// Returns the begin iterator for the Struct
+	{
+		return _data.begin();
+	}
+
+	inline ConstIterator begin() const
+		/// Returns the begin const iterator for the Struct
+	{
+		return _data.begin();
+	}
+
+	template <typename T>
+	inline InsRetVal insert(const K& key, const T& value)
+		/// Inserts a <name, Var> pair into the Struct,
+		/// returns a pair containing the iterator and a boolean which
+		/// indicates success or not (is true, when insert succeeded, false,
+		/// when already another element was present, in this case Iterator
+		/// points to that other element)
+	{
+		// fix: SunPro C++ is silly ...
+		ValueType valueType(key, value);
+		return insert(valueType);
+	}
+
+	inline InsRetVal insert(const ValueType& aPair)
+		/// Inserts a <name, Var> pair into the Struct,
+		/// returns a pair containing the iterator and a boolean which
+		/// indicates success or not (is true, when insert succeeded, false,
+		/// when already another element was present, in this case Iterator
+		/// points to that other element)
+	{
+		return _data.insert(aPair);
+	}
+
+	inline SizeType erase(const K& key)
+		/// Erases the element if found, returns number of elements deleted
+	{
+		return _data.erase(key);
+	}
+
+	inline void erase(Iterator& it)
+		/// Erases the element at the given position
+	{
+		_data.erase(it);
+	}
+
+	inline bool empty() const
+		/// Returns true if the Struct doesn't contain any members
+	{
+		return _data.empty();
+	}
+
+	inline void clear()
+		/// Clears the Struct contents
+	{
+		_data.clear();
+	}
+
+	SizeType size() const
+		/// Returns the number of members the Struct contains
+	{
+		return _data.size();
+	}
+
+	inline NameSet members() const
+		/// Returns a sorted collection containing all member names
+	{
+		NameSet keys;
+		ConstIterator it = begin();
+		ConstIterator itEnd = end();
+		for (; it != itEnd; ++it) keys.insert(it->first);
+		return keys;
+	}
+
+	std::string toString()
+	{
+		std::string str;
+		Var(*this).convert<std::string>(str);
+		return str;
+	}
+
+private:
+	Data _data;
+};
+
+
+template <>
+class VarHolderImpl<Struct<std::string> >: public VarHolder
+{
+public:
+	VarHolderImpl(const Struct<std::string>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Struct<std::string>);
+	}
+
+	void convert(Int8&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int8");
+	}
+
+	void convert(Int16&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int16");
+	}
+	
+	void convert(Int32&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int32");
+	}
+
+	void convert(Int64&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int64");
+	}
+
+	void convert(UInt8&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt8");
+	}
+
+	void convert(UInt16&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt16");
+	}
+	
+	void convert(UInt32&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt32");
+	}
+
+	void convert(UInt64&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt64");
+	}
+
+	void convert(bool&) const
+	{
+		throw BadCastException("Cannot cast Struct type to bool");
+	}
+
+	void convert(float&) const
+	{
+		throw BadCastException("Cannot cast Struct type to float");
+	}
+
+	void convert(double&) const
+	{
+		throw BadCastException("Cannot cast Struct type to double");
+	}
+
+	void convert(char&) const
+	{
+		throw BadCastException("Cannot cast Struct type to char");
+	}
+
+	void convert(std::string& val) const
+	{
+		val.append("{ ");
+		Struct<std::string>::ConstIterator it = _val.begin();
+		Struct<std::string>::ConstIterator itEnd = _val.end();
+		if (!_val.empty())
+		{
+			Var key(it->first);
+			Impl::appendJSONKey(val, key);
+			val.append(" : ");
+			Impl::appendJSONValue(val, it->second);
+			++it;
+		}
+		for (; it != itEnd; ++it)
+		{
+			val.append(", ");
+			Var key(it->first);
+			Impl::appendJSONKey(val, key);
+			val.append(" : ");
+			Impl::appendJSONValue(val, it->second);
+		}
+		val.append(" }");
+	}
+
+	void convert(Poco::DateTime&) const
+	{
+		throw BadCastException("Struct -> Poco::DateTime");
+	}
+
+	void convert(Poco::LocalDateTime&) const
+	{
+		throw BadCastException("Struct -> Poco::LocalDateTime");
+	}
+
+	void convert(Poco::Timestamp&) const
+	{
+		throw BadCastException("Struct -> Poco::Timestamp");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Struct<std::string>& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return true;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+	
+	std::size_t size() const
+	{
+		return _val.size();
+	}
+
+	Var& operator [] (const std::string& name)
+	{
+		return _val[name];
+	}
+
+	const Var& operator [] (const std::string& name) const
+	{
+		return _val[name];
+	}
+
+private:
+	Struct<std::string> _val;
+};
+
+
+template <>
+class VarHolderImpl<Struct<int> >: public VarHolder
+{
+public:
+	VarHolderImpl(const Struct<int>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Struct<int>);
+	}
+
+	void convert(Int8&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int8");
+	}
+
+	void convert(Int16&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int16");
+	}
+	
+	void convert(Int32&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int32");
+	}
+
+	void convert(Int64&) const
+	{
+		throw BadCastException("Cannot cast Struct type to Int64");
+	}
+
+	void convert(UInt8&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt8");
+	}
+
+	void convert(UInt16&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt16");
+	}
+	
+	void convert(UInt32&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt32");
+	}
+
+	void convert(UInt64&) const
+	{
+		throw BadCastException("Cannot cast Struct type to UInt64");
+	}
+
+	void convert(bool&) const
+	{
+		throw BadCastException("Cannot cast Struct type to bool");
+	}
+
+	void convert(float&) const
+	{
+		throw BadCastException("Cannot cast Struct type to float");
+	}
+
+	void convert(double&) const
+	{
+		throw BadCastException("Cannot cast Struct type to double");
+	}
+
+	void convert(char&) const
+	{
+		throw BadCastException("Cannot cast Struct type to char");
+	}
+
+	void convert(std::string& val) const
+	{
+		val.append("{ ");
+		Struct<int>::ConstIterator it = _val.begin();
+		Struct<int>::ConstIterator itEnd = _val.end();
+		if (!_val.empty())
+		{
+			Var key(it->first);
+			Impl::appendJSONKey(val, key);
+			val.append(" : ");
+			Impl::appendJSONValue(val, it->second);
+			++it;
+		}
+		for (; it != itEnd; ++it)
+		{
+			val.append(", ");
+			Var key(it->first);
+			Impl::appendJSONKey(val, key);
+			val.append(" : ");
+			Impl::appendJSONValue(val, it->second);
+		}
+		val.append(" }");	
+	}
+
+	void convert(Poco::DateTime&) const
+	{
+		throw BadCastException("Struct -> Poco::DateTime");
+	}
+
+	void convert(Poco::LocalDateTime&) const
+	{
+		throw BadCastException("Struct -> Poco::LocalDateTime");
+	}
+
+	void convert(Poco::Timestamp&) const
+	{
+		throw BadCastException("Struct -> Poco::Timestamp");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Struct<int>& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return true;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+	std::size_t size() const
+	{
+		return _val.size();
+	}
+
+	Var& operator [] (int name)
+	{
+		return _val[name];
+	}
+
+	const Var& operator [] (int name) const
+	{
+		return _val[name];
+	}
+
+private:
+	Struct<int> _val;
+};
+
+
+} // namespace Dynamic
+
+
+typedef Dynamic::Struct<std::string> DynamicStruct;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Struct_INCLUDED
diff --git a/Poco/Dynamic/Var.h b/Poco/Dynamic/Var.h
new file mode 100644
index 0000000..bd06afe
--- /dev/null
+++ b/Poco/Dynamic/Var.h
@@ -0,0 +1,2228 @@
+//
+// Var.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Var
+//
+// Definition of the Var class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Var_INCLUDED
+#define Foundation_Var_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Format.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Dynamic/VarHolder.h"
+#include "Poco/Dynamic/VarIterator.h"
+#include <typeinfo>
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <typename T>
+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 
+	/// unexpected data loss, particularly when performing narrowing or signedness conversions of numeric data types.
+	///
+	/// An attempt to convert or extract from a non-initialized ("empty") Var variable shall result
+	/// in an exception being thrown.
+	///
+	/// Loss of signedness is not allowed for numeric values. This means that if an attempt is made to convert 
+	/// the internal value which is a negative signed integer to an unsigned integer type storage, a RangeException is thrown. 
+	/// Overflow is not allowed, so if the internal value is a larger number than the target numeric type size can accommodate, 
+	/// a RangeException is thrown.
+	///
+	/// Precision loss, such as in conversion from floating-point types to integers or from double to float on platforms
+	/// where they differ in size (provided internal actual value fits in float min/max range), is allowed.
+	/// 
+	/// String truncation is allowed -- it is possible to convert between string and character when string length is 
+	/// greater than 1. An empty string gets converted to the char '\0', a non-empty string is truncated to the first character. 
+	///
+	/// Boolean conversion is performed as follows:
+	///
+	/// A string value "false" (not case sensitive), "0" or "" (empty string) can be converted to a boolean value false,
+	/// any other string not being false by the above criteria evaluates to true (e.g: "hi" -> true).
+	/// Integer 0 values are false, everything else is true.
+	/// Floating point values equal to the minimal FP representation on a given platform are false, everything else is true.
+	///
+	/// Arithmetic operations with POD types as well as between Var's are supported, subject to following
+	/// limitations:
+	/// 
+	/// 	- for std::string and const char* values, only '+' and '+=' operations are supported
+	/// 
+	/// 	- for integral and floating point numeric values, following operations are supported:
+	/// 	  '+', '+=', '-', '-=', '*', '*=' , '/' and '/=' 
+	///
+	/// 	- for integral values, following operations are supported:
+	///		  prefix and postfix increment (++) and decrement (--)
+	/// 
+	/// 	- for all other types, InvalidArgumentException is thrown upon attempt of an arithmetic operation
+	/// 
+	/// A Var can be created from and converted to a value of any type for which a specialization of 
+	/// VarHolderImpl is available. For supported types, see VarHolder documentation.
+{
+public:
+	typedef SharedPtr<Var>             Ptr;
+	typedef Poco::Dynamic::VarIterator Iterator;
+	typedef const VarIterator          ConstIterator;
+
+	Var();
+		/// Creates an empty Var.
+
+	template <typename T> 
+	Var(const T& val)
+		/// Creates the Var from the given value.
+#ifdef POCO_NO_SOO
+		: _pHolder(new VarHolderImpl<T>(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.
+
+	Var(const Var& other);
+		/// Copy constructor.
+
+	~Var();
+		/// Destroys the Var.
+
+	void swap(Var& other);
+		/// Swaps the content of the this Var with the other Var.
+
+	ConstIterator begin() const;
+		/// Returns the const Var iterator.
+
+	ConstIterator end() const;
+		/// Returns the const Var iterator.
+
+	Iterator begin();
+		/// Returns the Var iterator.
+
+	Iterator end();
+		/// Returns the Var iterator.
+
+	template <typename T> 
+	void convert(T& val) const
+		/// Invoke this method to perform a safe conversion.
+		///
+		/// Example usage:
+		///     Var any("42");
+		///     int i;
+		///     any.convert(i);
+		///
+		/// Throws a RangeException if the value does not fit
+		/// into the result variable.
+		/// Throws a NotImplementedException if conversion is
+		/// not available for the given type.
+		/// Throws InvalidAccessException if Var is empty.
+	{
+		VarHolder* pHolder = content();
+
+		if (!pHolder)
+			throw InvalidAccessException("Can not convert empty value.");
+
+		pHolder->convert(val);
+	}
+	
+	template <typename T> 
+	T convert() const
+		/// Invoke this method to perform a safe conversion.
+		///
+		/// Example usage:
+		///     Var any("42");
+		///     int i = any.convert<int>();
+		///
+		/// Throws a RangeException if the value does not fit
+		/// into the result variable.
+		/// Throws a NotImplementedException if conversion is
+		/// not available for the given type.
+		/// Throws InvalidAccessException if Var is empty.
+	{
+		VarHolder* pHolder = content();
+
+		if (!pHolder)
+			throw InvalidAccessException("Can not convert empty value.");
+
+		if (typeid(T) == pHolder->type()) return extract<T>();
+
+		T result;
+		pHolder->convert(result);
+		return result;
+	}
+	
+	template <typename T>
+	operator T () const
+		/// Safe conversion operator for implicit type
+		/// conversions. If the requested type T is same as the 
+		/// type being held, the operation performed is direct 
+		/// extraction, otherwise it is the conversion of the value
+		/// from type currently held to the one requested.
+		///
+		/// Throws a RangeException if the value does not fit
+		/// into the result variable.
+		/// Throws a NotImplementedException if conversion is
+		/// not available for the given type.
+		/// Throws InvalidAccessException if Var is empty.
+	{
+		VarHolder* pHolder = content();
+
+		if (!pHolder)
+				throw InvalidAccessException("Can not convert empty value.");
+
+		if (typeid(T) == pHolder->type())
+			return extract<T>();
+		else
+		{
+			T result;
+			pHolder->convert(result);
+			return result;
+		}
+	}
+
+	template <typename T>
+	const T& extract() const
+		/// Returns a const reference to the actual value.
+		///
+		/// Must be instantiated with the exact type of
+		/// the stored value, otherwise a BadCastException
+		/// is thrown.
+		/// Throws InvalidAccessException if Var is empty.
+	{
+		VarHolder* pHolder = content();
+
+		if (pHolder && pHolder->type() == typeid(T))
+		{
+			VarHolderImpl<T>* pHolderImpl = static_cast<VarHolderImpl<T>*>(pHolder);
+			return pHolderImpl->value();
+		}
+		else if (!pHolder)
+			throw InvalidAccessException("Can not extract empty value.");
+		else
+			throw BadCastException(format("Can not convert %s to %s.",
+				std::string(pHolder->type().name()),
+				std::string(typeid(T).name())));
+	}
+
+	template <typename T> 
+	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;
+	}
+
+	bool operator ! () const;
+		/// Logical NOT operator.
+
+	Var& operator = (const Var& other);
+		/// Assignment operator specialization for Var
+
+	template <typename T>
+	const Var operator + (const T& other) const
+		/// Addition operator for adding POD to Var
+	{
+		return convert<T>() + other;
+	}
+
+	const Var operator + (const Var& other) const;
+		/// Addition operator specialization for Var
+
+	const Var operator + (const char* other) const;
+		/// Addition operator specialization for adding const char* to Var
+
+	Var& operator ++ ();
+		/// Pre-increment operator
+
+	const Var operator ++ (int);
+		/// Post-increment operator
+
+	Var& operator -- ();
+		/// Pre-decrement operator
+
+	const Var operator -- (int);
+		/// Post-decrement operator
+
+	template <typename T> 
+	Var& operator += (const T& other)
+		/// Addition assignment operator for addition/assignment of POD to Var.
+	{
+		return *this = convert<T>() + other;
+	}
+
+	Var& operator += (const Var& other);
+		/// Addition assignment operator overload for Var
+
+	Var& operator += (const char* other);
+		/// Addition assignment operator overload for const char*
+
+	template <typename T> 
+	const Var operator - (const T& other) const
+		/// Subtraction operator for subtracting POD from Var
+	{
+		return convert<T>() - other;
+	}
+
+	const Var operator - (const Var& other) const;
+		/// Subtraction operator overload for Var
+
+	template <typename T> 
+	Var& operator -= (const T& other)
+		/// Subtraction assignment operator
+	{
+		return *this = convert<T>() - other;
+	}
+
+	Var& operator -= (const Var& other);
+		/// Subtraction assignment operator overload for Var
+
+	template <typename T> 
+	const Var operator * (const T& other) const
+		/// Multiplication operator for multiplying Var with POD
+	{
+		return convert<T>() * other;
+	}
+
+	const Var operator * (const Var& other) const;
+		/// Multiplication operator overload for Var
+
+	template <typename T> 
+	Var& operator *= (const T& other)
+		/// Multiplication assignment operator
+	{
+		return *this = convert<T>() * other;
+	}
+
+	Var& operator *= (const Var& other);
+		/// Multiplication assignment operator overload for Var
+
+	template <typename T> 
+	const Var operator / (const T& other) const
+		/// Division operator for dividing Var with POD
+	{
+		return convert<T>() / other;
+	}
+
+	const Var operator / (const Var& other) const;
+		/// Division operator overload for Var
+
+	template <typename T> 
+	Var& operator /= (const T& other)
+		/// Division assignment operator
+	{
+		return *this = convert<T>() / other;
+	}
+
+	Var& operator /= (const Var& other);
+		/// Division assignment operator specialization for Var
+
+	template <typename T> 
+	bool operator == (const T& other) const
+		/// Equality operator
+	{
+		if (isEmpty()) return false;
+		return convert<T>() == other;
+	}
+
+	bool operator == (const char* other) const;
+		/// Equality operator overload for const char*
+
+	bool operator == (const Var& other) const;
+		/// Equality operator overload for Var
+
+	template <typename T> 
+	bool operator != (const T& other) const
+		/// Inequality operator
+	{
+		if (isEmpty()) return true;
+		return convert<T>() != other;
+	}
+
+	bool operator != (const Var& other) const;
+		/// Inequality operator overload for Var
+
+	bool operator != (const char* other) const;
+		/// Inequality operator overload for const char*
+
+	template <typename T> 
+	bool operator < (const T& other) const
+		/// Less than operator
+	{
+		if (isEmpty()) return false;
+		return convert<T>() < other;
+	}
+
+	bool operator < (const Var& other) const;
+		/// Less than operator overload for Var
+
+	template <typename T> 
+	bool operator <= (const T& other) const
+		/// Less than or equal operator
+	{
+		if (isEmpty()) return false;
+		return convert<T>() <= other;
+	}
+
+	bool operator <= (const Var& other) const;
+		/// Less than or equal operator overload for Var
+
+	template <typename T> 
+	bool operator > (const T& other) const
+		/// Greater than operator
+	{
+		if (isEmpty()) return false;
+		return convert<T>() > other;
+	}
+
+	bool operator > (const Var& other) const;
+		/// Greater than operator overload for Var
+
+	template <typename T> 
+	bool operator >= (const T& other) const
+		/// Greater than or equal operator
+	{
+		if (isEmpty()) return false;
+		return convert<T>() >= other;
+	}
+
+	bool operator >= (const Var& other) const;
+		/// Greater than or equal operator overload for Var
+
+	template <typename T>
+	bool operator || (const T& other) const
+		/// Logical OR operator
+	{
+		if (isEmpty()) return false;
+		return convert<bool>() || other;
+	}
+
+	bool operator || (const Var& other) const;
+		/// Logical OR operator operator overload for Var
+
+	template <typename T>
+	bool operator && (const T& other) const
+		/// Logical AND operator.
+	{
+		if (isEmpty()) return false;
+		return convert<bool>() && other;
+	}
+
+	bool operator && (const Var& other) const;
+		/// Logical AND operator operator overload for Var.
+
+	bool isArray() const;
+		/// Returns true if Var is an array.
+
+	bool isVector() const;
+		/// Returns true if Var represents a vector.
+
+	bool isList() const;
+		/// Returns true if Var represents a list.
+
+	bool isDeque() const;
+		/// Returns true if Var represents a deque.
+
+	bool isStruct() const;
+		/// Returns true if Var represents a struct.
+
+	char& at(std::size_t n);
+		/// Returns character at position n. This function only works with
+		/// Var containing a std::string.
+
+
+	template <typename T>
+	Var& operator [] (const T& n)
+	{
+		return getAt(n);
+	}
+
+	template <typename T>
+	const Var& operator [] (const T& n) const
+	{
+		return const_cast<Var*>(this)->getAt(n);
+	}
+
+	Var& operator [] (const std::string& name);
+		/// Index operator by name, only use on Vars where isStruct
+		/// returns true! In all other cases InvalidAccessException is thrown.
+
+	const Var& operator [] (const std::string& name) const;
+		/// Index operator by name, only use on Vars where isStruct
+		/// returns true! In all other cases InvalidAccessException is thrown.
+
+	const std::type_info& type() const;
+		/// Returns the type information of the stored content.
+
+	//@ deprecated
+	void empty();
+		/// Empties Var.
+		/// This function is deprecated and will be removed.
+		/// Please use clear().
+
+	void clear();
+		/// Empties Var.
+
+	bool isEmpty() const;
+		/// Returns true if empty.
+
+	bool isInteger() const;
+		/// Returns true if stored value is integer.
+
+	bool isSigned() const;
+		/// Returns true if stored value is signed.
+
+	bool isNumeric() const;
+		/// Returns true if stored value is numeric.
+		/// Returns false for numeric strings (e.g. "123" is string, not number)
+
+	bool isBoolean() const;
+		/// Returns true if stored value is boolean.
+		/// Returns false for boolean strings (e.g. "true" is string, not number)
+
+	bool isString() const;
+		/// Returns true if stored value is std::string.
+
+	bool isDate() const;
+		/// Returns true if stored value represents a date.
+
+	bool isTime() const;
+		/// Returns true if stored value represents time or date/time.
+
+	bool isDateTime() const;
+		/// Returns true if stored value represents a date/time.
+
+	std::size_t size() const;
+		/// Returns the size of this Var.
+		/// This function returns 0 when Var is empty, 1 for POD or the size (i.e. length)
+		/// for held container.
+
+	std::string toString() const
+		/// Returns the stored value as string.
+	{
+		VarHolder* pHolder = content();
+
+		if (!pHolder)
+				throw InvalidAccessException("Can not convert empty value.");
+
+		if (typeid(std::string) == pHolder->type())
+			return extract<std::string>();
+		else
+		{
+			std::string result;
+			pHolder->convert(result);
+			return result;
+		}
+	}
+
+	static Var parse(const std::string& val);
+		/// Parses the string which must be in JSON format
+
+	static std::string toString(const Var& var);
+		/// Converts the Var to a string in JSON format. Note that toString(const Var&) will return
+		/// a different result than Var::convert<std::string>() and Var::toString()!
+	
+private:
+	Var& getAt(std::size_t n);
+	Var& getAt(const std::string& n);
+
+	static Var parse(const std::string& val, std::string::size_type& offset);
+		/// Parses the string which must be in JSON format
+
+	static Var parseObject(const std::string& val, std::string::size_type& pos);
+	static Var parseArray(const std::string& val, std::string::size_type& pos);
+	static std::string parseString(const std::string& val, std::string::size_type& pos);
+	static std::string parseJSONString(const std::string& val, std::string::size_type& pos);
+	static void skipWhiteSpace(const std::string& val, std::string::size_type& pos);
+
+	template <typename T>
+	T add(const Var& other) const
+	{
+		return convert<T>() + other.convert<T>();
+	}
+
+	template <typename T>
+	T subtract(const Var& other) const
+	{
+		return convert<T>() - other.convert<T>();
+	}
+	
+	template <typename T>
+	T multiply(const Var& other) const
+	{
+		return convert<T>() * other.convert<T>();
+	}
+
+	template <typename T>
+	T divide(const Var& other) const
+	{
+		return convert<T>() / other.convert<T>();
+	}
+
+	template <typename T, typename E>
+	VarHolderImpl<T>* holderImpl(const std::string errorMessage = "") const
+	{
+		VarHolder* pHolder = content();
+
+		if (pHolder && pHolder->type() == typeid(T))
+			return static_cast<VarHolderImpl<T>*>(pHolder);
+		else if (!pHolder)
+			throw InvalidAccessException("Can not access empty value.");
+		else
+			throw E(errorMessage);
+	}
+
+	Var& structIndexOperator(VarHolderImpl<Struct<int> >* pStr, int n) const;
+
+#ifdef POCO_NO_SOO
+
+	VarHolder* content() const
+	{
+		return _pHolder;
+	}
+
+	void destruct()
+	{
+		if (!isEmpty()) delete content();
+	}
+
+	VarHolder* _pHolder;
+
+#else
+
+	VarHolder* content() const
+	{
+		return _placeholder.content();
+	}
+
+	template<typename ValueType>
+	void construct(const ValueType& value)
+	{
+		if (sizeof(VarHolderImpl<ValueType>) <= Placeholder<ValueType>::Size::value)
+		{
+			new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<ValueType>(value);
+			_placeholder.setLocal(true);
+		}
+		else
+		{
+			_placeholder.pHolder = new VarHolderImpl<ValueType>(value);
+			_placeholder.setLocal(false);
+		}
+	}
+
+	void construct(const char* value)
+	{
+		std::string val(value);
+		if (sizeof(VarHolderImpl<std::string>) <= Placeholder<std::string>::Size::value)
+		{
+			new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<std::string>(val);
+			_placeholder.setLocal(true);
+		}
+		else
+		{
+			_placeholder.pHolder = new VarHolderImpl<std::string>(val);
+			_placeholder.setLocal(false);
+		}
+	}
+
+	void construct(const Var& other)
+	{
+		if (!other.isEmpty())
+			other.content()->clone(&_placeholder);
+		else
+			_placeholder.erase();
+	}
+
+	void destruct()
+	{
+		if (!isEmpty())
+		{
+			if (_placeholder.isLocal())
+				content()->~VarHolder();
+			else
+				delete content();
+		}
+	}
+
+	Placeholder<VarHolder> _placeholder;
+
+#endif // POCO_NO_SOO
+};
+
+
+///
+/// inlines
+///
+
+
+///
+/// Var members
+///
+
+inline void Var::swap(Var& other)
+{
+#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);
+		try
+		{
+			if (_placeholder.isLocal()) destruct();
+			construct(other);
+			other = tmp;
+		}
+		catch (...)
+		{
+			construct(tmp);
+			throw;
+		}
+	}
+
+#endif
+}
+
+
+inline const std::type_info& Var::type() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->type() : typeid(void);
+}
+
+
+inline Var::ConstIterator Var::begin() const
+{
+	if (isEmpty()) return ConstIterator(const_cast<Var*>(this), true);
+
+	return ConstIterator(const_cast<Var*>(this), false);
+}
+
+inline Var::ConstIterator Var::end() const
+{
+	return ConstIterator(const_cast<Var*>(this), true);
+}
+
+inline Var::Iterator Var::begin()
+{
+	if (isEmpty()) return Iterator(const_cast<Var*>(this), true);
+
+	return Iterator(const_cast<Var*>(this), false);
+}
+
+inline Var::Iterator Var::end()
+{
+	return Iterator(this, true);
+}
+
+
+inline Var& Var::operator [] (const std::string& name)
+{
+	return getAt(name);
+}
+
+
+inline const Var& Var::operator [] (const std::string& name) const
+{
+	return const_cast<Var*>(this)->getAt(name);
+}
+
+
+inline const Var Var::operator + (const char* other) const
+{
+	return convert<std::string>() + other;
+}
+
+
+inline Var& Var::operator += (const char*other)
+{
+	return *this = convert<std::string>() + other;
+}
+
+
+inline bool Var::operator ! () const
+{
+	return !convert<bool>();
+}
+
+
+inline bool Var::isEmpty() const
+{
+	return 0 == content();
+}
+
+
+inline bool Var::isArray() const
+{
+	if (isEmpty() || 
+		isString()) return false;
+
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isArray() : false;
+}
+
+
+inline bool Var::isVector() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isVector() : false;
+}
+
+
+inline bool Var::isList() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isList() : false;
+}
+
+
+inline bool Var::isDeque() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isDeque() : false;
+}
+
+
+inline bool Var::isStruct() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isStruct() : false;
+}
+
+
+inline bool Var::isInteger() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isInteger() : false;
+}
+
+
+inline bool Var::isSigned() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isSigned() : false;
+}
+
+
+inline bool Var::isNumeric() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isNumeric() : false;
+}
+
+
+inline bool Var::isBoolean() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isBoolean() : false;
+}
+
+
+inline bool Var::isString() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isString() : false;
+}
+
+
+inline bool Var::isDate() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isDate() : false;
+}
+
+
+inline bool Var::isTime() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isTime() : false;
+}
+
+
+inline bool Var::isDateTime() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->isDateTime() : false;
+}
+
+
+inline std::size_t Var::size() const
+{
+	VarHolder* pHolder = content();
+	return pHolder ? pHolder->size() : 0;
+}
+
+
+///
+/// Var non-member functions
+///
+
+inline const Var operator + (const char* other, const Var& da)
+	/// Addition operator for adding Var to const char*
+{
+	std::string tmp = other;
+	return tmp + da.convert<std::string>();
+}
+
+
+inline char operator + (const char& other, const Var& da)
+	/// Addition operator for adding Var to char
+{
+	return other + da.convert<char>();
+}
+
+
+inline char operator - (const char& other, const Var& da)
+	/// Subtraction operator for subtracting Var from char
+{
+	return other - da.convert<char>();
+}
+
+
+inline char operator * (const char& other, const Var& da)
+	/// Multiplication operator for multiplying Var with char
+{
+	return other * da.convert<char>();
+}
+
+
+inline char operator / (const char& other, const Var& da)
+	/// Division operator for dividing Var with char
+{
+	return other / da.convert<char>();
+}
+
+
+inline char operator += (char& other, const Var& da)
+	/// Addition assignment operator for adding Var to char
+{
+	return other += da.convert<char>();
+}
+
+
+inline char operator -= (char& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from char
+{
+	return other -= da.convert<char>();
+}
+
+
+inline char operator *= (char& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with char
+{
+	return other *= da.convert<char>();
+}
+
+
+inline char operator /= (char& other, const Var& da)
+	/// Division assignment operator for dividing Var with char
+{
+	return other /= da.convert<char>();
+}
+
+
+inline bool operator == (const char& other, const Var& da)
+	/// Equality operator for comparing Var with char
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<char>();
+}
+
+
+inline bool operator != (const char& other, const Var& da)
+	/// Inequality operator for comparing Var with char
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<char>();
+}
+
+
+inline bool operator < (const char& other, const Var& da)
+	/// Less than operator for comparing Var with char
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<char>();
+}
+
+
+inline bool operator <= (const char& other, const Var& da)
+	/// Less than or equal operator for comparing Var with char
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<char>();
+}
+
+
+inline bool operator > (const char& other, const Var& da)
+	/// Greater than operator for comparing Var with char
+{
+	if (da.isEmpty())return false;
+	return other > da.convert<char>();
+}
+
+
+inline bool operator >= (const char& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with char
+{
+	if (da.isEmpty())return false;
+	return other >= da.convert<char>();
+}
+
+
+inline Poco::Int8 operator + (const Poco::Int8& other, const Var& da)
+	/// Addition operator for adding Var to Poco::Int8
+{
+	return other + da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator - (const Poco::Int8& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::Int8
+{
+	return other - da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator * (const Poco::Int8& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::Int8
+{
+	return other * da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator / (const Poco::Int8& other, const Var& da)
+	/// Division operator for dividing Var with Poco::Int8
+{
+	return other / da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator += (Poco::Int8& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::Int8
+{
+	return other += da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator -= (Poco::Int8& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::Int8
+{
+	return other -= da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator *= (Poco::Int8& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::Int8
+{
+	return other *= da.convert<Poco::Int8>();
+}
+
+
+inline Poco::Int8 operator /= (Poco::Int8& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::Int8
+{
+	return other /= da.convert<Poco::Int8>();
+}
+
+
+inline bool operator == (const Poco::Int8& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::Int8
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::Int8>();
+}
+
+
+inline bool operator != (const Poco::Int8& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::Int8
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::Int8>();
+}
+
+
+inline bool operator < (const Poco::Int8& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::Int8
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::Int8>();
+}
+
+
+inline bool operator <= (const Poco::Int8& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::Int8
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::Int8>();
+}
+
+
+inline bool operator > (const Poco::Int8& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::Int8
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::Int8>();
+}
+
+
+inline bool operator >= (const Poco::Int8& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::Int8
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::Int8>();
+}
+
+
+inline Poco::UInt8 operator + (const Poco::UInt8& other, const Var& da)
+	/// Addition operator for adding Var to Poco::UInt8
+{
+	return other + da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator - (const Poco::UInt8& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::UInt8
+{
+	return other - da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator * (const Poco::UInt8& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::UInt8
+{
+	return other * da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator / (const Poco::UInt8& other, const Var& da)
+	/// Division operator for dividing Var with Poco::UInt8
+{
+	return other / da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator += (Poco::UInt8& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::UInt8
+{
+	return other += da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator -= (Poco::UInt8& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::UInt8
+{
+	return other -= da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator *= (Poco::UInt8& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::UInt8
+{
+	return other *= da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::UInt8 operator /= (Poco::UInt8& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::UInt8
+{
+	return other /= da.convert<Poco::UInt8>();
+}
+
+
+inline bool operator == (const Poco::UInt8& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::UInt8
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::UInt8>();
+}
+
+
+inline bool operator != (const Poco::UInt8& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::UInt8
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::UInt8>();
+}
+
+
+inline bool operator < (const Poco::UInt8& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::UInt8
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::UInt8>();
+}
+
+
+inline bool operator <= (const Poco::UInt8& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::UInt8
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::UInt8>();
+}
+
+
+inline bool operator > (const Poco::UInt8& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::UInt8
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::UInt8>();
+}
+
+
+inline bool operator >= (const Poco::UInt8& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::UInt8
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::UInt8>();
+}
+
+
+inline Poco::Int16 operator + (const Poco::Int16& other, const Var& da)
+	/// Addition operator for adding Var to Poco::Int16
+{
+	return other + da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator - (const Poco::Int16& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::Int16
+{
+	return other - da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator * (const Poco::Int16& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::Int16
+{
+	return other * da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator / (const Poco::Int16& other, const Var& da)
+	/// Division operator for dividing Var with Poco::Int16
+{
+	return other / da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator += (Poco::Int16& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::Int16
+{
+	return other += da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator -= (Poco::Int16& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::Int16
+{
+	return other -= da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator *= (Poco::Int16& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::Int16
+{
+	return other *= da.convert<Poco::Int16>();
+}
+
+
+inline Poco::Int16 operator /= (Poco::Int16& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::Int16
+{
+	return other /= da.convert<Poco::Int16>();
+}
+
+
+inline bool operator == (const Poco::Int16& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::Int16
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::Int16>();
+}
+
+
+inline bool operator != (const Poco::Int16& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::Int16
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::Int16>();
+}
+
+
+inline bool operator < (const Poco::Int16& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::Int16
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::Int16>();
+}
+
+
+inline bool operator <= (const Poco::Int16& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::Int16
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::Int16>();
+}
+
+
+inline bool operator > (const Poco::Int16& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::Int16
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::Int16>();
+}
+
+
+inline bool operator >= (const Poco::Int16& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::Int16
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::Int16>();
+}
+
+
+inline Poco::UInt16 operator + (const Poco::UInt16& other, const Var& da)
+	/// Addition operator for adding Var to Poco::UInt16
+{
+	return other + da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator - (const Poco::UInt16& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::UInt16
+{
+	return other - da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator * (const Poco::UInt16& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::UInt16
+{
+	return other * da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator / (const Poco::UInt16& other, const Var& da)
+	/// Division operator for dividing Var with Poco::UInt16
+{
+	return other / da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator += (Poco::UInt16& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::UInt16
+{
+	return other += da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator -= (Poco::UInt16& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::UInt16
+{
+	return other -= da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator *= (Poco::UInt16& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::UInt16
+{
+	return other *= da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::UInt16 operator /= (Poco::UInt16& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::UInt16
+{
+	return other /= da.convert<Poco::UInt16>();
+}
+
+
+inline bool operator == (const Poco::UInt16& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::UInt16
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::UInt16>();
+}
+
+
+inline bool operator != (const Poco::UInt16& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::UInt16
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::UInt16>();
+}
+
+
+inline bool operator < (const Poco::UInt16& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::UInt16
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::UInt16>();
+}
+
+
+inline bool operator <= (const Poco::UInt16& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::UInt16
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::UInt16>();
+}
+
+
+inline bool operator > (const Poco::UInt16& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::UInt16
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::UInt16>();
+}
+
+
+inline bool operator >= (const Poco::UInt16& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::UInt16
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::UInt16>();
+}
+
+
+inline Poco::Int32 operator + (const Poco::Int32& other, const Var& da)
+	/// Addition operator for adding Var to Poco::Int32
+{
+	return other + da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator - (const Poco::Int32& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::Int32
+{
+	return other - da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator * (const Poco::Int32& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::Int32
+{
+	return other * da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator / (const Poco::Int32& other, const Var& da)
+	/// Division operator for dividing Var with Poco::Int32
+{
+	return other / da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator += (Poco::Int32& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::Int32
+{
+	return other += da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator -= (Poco::Int32& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::Int32
+{
+	return other -= da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator *= (Poco::Int32& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::Int32
+{
+	return other *= da.convert<Poco::Int32>();
+}
+
+
+inline Poco::Int32 operator /= (Poco::Int32& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::Int32
+{
+	return other /= da.convert<Poco::Int32>();
+}
+
+
+inline bool operator == (const Poco::Int32& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::Int32
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::Int32>();
+}
+
+
+inline bool operator != (const Poco::Int32& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::Int32
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::Int32>();
+}
+
+
+inline bool operator < (const Poco::Int32& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::Int32
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::Int32>();
+}
+
+
+inline bool operator <= (const Poco::Int32& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::Int32
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::Int32>();
+}
+
+
+inline bool operator > (const Poco::Int32& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::Int32
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::Int32>();
+}
+
+
+inline bool operator >= (const Poco::Int32& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::Int32
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::Int32>();
+}
+
+
+inline Poco::UInt32 operator + (const Poco::UInt32& other, const Var& da)
+	/// Addition operator for adding Var to Poco::UInt32
+{
+	return other + da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator - (const Poco::UInt32& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::UInt32
+{
+	return other - da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator * (const Poco::UInt32& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::UInt32
+{
+	return other * da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator / (const Poco::UInt32& other, const Var& da)
+	/// Division operator for dividing Var with Poco::UInt32
+{
+	return other / da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator += (Poco::UInt32& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::UInt32
+{
+	return other += da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator -= (Poco::UInt32& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::UInt32
+{
+	return other -= da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator *= (Poco::UInt32& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::UInt32
+{
+	return other *= da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::UInt32 operator /= (Poco::UInt32& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::UInt32
+{
+	return other /= da.convert<Poco::UInt32>();
+}
+
+
+inline bool operator == (const Poco::UInt32& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::UInt32
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::UInt32>();
+}
+
+
+inline bool operator != (const Poco::UInt32& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::UInt32
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::UInt32>();
+}
+
+
+inline bool operator < (const Poco::UInt32& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::UInt32
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::UInt32>();
+}
+
+
+inline bool operator <= (const Poco::UInt32& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::UInt32
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::UInt32>();
+}
+
+
+inline bool operator > (const Poco::UInt32& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::UInt32
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::UInt32>();
+}
+
+
+inline bool operator >= (const Poco::UInt32& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::UInt32
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::UInt32>();
+}
+
+
+inline Poco::Int64 operator + (const Poco::Int64& other, const Var& da)
+	/// Addition operator for adding Var to Poco::Int64
+{
+	return other + da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator - (const Poco::Int64& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::Int64
+{
+	return other - da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator * (const Poco::Int64& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::Int64
+{
+	return other * da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator / (const Poco::Int64& other, const Var& da)
+	/// Division operator for dividing Var with Poco::Int64
+{
+	return other / da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator += (Poco::Int64& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::Int64
+{
+	return other += da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator -= (Poco::Int64& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::Int64
+{
+	return other -= da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator *= (Poco::Int64& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::Int64
+{
+	return other *= da.convert<Poco::Int64>();
+}
+
+
+inline Poco::Int64 operator /= (Poco::Int64& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::Int64
+{
+	return other /= da.convert<Poco::Int64>();
+}
+
+
+inline bool operator == (const Poco::Int64& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::Int64
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::Int64>();
+}
+
+
+inline bool operator != (const Poco::Int64& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::Int64
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::Int64>();
+}
+
+
+inline bool operator < (const Poco::Int64& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::Int64
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::Int64>();
+}
+
+
+inline bool operator <= (const Poco::Int64& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::Int64
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::Int64>();
+}
+
+
+inline bool operator > (const Poco::Int64& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::Int64
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::Int64>();
+}
+
+
+inline bool operator >= (const Poco::Int64& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::Int64
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::Int64>();
+}
+
+
+inline Poco::UInt64 operator + (const Poco::UInt64& other, const Var& da)
+	/// Addition operator for adding Var to Poco::UInt64
+{
+	return other + da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator - (const Poco::UInt64& other, const Var& da)
+	/// Subtraction operator for subtracting Var from Poco::UInt64
+{
+	return other - da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator * (const Poco::UInt64& other, const Var& da)
+	/// Multiplication operator for multiplying Var with Poco::UInt64
+{
+	return other * da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator / (const Poco::UInt64& other, const Var& da)
+	/// Division operator for dividing Var with Poco::UInt64
+{
+	return other / da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator += (Poco::UInt64& other, const Var& da)
+	/// Addition assignment operator for adding Var to Poco::UInt64
+{
+	return other += da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator -= (Poco::UInt64& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from Poco::UInt64
+{
+	return other -= da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator *= (Poco::UInt64& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with Poco::UInt64
+{
+	return other *= da.convert<Poco::UInt64>();
+}
+
+
+inline Poco::UInt64 operator /= (Poco::UInt64& other, const Var& da)
+	/// Division assignment operator for dividing Var with Poco::UInt64
+{
+	return other /= da.convert<Poco::UInt64>();
+}
+
+
+inline bool operator == (const Poco::UInt64& other, const Var& da)
+	/// Equality operator for comparing Var with Poco::UInt64
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<Poco::UInt64>();
+}
+
+
+inline bool operator != (const Poco::UInt64& other, const Var& da)
+	/// Inequality operator for comparing Var with Poco::UInt64
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<Poco::UInt64>();
+}
+
+
+inline bool operator < (const Poco::UInt64& other, const Var& da)
+	/// Less than operator for comparing Var with Poco::UInt64
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<Poco::UInt64>();
+}
+
+
+inline bool operator <= (const Poco::UInt64& other, const Var& da)
+	/// Less than or equal operator for comparing Var with Poco::UInt64
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<Poco::UInt64>();
+}
+
+
+inline bool operator > (const Poco::UInt64& other, const Var& da)
+	/// Greater than operator for comparing Var with Poco::UInt64
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<Poco::UInt64>();
+}
+
+
+inline bool operator >= (const Poco::UInt64& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with Poco::UInt64
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<Poco::UInt64>();
+}
+
+
+inline float operator + (const float& other, const Var& da)
+	/// Addition operator for adding Var to float
+{
+	return other + da.convert<float>();
+}
+
+
+inline float operator - (const float& other, const Var& da)
+	/// Subtraction operator for subtracting Var from float
+{
+	return other - da.convert<float>();
+}
+
+
+inline float operator * (const float& other, const Var& da)
+	/// Multiplication operator for multiplying Var with float
+{
+	return other * da.convert<float>();
+}
+
+
+inline float operator / (const float& other, const Var& da)
+	/// Division operator for dividing Var with float
+{
+	return other / da.convert<float>();
+}
+
+
+inline float operator += (float& other, const Var& da)
+	/// Addition assignment operator for adding Var to float
+{
+	return other += da.convert<float>();
+}
+
+
+inline float operator -= (float& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from float
+{
+	return other -= da.convert<float>();
+}
+
+
+inline float operator *= (float& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with float
+{
+	return other *= da.convert<float>();
+}
+
+
+inline float operator /= (float& other, const Var& da)
+	/// Division assignment operator for dividing Var with float
+{
+	return other /= da.convert<float>();
+}
+
+
+inline bool operator == (const float& other, const Var& da)
+	/// Equality operator for comparing Var with float
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<float>();
+}
+
+
+inline bool operator != (const float& other, const Var& da)
+	/// Inequality operator for comparing Var with float
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<float>();
+}
+
+
+inline bool operator < (const float& other, const Var& da)
+	/// Less than operator for comparing Var with float
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<float>();
+}
+
+
+inline bool operator <= (const float& other, const Var& da)
+	/// Less than or equal operator for comparing Var with float
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<float>();
+}
+
+
+inline bool operator > (const float& other, const Var& da)
+	/// Greater than operator for comparing Var with float
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<float>();
+}
+
+
+inline bool operator >= (const float& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with float
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<float>();
+}
+
+
+inline double operator + (const double& other, const Var& da)
+	/// Addition operator for adding Var to double
+{
+	return other + da.convert<double>();
+}
+
+
+inline double operator - (const double& other, const Var& da)
+	/// Subtraction operator for subtracting Var from double
+{
+	return other - da.convert<double>();
+}
+
+
+inline double operator * (const double& other, const Var& da)
+	/// Multiplication operator for multiplying Var with double
+{
+	return other * da.convert<double>();
+}
+
+
+inline double operator / (const double& other, const Var& da)
+	/// Division operator for dividing Var with double
+{
+	return other / da.convert<double>();
+}
+
+
+inline double operator += (double& other, const Var& da)
+	/// Addition assignment operator for adding Var to double
+{
+	return other += da.convert<double>();
+}
+
+
+inline double operator -= (double& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from double
+{
+	return other -= da.convert<double>();
+}
+
+
+inline double operator *= (double& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with double
+{
+	return other *= da.convert<double>();
+}
+
+
+inline double operator /= (double& other, const Var& da)
+	/// Division assignment operator for dividing Var with double
+{
+	return other /= da.convert<double>();
+}
+
+
+inline bool operator == (const double& other, const Var& da)
+	/// Equality operator for comparing Var with double
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<double>();
+}
+
+
+inline bool operator != (const double& other, const Var& da)
+	/// Inequality operator for comparing Var with double
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<double>();
+}
+
+
+inline bool operator < (const double& other, const Var& da)
+	/// Less than operator for comparing Var with double
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<double>();
+}
+
+
+inline bool operator <= (const double& other, const Var& da)
+	/// Less than or equal operator for comparing Var with double
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<double>();
+}
+
+
+inline bool operator > (const double& other, const Var& da)
+	/// Greater than operator for comparing Var with double
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<double>();
+}
+
+
+inline bool operator >= (const double& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with double
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<double>();
+}
+
+
+inline bool operator == (const bool& other, const Var& da)
+	/// Equality operator for comparing Var with bool
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<bool>();
+}
+
+
+inline bool operator != (const bool& other, const Var& da)
+	/// Inequality operator for comparing Var with bool
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<bool>();
+}
+
+
+inline bool operator == (const std::string& other, const Var& da)
+	/// Equality operator for comparing Var with std::string
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<std::string>();
+}
+
+
+inline bool operator != (const std::string& other, const Var& da)
+	/// Inequality operator for comparing Var with std::string
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<std::string>();
+}
+
+
+inline bool operator == (const UTF16String& other, const Var& da)
+	/// Equality operator for comparing Var with UTF16String
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<UTF16String>();
+}
+
+
+inline bool operator != (const UTF16String& other, const Var& da)
+	/// Inequality operator for comparing Var with UTF16String
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<UTF16String>();
+}
+
+
+inline bool operator == (const char* other, const Var& da)
+	/// Equality operator for comparing Var with const char*
+{
+	if (da.isEmpty()) return false;
+	return da.convert<std::string>() == other;
+}
+
+
+inline bool operator != (const char* other, const Var& da)
+	/// Inequality operator for comparing Var with const char*
+{
+	if (da.isEmpty()) return true;
+	return da.convert<std::string>() != other;
+}
+
+
+#ifndef POCO_LONG_IS_64_BIT
+
+
+inline long operator + (const long& other, const Var& da)
+	/// Addition operator for adding Var to long
+{
+	return other + da.convert<long>();
+}
+
+
+inline long operator - (const long& other, const Var& da)
+	/// Subtraction operator for subtracting Var from long
+{
+	return other - da.convert<long>();
+}
+
+
+inline long operator * (const long& other, const Var& da)
+	/// Multiplication operator for multiplying Var with long
+{
+	return other * da.convert<long>();
+}
+
+
+inline long operator / (const long& other, const Var& da)
+	/// Division operator for dividing Var with long
+{
+	return other / da.convert<long>();
+}
+
+
+inline long operator += (long& other, const Var& da)
+	/// Addition assignment operator for adding Var to long
+{
+	return other += da.convert<long>();
+}
+
+
+inline long operator -= (long& other, const Var& da)
+	/// Subtraction assignment operator for subtracting Var from long
+{
+	return other -= da.convert<long>();
+}
+
+
+inline long operator *= (long& other, const Var& da)
+	/// Multiplication assignment operator for multiplying Var with long
+{
+	return other *= da.convert<long>();
+}
+
+
+inline long operator /= (long& other, const Var& da)
+	/// Division assignment operator for dividing Var with long
+{
+	return other /= da.convert<long>();
+}
+
+
+inline bool operator == (const long& other, const Var& da)
+	/// Equality operator for comparing Var with long
+{
+	if (da.isEmpty()) return false;
+	return other == da.convert<long>();
+}
+
+
+inline bool operator != (const long& other, const Var& da)
+	/// Inequality operator for comparing Var with long
+{
+	if (da.isEmpty()) return true;
+	return other != da.convert<long>();
+}
+
+
+inline bool operator < (const long& other, const Var& da)
+	/// Less than operator for comparing Var with long
+{
+	if (da.isEmpty()) return false;
+	return other < da.convert<long>();
+}
+
+
+inline bool operator <= (const long& other, const Var& da)
+	/// Less than or equal operator for comparing Var with long
+{
+	if (da.isEmpty()) return false;
+	return other <= da.convert<long>();
+}
+
+
+inline bool operator > (const long& other, const Var& da)
+	/// Greater than operator for comparing Var with long
+{
+	if (da.isEmpty()) return false;
+	return other > da.convert<long>();
+}
+
+
+inline bool operator >= (const long& other, const Var& da)
+	/// Greater than or equal operator for comparing Var with long
+{
+	if (da.isEmpty()) return false;
+	return other >= da.convert<long>();
+}
+
+
+#endif // POCO_LONG_IS_64_BIT
+
+
+} // namespace Dynamic
+
+
+//@ deprecated
+typedef Dynamic::Var DynamicAny;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Var_INCLUDED
diff --git a/Poco/Dynamic/VarHolder.h b/Poco/Dynamic/VarHolder.h
new file mode 100644
index 0000000..e0af6a6
--- /dev/null
+++ b/Poco/Dynamic/VarHolder.h
@@ -0,0 +1,4186 @@
+//
+// VarHolder.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  VarHolder
+//
+// Definition of the VarHolder class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_VarHolder_INCLUDED
+#define Foundation_VarHolder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/NumberParser.h"
+#include "Poco/DateTime.h"
+#include "Poco/Timestamp.h"
+#include "Poco/LocalDateTime.h"
+#include "Poco/DateTimeFormat.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/DateTimeParser.h"
+#include "Poco/String.h"
+#include "Poco/UnicodeConverter.h"
+#include "Poco/UTFString.h"
+#include "Poco/UTF8String.h"
+#include "Poco/Any.h"
+#include "Poco/Exception.h"
+#include <vector>
+#include <list>
+#include <deque>
+#include <typeinfo>
+#undef min
+#undef max
+#include <limits>
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+class Var;
+
+
+namespace Impl {
+
+
+bool Foundation_API isJSONString(const Var& any);
+	/// Returns true for values that should be JSON-formatted as string.
+
+
+void Foundation_API appendJSONKey(std::string& val, const Var& any);
+	/// Converts the any to a JSON key (i.e. wraps it into double quotes 
+	/// regardless of the underlying type) and appends it to val.
+
+
+void Foundation_API appendJSONString(std::string& val, const Var& any);
+	/// Converts the any to a JSON string (i.e. wraps it into double quotes) 
+	/// regardless of the underlying type) and appends it to val.
+
+
+void Foundation_API appendJSONValue(std::string& val, const Var& any);
+	/// Converts the any to a JSON value (if underlying type qualifies 
+	/// as string - see isJSONString() - , it is wrapped into double quotes) 
+	/// and appends it to val
+
+
+template <typename C>
+void containerToJSON(C& cont, std::string& val)
+{
+	// Serialize in JSON format. Note: although this is a vector<T>, the code only 
+	// supports vector<Var>. Total specialization is not possible
+	// because of the cyclic dependency between Var and VarHolder
+
+	// JSON format definition: [ n times: elem ',' ], no ',' for last elem
+	val.append("[ ");
+	typename C::const_iterator it = cont.begin();
+	typename C::const_iterator itEnd = cont.end();
+	if (!cont.empty())
+	{
+		appendJSONValue(val, *it);
+		++it;
+	}
+	for (; it != itEnd; ++it)
+	{
+		val.append(", ");
+		appendJSONValue(val, *it);
+	}
+	val.append(" ]");
+}
+
+
+} // namespace Impl
+
+
+class Foundation_API VarHolder
+	/// Interface for a data holder used by the Var class. 
+	/// Provides methods to convert between data types.
+	/// Only data types for which VarHolder specialization exists are supported.
+	/// 
+	/// Provided are specializations for all C++ built-in types with addition of 
+	/// std::string, Poco::UTF16String, DateTime, LocalDateTime, Timestamp, std::vector<Var> and DynamicStruct.
+	///
+	/// Additional types can be supported by adding specializations. When implementing specializations,
+	/// the only condition is that they reside in Poco namespace and implement the pure virtual functions
+	/// clone() and type().
+	///
+	/// Those conversions that are not implemented shall fail back to this base
+	/// class implementation. All the convert() function overloads in this class
+	/// throw BadCastException.
+{
+public:
+	typedef Var ArrayValueType;
+
+	virtual ~VarHolder();
+		/// Destroys the VarHolder.
+
+	virtual VarHolder* clone(Placeholder<VarHolder>* pHolder = 0) const = 0;
+		/// Implementation must implement this function to
+		/// deep-copy the VarHolder.
+		/// 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
+		/// specialization in order to support the conversion.
+
+	virtual void convert(Int16& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(Int32& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(Int64& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(UInt8& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(UInt16& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(UInt32& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(UInt64& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(DateTime& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(LocalDateTime& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(Timestamp& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support 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).
+
+#else
+
+	virtual void convert(long long& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to suport the conversion.
+
+	virtual void convert(unsigned long long & val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to suport the conversion.
+
+#endif
+
+	virtual void convert(bool& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(float& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(double& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(char& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(std::string& val) const;
+		/// Throws BadCastException. Must be overriden in a type
+		/// specialization in order to support the conversion.
+
+	virtual void convert(Poco::UTF16String& val) const;
+	/// Throws BadCastException. Must be overriden in a type
+	/// specialization in order to support the conversion.
+
+	virtual bool isArray() const;
+		/// Returns true.
+
+	virtual bool isVector() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isList() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isDeque() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isStruct() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isInteger() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isSigned() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isNumeric() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isBoolean() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isString() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isDate() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isTime() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual bool isDateTime() const;
+		/// Returns false. Must be properly overriden in a type
+		/// specialization in order to support the diagnostic.
+
+	virtual std::size_t size() const;
+		/// Returns 1 iff Var is not empty or this function overriden.
+
+protected:
+	VarHolder();
+		/// Creates the VarHolder.
+
+	template <typename T>
+	VarHolder* cloneHolder(Placeholder<VarHolder>* 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
+		/// small object optimization is enabled.
+	{
+#ifdef POCO_NO_SOO
+		(void)pVarHolder;
+		return new VarHolderImpl<T>(val);
+#else
+		poco_check_ptr (pVarHolder);
+		if ((sizeof(VarHolderImpl<T>) <= Placeholder<T>::Size::value))
+		{
+			new ((VarHolder*) pVarHolder->holder) VarHolderImpl<T>(val);
+			pVarHolder->setLocal(true);
+			return (VarHolder*) pVarHolder->holder;
+		}
+		else
+		{
+			pVarHolder->pHolder = new VarHolderImpl<T>(val);
+			pVarHolder->setLocal(false);
+			return pVarHolder->pHolder;
+		}
+#endif
+	}
+
+	template <typename F, typename T>
+	void convertToSmaller(const F& from, T& to) const
+		/// This function is meant to convert signed numeric values from
+		/// larger to smaller type. It checks the upper and lower bound and
+		/// if from value is within limits of type T (i.e. check calls do not throw), 
+		/// it is converted.
+	{
+		poco_static_assert (std::numeric_limits<F>::is_specialized);
+		poco_static_assert (std::numeric_limits<T>::is_specialized);
+		poco_static_assert (std::numeric_limits<F>::is_signed);
+		poco_static_assert (std::numeric_limits<T>::is_signed);
+
+		if (std::numeric_limits<F>::is_integer)
+		{
+			checkUpperLimit<F,T>(from); 
+			checkLowerLimit<F,T>(from);
+		}
+		else
+		{
+			checkUpperLimitFloat<F,T>(from); 
+			checkLowerLimitFloat<F,T>(from); 
+		}
+		
+		to = static_cast<T>(from);
+	}
+
+	template <typename F, typename T>
+	void convertToSmallerUnsigned(const F& from, T& to) const
+		/// This function is meant for converting unsigned integral data types,
+		/// from larger to smaller type. Since lower limit is always 0 for unsigned types,
+		/// only the upper limit is checked, thus saving some cycles compared to the signed
+		/// version of the function. If the value to be converted is smaller than
+		/// the maximum value for the target type, the conversion is performed.
+	{
+		poco_static_assert (std::numeric_limits<F>::is_specialized);
+		poco_static_assert (std::numeric_limits<T>::is_specialized);
+		poco_static_assert (!std::numeric_limits<F>::is_signed);
+		poco_static_assert (!std::numeric_limits<T>::is_signed);
+
+		checkUpperLimit<F,T>(from); 
+		to = static_cast<T>(from);
+	}
+
+	template <typename F, typename T>
+	void convertSignedToUnsigned(const F& from, T& to) const
+		/// This function is meant for converting signed integral data types to
+		/// unsigned data types. Negative values can not be converted and if one
+		/// is encountered, RangeException is thrown.
+		/// If upper limit is within the target data type limits, the conversion is performed.
+	{
+		poco_static_assert (std::numeric_limits<F>::is_specialized);
+		poco_static_assert (std::numeric_limits<T>::is_specialized);
+		poco_static_assert (std::numeric_limits<F>::is_signed);
+		poco_static_assert (!std::numeric_limits<T>::is_signed);
+
+		if (from < 0)
+			throw RangeException("Value too small.");
+		checkUpperLimit<F,T>(from); 
+		to = static_cast<T>(from);
+	}
+
+	template <typename F, typename T>
+	void convertSignedFloatToUnsigned(const F& from, T& to) const
+		/// This function is meant for converting floating point data types to
+		/// unsigned integral data types. Negative values can not be converted and if one
+		/// is encountered, RangeException is thrown.
+		/// If upper limit is within the target data type limits, the conversion is performed.
+	{
+		poco_static_assert (std::numeric_limits<F>::is_specialized);
+		poco_static_assert (std::numeric_limits<T>::is_specialized);
+		poco_static_assert (!std::numeric_limits<F>::is_integer);
+		poco_static_assert (std::numeric_limits<T>::is_integer);
+		poco_static_assert (!std::numeric_limits<T>::is_signed);
+
+		if (from < 0)
+			throw RangeException("Value too small.");
+		checkUpperLimitFloat<F,T>(from); 
+		to = static_cast<T>(from);
+	}
+
+	template <typename F, typename T>
+	void convertUnsignedToSigned(const F& from, T& to) const
+		/// This function is meant for converting unsigned integral data types to
+		/// signed integral data types. Negative values can not be converted and if one
+		/// is encountered, RangeException is thrown.
+		/// If upper limit is within the target data type limits, the conversion is performed.
+	{
+		poco_static_assert (std::numeric_limits<F>::is_specialized);
+		poco_static_assert (std::numeric_limits<T>::is_specialized);
+		poco_static_assert (!std::numeric_limits<F>::is_signed);
+		poco_static_assert (std::numeric_limits<T>::is_signed);
+
+		checkUpperLimit<F,T>(from);
+		to = static_cast<T>(from);
+	}
+
+private:
+	template <typename F, typename T>
+	void checkUpperLimit(const F& from) const
+	{
+		if ((sizeof(T) < sizeof(F)) &&
+			(from > static_cast<F>(std::numeric_limits<T>::max())))
+		{
+			throw RangeException("Value too large.");
+		}
+		else
+		if (from > std::numeric_limits<T>::max())
+		{
+			throw RangeException("Value too large.");
+		}
+	}
+
+	template <typename F, typename T>
+	void checkUpperLimitFloat(const F& from) const
+	{
+		if (from > std::numeric_limits<T>::max())
+			throw RangeException("Value too large.");
+	}
+
+	template <typename F, typename T>
+	void checkLowerLimitFloat(const F& from) const
+	{
+		if (from < -std::numeric_limits<T>::max()) 
+			throw RangeException("Value too small.");
+	}
+
+	template <typename F, typename T>
+	void checkLowerLimit(const F& from) const
+	{
+		if (from < std::numeric_limits<T>::min()) 
+			throw RangeException("Value too small.");
+	}
+};
+
+
+//
+// inlines
+//
+
+
+inline void VarHolder::convert(Int8& /*val*/) const
+{
+	throw BadCastException("Can not convert to Int8");
+}
+
+
+inline void VarHolder::convert(Int16& /*val*/) const
+{
+	throw BadCastException("Can not convert to Int16");
+}
+
+
+inline void VarHolder::convert(Int32& /*val*/) const
+{
+	throw BadCastException("Can not convert to Int32");
+}
+
+
+inline void VarHolder::convert(Int64& /*val*/) const
+{
+	throw BadCastException("Can not convert to Int64");
+}
+
+
+inline void VarHolder::convert(UInt8& /*val*/) const
+{
+	throw BadCastException("Can not convert to UInt8");
+}
+
+
+inline void VarHolder::convert(UInt16& /*val*/) const
+{
+	throw BadCastException("Can not convert to UInt16");
+}
+
+
+inline void VarHolder::convert(UInt32& /*val*/) const
+{
+	throw BadCastException("Can not convert to UInt32");
+}
+
+
+inline void VarHolder::convert(UInt64& /*val*/) const
+{
+	throw BadCastException("Can not convert to UInt64");
+}
+
+
+inline void VarHolder::convert(DateTime& /*val*/) const
+{
+	throw BadCastException("Can not convert to DateTime");
+}
+
+
+inline void VarHolder::convert(LocalDateTime& /*val*/) const
+{
+	throw BadCastException("Can not convert to LocalDateTime");
+}
+
+
+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;
+	convert(tmp);
+	val = tmp;
+}
+
+
+inline void VarHolder::convert(unsigned long& val) const
+{
+	UInt32 tmp;
+	convert(tmp);
+	val = tmp;
+}
+
+#else
+
+inline void VarHolder::convert(long long& /*val*/) const
+{
+	throw BadCastException("Can not convert to long long");
+}
+
+
+inline void VarHolder::convert(unsigned long long& /*val*/) const
+{
+	throw BadCastException("Can not convert to unsigned long long");
+}
+
+#endif
+
+inline void VarHolder::convert(bool& /*val*/) const
+{
+	throw BadCastException("Can not convert to bool");
+}
+
+
+inline void VarHolder::convert(float& /*val*/) const
+{
+	throw BadCastException("Can not convert to float");
+}
+
+
+inline void VarHolder::convert(double& /*val*/) const
+{
+	throw BadCastException("Can not convert to double");
+}
+
+
+inline void VarHolder::convert(char& /*val*/) const
+{
+	throw BadCastException("Can not convert to char");
+}
+
+
+inline void VarHolder::convert(std::string& /*val*/) const
+{
+	throw BadCastException("Can not convert to std::string");
+}
+
+
+inline void VarHolder::convert(Poco::UTF16String& /*val*/) const
+{
+	throw BadCastException("Can not convert to Poco::UTF16String");
+}
+
+
+inline bool VarHolder::isArray() const
+{
+	return true;
+}
+
+
+inline bool VarHolder::isVector() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isList() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isDeque() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isStruct() const
+{
+	return false;
+}
+
+inline bool VarHolder::isInteger() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isSigned() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isNumeric() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isBoolean() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isString() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isDate() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isTime() const
+{
+	return false;
+}
+
+
+inline bool VarHolder::isDateTime() const
+{
+	return false;
+}
+
+inline std::size_t VarHolder::size() const
+{
+	return 1u;
+}
+
+
+template <typename T>
+class VarHolderImpl: public VarHolder
+	/// Template based implementation of a VarHolder. 
+	/// This class provides type storage for user-defined types
+	/// that do not have VarHolderImpl specialization.
+	///
+	/// The actual conversion work happens in the template specializations
+	/// of this class.
+	///
+	/// VarHolderImpl throws following exceptions:
+	///		BadCastException (if the requested conversion is not implemented)
+	///		RangeException (if an attempt is made to assign a numeric value outside of the target min/max limits
+	///		SyntaxException (if an attempt is made to convert a string containing non-numeric characters to number)
+	///
+	/// In order to support efficient direct extraction of the held value,
+	/// all specializations must additionally implement a public member function:
+	///
+	///     const T& value() const
+	///
+	/// returning a const reference to the actual stored value.
+{
+public:
+	VarHolderImpl(const T& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(T);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const T& value() const
+	{
+		return _val;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	T _val;
+};
+
+
+template <>
+class VarHolderImpl<Int8>: public VarHolder
+{
+public:
+	VarHolderImpl(Int8 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Int8);
+	}
+
+	void convert(Int8& val) const
+	{
+		val = _val;
+	}
+
+	void convert(Int16& val) const
+	{
+		val = _val;
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = _val;
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val;
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		val = static_cast<char>(_val);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	void convert(Poco::UTF16String& val) const
+	{
+		std::string str = NumberFormatter::format(_val);
+		Poco::UnicodeConverter::convert(str, val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Int8& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<Int8>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<Int8>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<Int8>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	Int8 _val;
+};
+
+
+template <>
+class VarHolderImpl<Int16>: public VarHolder
+{
+public:
+	VarHolderImpl(Int16 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Int16);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		val = _val;
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = _val;
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val;
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	void convert(Poco::UTF16String& val) const
+	{
+		std::string str = NumberFormatter::format(_val);
+		Poco::UnicodeConverter::convert(str, val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const Int16& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<Int16>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<Int16>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<Int16>::is_specialized;
+	}
+
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	Int16 _val;
+};
+
+
+template <>
+class VarHolderImpl<Int32>: public VarHolder
+{
+public:
+	VarHolderImpl(Int32 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(Int32);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = _val;
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val;
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const Int32& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<Int32>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<Int32>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<Int32>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	Int32 _val;
+};
+
+
+template <>
+class VarHolderImpl<Int64>: public VarHolder
+{
+public:
+	VarHolderImpl(Int64 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(Int64);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val;
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	void convert(DateTime& dt) const
+	{
+		dt = Timestamp(_val);
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		ldt = Timestamp(_val);
+	}
+
+	void convert(Timestamp& val) const
+	{
+		val = Timestamp(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const Int64& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<Int64>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<Int64>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<Int64>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	Int64 _val;
+};
+
+
+template <>
+class VarHolderImpl<UInt8>: public VarHolder
+{
+public:
+	VarHolderImpl(UInt8 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(UInt8);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = static_cast<Int32>(_val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = static_cast<Int64>(_val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt16& val) const
+	{
+		val = _val;
+	}
+	
+	void convert(UInt32& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val;
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = static_cast<long long>(_val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val;
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const UInt8& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<UInt8>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<UInt8>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<UInt8>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	UInt8 _val;
+};
+
+
+template <>
+class VarHolderImpl<UInt16>: public VarHolder
+{
+public:
+	VarHolderImpl(UInt16 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(UInt16);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = static_cast<Int64>(_val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		val = _val;
+	}
+	
+	void convert(UInt32& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val;
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = static_cast<long long>(_val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val;
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const UInt16& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<UInt16>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<UInt16>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<UInt16>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	UInt16 _val;
+};
+
+
+template <>
+class VarHolderImpl<UInt32>: public VarHolder
+{
+public:
+	VarHolderImpl(UInt32 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(UInt32);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		val = _val;
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val;
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val;
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const UInt32& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<UInt32>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<UInt32>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<UInt32>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	UInt32 _val;
+};
+
+
+template <>
+class VarHolderImpl<UInt64>: public VarHolder
+{
+public:
+	VarHolderImpl(UInt64 val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(UInt64);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val;
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val;
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	void convert(DateTime& dt) const
+	{
+		Int64 val;
+		convertUnsignedToSigned(_val, val);
+		dt = Timestamp(val);
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		Int64 val;
+		convertUnsignedToSigned(_val, val);
+		ldt = Timestamp(val);
+	}
+
+	void convert(Timestamp& val) const
+	{
+		Int64 tmp;
+		convertUnsignedToSigned(_val, tmp);
+		val = Timestamp(tmp);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const UInt64& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<UInt64>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<UInt64>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<UInt64>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	UInt64 _val;
+};
+
+
+template <>
+class VarHolderImpl<bool>: public VarHolder
+{
+public:
+	VarHolderImpl(bool val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(bool);
+	}
+
+	void convert(Int8& val) const
+	{
+		val = static_cast<Int8>(_val ? 1 : 0);
+	}
+
+	void convert(Int16& val) const
+	{
+		val = static_cast<Int16>(_val ? 1 : 0);
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = static_cast<Int32>(_val ? 1 : 0);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = static_cast<Int64>(_val ? 1 : 0);
+	}
+
+	void convert(UInt8& val) const
+	{
+		val = static_cast<UInt8>(_val ? 1 : 0);
+	}
+
+	void convert(UInt16& val) const
+	{
+		val = static_cast<UInt16>(_val ? 1 : 0);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		val = static_cast<UInt32>(_val ? 1 : 0);
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = static_cast<UInt64>(_val ? 1 : 0);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = static_cast<long long>(_val ? 1 : 0);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = static_cast<unsigned long long>(_val ? 1 : 0);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = _val;
+	}
+
+	void convert(float& val) const
+	{
+		val = (_val ? 1.0f : 0.0f);
+	}
+
+	void convert(double& val) const
+	{
+		val = (_val ? 1.0 : 0.0);
+	}
+
+	void convert(char& val) const
+	{
+		val = static_cast<char>(_val ? 1 : 0);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = (_val ? "true" : "false");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const bool& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<bool>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<bool>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<bool>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return true;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	bool _val;
+};
+
+
+template <>
+class VarHolderImpl<float>: public VarHolder
+{
+public:
+	VarHolderImpl(float val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(float);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = !(_val <= std::numeric_limits<float>::min() && 
+			_val >= -1 * std::numeric_limits<float>::min());
+	}
+
+	void convert(float& val) const
+	{
+		val = _val;
+	}
+
+	void convert(double& val) const
+	{
+		val = _val;
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const float& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<float>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<float>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<float>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	float _val;
+};
+
+
+template <>
+class VarHolderImpl<double>: public VarHolder
+{
+public:
+	VarHolderImpl(double val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(double);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedFloatToUnsigned(_val, val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = !(_val <= std::numeric_limits<double>::min() && 
+			_val >= -1 * std::numeric_limits<double>::min());
+	}
+
+	void convert(float& val) const
+	{
+		double fMin = -1 * std::numeric_limits<float>::max();
+		double fMax = std::numeric_limits<float>::max();
+
+		if (_val < fMin) throw RangeException("Value too small.");
+		if (_val > fMax) throw RangeException("Value too large.");
+
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = _val;
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const double& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<double>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<double>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<double>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	double _val;
+};
+
+
+template <>
+class VarHolderImpl<char>: public VarHolder
+{
+public:
+	VarHolderImpl(char val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(char);
+	}
+
+	void convert(Int8& val) const
+	{
+		val = static_cast<Int8>(_val);
+	}
+
+	void convert(Int16& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = static_cast<UInt8>(_val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = static_cast<long long>(_val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = static_cast<unsigned long long>(_val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		val = (_val != '\0');
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		val = _val;
+	}
+
+	void convert(std::string& val) const
+	{
+		val = std::string(1, _val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const char& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<char>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<char>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<char>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	char _val;
+};
+
+
+template <>
+class VarHolderImpl<std::string>: public VarHolder
+{
+public:
+	VarHolderImpl(const char* pVal): _val(pVal)
+	{
+	}
+
+	VarHolderImpl(const std::string& val) : _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(std::string);
+	}
+
+	void convert(Int8& val) const
+	{
+		int v = NumberParser::parse(_val);
+		convertToSmaller(v, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		int v = NumberParser::parse(_val);
+		convertToSmaller(v, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = NumberParser::parse(_val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = NumberParser::parse64(_val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		unsigned int v = NumberParser::parseUnsigned(_val);
+		convertToSmallerUnsigned(v, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		unsigned int v = NumberParser::parseUnsigned(_val);
+		convertToSmallerUnsigned(v, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		val = NumberParser::parseUnsigned(_val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = NumberParser::parseUnsigned64(_val);
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = NumberParser::parse64(_val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = NumberParser::parseUnsigned64(_val);
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		if (_val.empty())
+		{
+			val = false;
+			return;
+		}
+
+		static const std::string VAL_FALSE("false");
+		static const std::string VAL_INT_FALSE("0");
+		val = (_val != VAL_INT_FALSE &&
+			(icompare(_val, VAL_FALSE) != 0));
+	}
+
+	void convert(float& val) const
+	{
+		double v = NumberParser::parseFloat(_val);
+		convertToSmaller(v, val);
+	}
+
+	void convert(double& val) const
+	{
+		val = NumberParser::parseFloat(_val);
+	}
+
+	void convert(char& val) const
+	{
+		if (_val.empty())
+			val = '\0';
+		else
+			val = _val[0];
+	}
+
+	void convert(std::string& val) const
+	{
+		val = _val;
+	}
+
+	void convert(Poco::UTF16String& val) const
+	{
+		Poco::UnicodeConverter::convert(_val, val);
+	}
+
+	void convert(DateTime& val) const
+	{
+		int tzd = 0;
+		if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, _val, val, tzd))
+			throw BadCastException("string -> DateTime");
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		int tzd = 0;
+		DateTime tmp;
+		if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, _val, tmp, tzd))
+			throw BadCastException("string -> LocalDateTime");
+
+		ldt = LocalDateTime(tzd, tmp, false);
+	}
+
+	void convert(Timestamp& ts) const
+	{
+		int tzd = 0;
+		DateTime tmp;
+		if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, _val, tmp, tzd))
+			throw BadCastException("string -> Timestamp");
+
+		ts = tmp.timestamp();
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const std:: string& value() const
+	{
+		return _val;
+	}
+
+	bool isString() const
+	{
+		return true;
+	}
+
+	std::size_t size() const
+	{
+		return _val.length();
+	}
+
+	char& operator[](std::string::size_type n)
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("String index out of range");
+	}
+
+	const char& operator[](std::string::size_type n) const
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("String index out of range");
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	std::string _val;
+};
+
+
+template <>
+class VarHolderImpl<UTF16String>: public VarHolder
+{
+public:
+	VarHolderImpl(const char* pVal) : _val(Poco::UnicodeConverter::to<UTF16String>(pVal))
+	{
+	}
+
+	VarHolderImpl(const Poco::UTF16String& val) : _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(Poco::UTF16String);
+	}
+
+	void convert(Int8& val) const
+	{
+		int v = NumberParser::parse(toStdString());
+		convertToSmaller(v, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		int v = NumberParser::parse(toStdString());
+		convertToSmaller(v, val);
+	}
+
+	void convert(Int32& val) const
+	{
+		val = NumberParser::parse(toStdString());
+	}
+
+	void convert(Int64& val) const
+	{
+		val = NumberParser::parse64(toStdString());
+	}
+
+	void convert(UInt8& val) const
+	{
+		unsigned int v = NumberParser::parseUnsigned(toStdString());
+		convertToSmallerUnsigned(v, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		unsigned int v = NumberParser::parseUnsigned(toStdString());
+		convertToSmallerUnsigned(v, val);
+	}
+
+	void convert(UInt32& val) const
+	{
+		val = NumberParser::parseUnsigned(toStdString());
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = NumberParser::parseUnsigned64(toStdString());
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = NumberParser::parse64(toStdString());
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = NumberParser::parseUnsigned64(toStdString());
+	}
+
+#endif
+
+	void convert(bool& val) const
+	{
+		static const std::string VAL_FALSE("false");
+		static const std::string VAL_INT_FALSE("0");
+
+		if (_val.empty()) val = false;
+
+		std::string str;
+		UnicodeConverter::convert(_val, str);
+		val = (str != VAL_INT_FALSE &&
+			(icompare(str, VAL_FALSE) != 0));
+	}
+
+	void convert(float& val) const
+	{
+		double v = NumberParser::parseFloat(toStdString());
+		convertToSmaller(v, val);
+	}
+
+	void convert(double& val) const
+	{
+		val = NumberParser::parseFloat(toStdString());
+	}
+
+	void convert(char& val) const
+	{
+		if (_val.empty())
+			val = '\0';
+		else
+		{
+			std::string s;
+			UnicodeConverter::convert(_val, s);
+			val = s[0];
+		}
+	}
+
+	void convert(Poco::UTF16String& val) const
+	{
+		val = _val;
+	}
+
+	void convert(std::string& val) const
+	{
+		UnicodeConverter::convert(_val, val);
+	}
+
+	void convert(DateTime& val) const
+	{
+		int tzd = 0;
+		if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, toStdString(), val, tzd))
+			throw BadCastException("string -> DateTime");
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		int tzd = 0;
+		DateTime tmp;
+		if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, toStdString(), tmp, tzd))
+			throw BadCastException("string -> LocalDateTime");
+
+		ldt = LocalDateTime(tzd, tmp, false);
+	}
+
+	void convert(Timestamp& ts) const
+	{
+		int tzd = 0;
+		DateTime tmp;
+		if (!DateTimeParser::tryParse(DateTimeFormat::ISO8601_FORMAT, toStdString(), tmp, tzd))
+			throw BadCastException("string -> Timestamp");
+
+		ts = tmp.timestamp();
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const Poco::UTF16String& value() const
+	{
+		return _val;
+	}
+
+	bool isString() const
+	{
+		return true;
+	}
+
+	std::size_t size() const
+	{
+		return _val.length();
+	}
+
+	UTF16Char& operator[](Poco::UTF16String::size_type n)
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("String index out of range");
+	}
+
+	const UTF16Char& operator[](Poco::UTF16String::size_type n) const
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("String index out of range");
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	std::string toStdString() const
+	{
+		std::string str;
+		UnicodeConverter::convert(_val, str);
+		return str;
+	}
+
+	Poco::UTF16String _val;
+};
+
+
+#ifndef POCO_LONG_IS_64_BIT
+
+
+template <>
+class VarHolderImpl<long>: public VarHolder
+{
+public:
+	VarHolderImpl(long val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(long);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		val = static_cast<Int32>(_val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = static_cast<Int64>(_val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const long& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<long>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<long>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<long>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	long _val;
+};
+
+
+template <>
+class VarHolderImpl<unsigned long>: public VarHolder
+{
+public:
+	VarHolderImpl(unsigned long val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(unsigned long);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+	
+	void convert(Int32& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+	
+	void convert(UInt32& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = static_cast<UInt64>(_val);
+	}
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const unsigned long& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<unsigned long>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<unsigned long>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<unsigned long>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	unsigned long _val;
+};
+
+
+#else // if defined (POCO_LONG_IS_64_BIT)
+
+
+template <>
+class VarHolderImpl<long long>: public VarHolder
+{
+public:
+	VarHolderImpl(long long val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(long long);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int32& val) const
+	{
+		convertToSmaller(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = static_cast<Int64>(_val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt32& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(long long& val) const
+	{
+		val = _val;
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		convertSignedToUnsigned(_val, val);
+	}
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const long long& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<long long>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<long long>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<long long>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	long long _val;
+};
+
+
+template <>
+class VarHolderImpl<unsigned long long>: public VarHolder
+{
+public:
+	VarHolderImpl(unsigned long long val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(unsigned long long);
+	}
+
+	void convert(Int8& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int16& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int32& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(Int64& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(UInt8& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt16& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt32& val) const
+	{
+		convertToSmallerUnsigned(_val, val);
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = static_cast<UInt64>(_val);
+	}
+
+	void convert(long long& val) const
+	{
+		convertUnsignedToSigned(_val, val);
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val;
+	}
+
+	void convert(bool& val) const
+	{
+		val = (_val != 0);
+	}
+
+	void convert(float& val) const
+	{
+		val = static_cast<float>(_val);
+	}
+
+	void convert(double& val) const
+	{
+		val = static_cast<double>(_val);
+	}
+
+	void convert(char& val) const
+	{
+		UInt8 tmp;
+		convert(tmp);
+		val = static_cast<char>(tmp);
+	}
+
+	void convert(std::string& val) const
+	{
+		val = NumberFormatter::format(_val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const unsigned long long& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return std::numeric_limits<unsigned long long>::is_integer;
+	}
+
+	bool isSigned() const
+	{
+		return std::numeric_limits<unsigned long long>::is_signed;
+	}
+
+	bool isNumeric() const
+	{
+		return std::numeric_limits<unsigned long long>::is_specialized;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	unsigned long long _val;
+};
+
+
+#endif // 64bit
+
+
+template <typename T>
+class VarHolderImpl<std::vector<T> >: public VarHolder
+{
+public:
+	VarHolderImpl(const std::vector<T>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(std::vector<T>);
+	}
+
+	void convert(std::string& val) const
+	{
+		Impl::containerToJSON(_val, val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const std::vector<T>& value() const
+	{
+		return _val;
+	}
+
+	bool isVector() const
+	{
+		return true;
+	}
+
+	std::size_t size() const
+	{
+		return _val.size();
+	}
+
+	T& operator[](typename std::vector<T>::size_type n)
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("List index out of range");
+	}
+
+	const T& operator[](typename std::vector<T>::size_type n) const
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("List index out of range");
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	std::vector<T> _val;
+};
+
+
+template <typename T>
+class VarHolderImpl<std::list<T> >: public VarHolder
+{
+public:
+	VarHolderImpl(const std::list<T>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(std::list<T>);
+	}
+
+	void convert(std::string& val) const
+	{
+		Impl::containerToJSON(_val, val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const std::list<T>& value() const
+	{
+		return _val;
+	}
+
+	bool isList() const
+	{
+		return true;
+	}
+
+	std::size_t size() const
+	{
+		return _val.size();
+	}
+
+	T& operator[](typename std::list<T>::size_type n)
+	{
+		if (n >= size())
+			throw RangeException("List index out of range");
+
+		typename std::list<T>::size_type counter = 0;
+		typename std::list<T>::iterator it = _val.begin();
+		for (; counter < n; ++counter) ++it;
+
+		return *it;
+	}
+
+	const T& operator[](typename std::list<T>::size_type n) const
+	{
+		if (n >= size())
+			throw RangeException("List index out of range");
+
+		typename std::list<T>::size_type counter = 0;
+		typename std::list<T>::const_iterator it = _val.begin();
+		for (; counter < n; ++counter) ++it;
+
+		return *it;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	std::list<T> _val;
+};
+
+
+template <typename T>
+class VarHolderImpl<std::deque<T> >: public VarHolder
+{
+public:
+	VarHolderImpl(const std::deque<T>& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(std::deque<T>);
+	}
+
+	void convert(std::string& val) const
+	{
+		Impl::containerToJSON(_val, val);
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const std::deque<T>& value() const
+	{
+		return _val;
+	}
+
+	bool isDeque() const
+	{
+		return true;
+	}
+
+	std::size_t size() const
+	{
+		return _val.size();
+	}
+
+	T& operator[](typename std::deque<T>::size_type n)
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("List index out of range");
+	}
+
+	const T& operator[](typename std::deque<T>::size_type n) const
+	{
+		if (n < size()) return _val.operator[](n);
+
+		throw RangeException("List index out of range");
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	std::deque<T> _val;
+};
+
+
+template <>
+class VarHolderImpl<DateTime>: public VarHolder
+{
+public:
+	VarHolderImpl(const DateTime& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(DateTime);
+	}
+
+	void convert(Int8& /*val*/) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int16& /*val*/) const
+	{
+		throw BadCastException();
+	}
+	
+	void convert(Int32& /*val*/) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+#endif
+
+	void convert(std::string& val) const
+	{
+		val = DateTimeFormatter::format(_val, Poco::DateTimeFormat::ISO8601_FORMAT);
+	}
+
+	void convert(DateTime& val) const
+	{
+		val = _val;
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		ldt = _val.timestamp();
+	}
+
+	void convert(Timestamp& ts) const
+	{
+		ts = _val.timestamp();
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const DateTime& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+	bool isDate() const
+	{
+		return true;
+	}
+
+	bool isTime() const
+	{
+		return true;
+	}
+
+	bool isDateTime() const
+	{
+		return true;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	DateTime _val;
+};
+
+
+template <>
+class VarHolderImpl<LocalDateTime>: public VarHolder
+{
+public:
+	VarHolderImpl(const LocalDateTime& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(LocalDateTime);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val.timestamp().epochMicroseconds();
+	}
+
+#endif
+
+	void convert(std::string& val) const
+	{
+		val = DateTimeFormatter::format(_val, Poco::DateTimeFormat::ISO8601_FORMAT);
+	}
+
+	void convert(DateTime& val) const
+	{
+		val = _val.timestamp();
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		ldt = _val;
+	}
+
+	void convert(Timestamp& ts) const
+	{
+		ts = _val.timestamp();
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const LocalDateTime& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+	bool isDate() const
+	{
+		return true;
+	}
+
+	bool isTime() const
+	{
+		return true;
+	}
+
+	bool isDateTime() const
+	{
+		return true;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	LocalDateTime _val;
+};
+
+
+template <>
+class VarHolderImpl<Timestamp>: public VarHolder
+{
+public:
+	VarHolderImpl(const Timestamp& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+	
+	const std::type_info& type() const
+	{
+		return typeid(Timestamp);
+	}
+
+	void convert(Int64& val) const
+	{
+		val = _val.epochMicroseconds();
+	}
+
+	void convert(UInt64& val) const
+	{
+		val = _val.epochMicroseconds();
+	}
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	void convert(long long& val) const
+	{
+		val = _val.epochMicroseconds();
+	}
+
+	void convert(unsigned long long& val) const
+	{
+		val = _val.epochMicroseconds();
+	}
+
+#endif
+
+	void convert(std::string& val) const
+	{
+		val = DateTimeFormatter::format(_val, Poco::DateTimeFormat::ISO8601_FORMAT);
+	}
+
+	void convert(DateTime& val) const
+	{
+		val = _val;
+	}
+
+	void convert(LocalDateTime& ldt) const
+	{
+		ldt = _val;
+	}
+
+	void convert(Timestamp& ts) const
+	{
+		ts = _val;
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+	
+	const Timestamp& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isStruct() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isBoolean() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+	bool isDate() const
+	{
+		return true;
+	}
+
+	bool isTime() const
+	{
+		return true;
+	}
+
+	bool isDateTime() const
+	{
+		return true;
+	}
+
+private:
+	VarHolderImpl();
+	VarHolderImpl(const VarHolderImpl&);
+	VarHolderImpl& operator = (const VarHolderImpl&);
+
+	Timestamp _val;
+};
+
+
+typedef std::vector<Var> Vector;
+typedef std::deque<Var>  Deque;
+typedef std::list<Var>   List;
+typedef Vector           Array;
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // Foundation_VarHolder_INCLUDED
diff --git a/Poco/Dynamic/VarIterator.h b/Poco/Dynamic/VarIterator.h
new file mode 100644
index 0000000..a91bb3a
--- /dev/null
+++ b/Poco/Dynamic/VarIterator.h
@@ -0,0 +1,150 @@
+//
+// VarIterator.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  VarIterator
+//
+// Definition of the VarIterator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_VarIterator_INCLUDED
+#define Foundation_VarIterator_INCLUDED
+
+
+#include "Poco/Exception.h"
+#include <iterator>
+#include <algorithm>
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+class Var;
+
+
+class Foundation_API VarIterator
+	/// VarIterator class.
+{
+public:
+	typedef std::bidirectional_iterator_tag iterator_category;
+	typedef Var                             value_type;
+	typedef std::ptrdiff_t                  difference_type;
+	typedef Var*                            pointer;
+	typedef Var&                            reference;
+
+	static const std::size_t POSITION_END;
+		/// End position indicator.
+
+	VarIterator(Var* pVar, bool positionEnd);
+		/// Creates the VarIterator and positions it at the end of
+		/// the recordset if positionEnd is true. Otherwise, it is
+		/// positioned at the beginning.
+
+	VarIterator(const VarIterator& other);
+		/// Creates a copy of other VarIterator.
+
+	~VarIterator();
+		/// Destroys the VarIterator.
+
+	VarIterator& operator = (const VarIterator& other);
+		/// Assigns the other VarIterator.
+
+	bool operator == (const VarIterator& other) const;
+		/// Equality operator.
+
+	bool operator != (const VarIterator& other) const;
+		/// Inequality operator.
+
+	Var& operator * () const;
+		/// Returns value at the current position.
+
+	Var* operator -> () const;
+		/// Returns pointer to the value at current position.
+
+	const VarIterator& operator ++ () const;
+		/// Advances by one position and returns current position.
+
+	VarIterator operator ++ (int) const;
+		/// Advances by one position and returns copy of the iterator with 
+		/// previous current position.
+
+	const VarIterator& operator -- () const;
+		/// Goes back by one position and returns copy of the iterator with 
+		/// previous current position.
+
+	VarIterator operator -- (int) const;
+		/// Goes back by one position and returns previous current position.
+
+	VarIterator operator + (std::size_t diff) const;
+		/// Returns a copy the VarIterator advanced by diff positions.
+
+	VarIterator operator - (std::size_t diff) const;
+		/// Returns a copy the VarIterator backed by diff positions.
+		/// Throws RangeException if diff is larger than current position.
+
+	void swap(VarIterator& other);
+		/// Swaps the VarIterator with another one.
+
+private:
+	VarIterator();
+
+	void increment() const;
+		/// Increments the iterator position by one. 
+		/// Throws RangeException if position is out of range.
+
+	void decrement() const;
+		/// Decrements the iterator position by one. 
+		/// Throws RangeException if position is out of range.
+
+	void setPosition(std::size_t pos) const;
+		/// Sets the iterator position. 
+		/// Throws RangeException if position is out of range.
+
+	Var*                _pVar;
+	mutable std::size_t _position;
+
+	friend class Var;
+};
+
+
+///
+/// inlines
+///
+
+
+inline bool VarIterator::operator == (const VarIterator& other) const
+{
+	return _pVar == other._pVar && _position == other._position;
+}
+
+
+inline bool VarIterator::operator != (const VarIterator& other) const
+{
+	return _pVar != other._pVar || _position != other._position;
+}
+
+
+} } // namespace Poco::Dynamic
+
+
+namespace std
+{
+	template<>
+	inline void swap<Poco::Dynamic::VarIterator>(Poco::Dynamic::VarIterator& s1, 
+		Poco::Dynamic::VarIterator& s2)
+		/// Full template specialization of std:::swap for VarIterator
+	{
+		s1.swap(s2);
+	}
+}
+
+
+#endif // Foundation_VarIterator_INCLUDED
diff --git a/Poco/DynamicAny.h b/Poco/DynamicAny.h
new file mode 100644
index 0000000..214a296
--- /dev/null
+++ b/Poco/DynamicAny.h
@@ -0,0 +1,24 @@
+//
+// DynamicAny.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Var
+//
+// Forward header for Var class to maintain backward compatibility.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DynamicAny_INCLUDED
+#define Foundation_DynamicAny_INCLUDED
+
+//@ deprecated
+#include "Poco/Dynamic/Var.h"
+
+
+#endif // Foundation_DynamicAny_INCLUDED
diff --git a/Poco/DynamicAnyHolder.h b/Poco/DynamicAnyHolder.h
new file mode 100644
index 0000000..4400af3
--- /dev/null
+++ b/Poco/DynamicAnyHolder.h
@@ -0,0 +1,24 @@
+//
+// DynamicAnyHolder.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  VarHolder
+//
+// Forward header for VarHolder class to maintain backward compatibility
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DynamicAnyHolder_INCLUDED
+#define Foundation_DynamicAnyHolder_INCLUDED
+
+//@ deprecated
+#include "Poco/Dynamic/VarHolder.h"
+
+
+#endif // Foundation_DynamicAnyHolder_INCLUDED
diff --git a/Poco/DynamicFactory.h b/Poco/DynamicFactory.h
new file mode 100644
index 0000000..5f94204
--- /dev/null
+++ b/Poco/DynamicFactory.h
@@ -0,0 +1,141 @@
+//
+// DynamicFactory.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  DynamicFactory
+//
+// Definition of the DynamicFactory class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DynamicFactory_INCLUDED
+#define Foundation_DynamicFactory_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Instantiator.h"
+#include "Poco/Exception.h"
+#include "Poco/Mutex.h"
+#include <map>
+#include <memory>
+
+
+namespace Poco {
+
+
+template <class Base>
+class DynamicFactory
+	/// A factory that creates objects by class name.
+{
+public:
+	typedef AbstractInstantiator<Base> AbstractFactory;
+
+	DynamicFactory()
+		/// Creates the DynamicFactory.
+	{
+	}
+
+	~DynamicFactory()
+		/// Destroys the DynamicFactory and deletes the instantiators for 
+		/// all registered classes.
+	{
+		for (typename FactoryMap::iterator it = _map.begin(); it != _map.end(); ++it)
+		{
+			delete it->second;
+		}
+	}
+	
+	Base* createInstance(const std::string& className) const
+		/// Creates a new instance of the class with the given name.
+		/// The class must have been registered with registerClass.
+		/// If the class name is unknown, a NotFoundException is thrown.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		typename FactoryMap::const_iterator it = _map.find(className);
+		if (it != _map.end())
+			return it->second->createInstance();
+		else
+			throw NotFoundException(className);
+	}
+	
+	template <class C> 
+	void registerClass(const std::string& className)
+		/// Registers the instantiator for the given class with the DynamicFactory.
+		/// The DynamicFactory takes ownership of the instantiator and deletes
+		/// it when it's no longer used.
+		/// If the class has already been registered, an ExistsException is thrown
+		/// and the instantiator is deleted.
+	{
+		registerClass(className, new Instantiator<C, Base>);
+	}
+	
+	void registerClass(const std::string& className, AbstractFactory* pAbstractFactory)
+		/// Registers the instantiator for the given class with the DynamicFactory.
+		/// The DynamicFactory takes ownership of the instantiator and deletes
+		/// it when it's no longer used.
+		/// If the class has already been registered, an ExistsException is thrown
+		/// and the instantiator is deleted.
+	{
+		poco_check_ptr (pAbstractFactory);
+
+		FastMutex::ScopedLock lock(_mutex);
+
+#ifndef POCO_ENABLE_CPP11
+		std::auto_ptr<AbstractFactory> ptr(pAbstractFactory);
+#else
+		std::unique_ptr<AbstractFactory> ptr(pAbstractFactory);
+#endif // POCO_ENABLE_CPP11
+
+		typename FactoryMap::iterator it = _map.find(className);
+		if (it == _map.end())
+			_map[className] = ptr.release();
+		else
+			throw ExistsException(className);
+	}
+	
+	void unregisterClass(const std::string& className)
+		/// Unregisters the given class and deletes the instantiator
+		/// for the class.
+		/// Throws a NotFoundException if the class has not been registered.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		typename FactoryMap::iterator it = _map.find(className);
+		if (it != _map.end())
+		{
+			delete it->second;
+			_map.erase(it);
+		}
+		else throw NotFoundException(className);
+	}
+	
+	bool isClass(const std::string& className) const
+		/// Returns true iff the given class has been registered.
+	{
+		FastMutex::ScopedLock lock(_mutex);
+
+		return _map.find(className) != _map.end();
+	}
+
+private:
+	DynamicFactory(const DynamicFactory&);
+	DynamicFactory& operator = (const DynamicFactory&);
+
+	typedef std::map<std::string, AbstractFactory*> FactoryMap;
+	
+	FactoryMap _map;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_DynamicFactory_INCLUDED
diff --git a/Poco/DynamicStruct.h b/Poco/DynamicStruct.h
new file mode 100644
index 0000000..1f0fb56
--- /dev/null
+++ b/Poco/DynamicStruct.h
@@ -0,0 +1,24 @@
+//
+// DynamicStruct.h
+//
+// Library: Foundation
+// Package: Dynamic
+// Module:  Struct
+//
+// Forward header for Struct class to maintain backward compatibility.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_DynamicStruct_INCLUDED
+#define Foundation_DynamicStruct_INCLUDED
+
+//@ deprecated
+#include "Poco/Dynamic/Struct.h"
+
+
+#endif // Foundation_DynamicStruct_INCLUDED
diff --git a/Poco/Encodings.h b/Poco/Encodings.h
new file mode 100644
index 0000000..7f324d2
--- /dev/null
+++ b/Poco/Encodings.h
@@ -0,0 +1,73 @@
+//
+// Encodings.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Encodings
+//
+// Basic definitions for the Poco Encodings library.
+// This file must be the first file included by every other Encodings
+// header file.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Encodings_Encodings_INCLUDED
+#define Encodings_Encodings_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Encodings_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Encodings_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(Encodings_EXPORTS)
+		#define Encodings_API __declspec(dllexport)
+	#else
+		#define Encodings_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Encodings_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Encodings_API __attribute__ ((visibility ("default")))
+	#else
+		#define Encodings_API
+	#endif
+#endif
+
+
+//
+// Automatically link Encodings library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Encodings_EXPORTS)
+		#pragma comment(lib, "PocoEncodings" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+namespace Poco {
+
+
+void Encodings_API registerExtraEncodings();
+	/// Registers the character encodings from the Encodings library
+	/// with the TextEncoding class.
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Encodings_INCLUDED
diff --git a/Poco/Environment.h b/Poco/Environment.h
new file mode 100644
index 0000000..a422109
--- /dev/null
+++ b/Poco/Environment.h
@@ -0,0 +1,123 @@
+//
+// Environment.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Environment
+//
+// Definition of the Environment class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_INCLUDED
+#define Foundation_Environment_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Environment
+	/// This class provides access to environment variables
+	/// and some general system information.
+{
+public:
+	typedef UInt8 NodeId[6]; /// Ethernet address.
+
+	static std::string get(const std::string& name);
+		/// Returns the value of the environment variable
+		/// with the given name. Throws a NotFoundException
+		/// if the variable does not exist.
+
+	static std::string get(const std::string& name, const std::string& defaultValue);
+		/// Returns the value of the environment variable
+		/// with the given name. If the environment variable
+		/// is undefined, returns defaultValue instead.
+
+	static bool has(const std::string& name);
+		/// Returns true iff an environment variable
+		/// with the given name is defined.
+
+	static void set(const std::string& name, const std::string& value);
+		/// Sets the environment variable with the given name
+		/// to the given value.
+
+	static std::string osName();
+		/// Returns the operating system name.
+
+	static std::string osDisplayName();
+		/// Returns the operating system name in a
+		/// "user-friendly" way.
+		///
+		/// Currently this is only implemented for
+		/// Windows. There it will return names like
+		/// "Windows XP" or "Windows 7/Server 2008 SP2".
+		/// On other platforms, returns the same as
+		/// osName().
+
+	static std::string osVersion();
+		/// Returns the operating system version.
+
+	static std::string osArchitecture();
+		/// Returns the operating system architecture.
+
+	static std::string nodeName();
+		/// Returns the node (or host) name.
+
+	static void nodeId(NodeId& id);
+		/// Returns the Ethernet address of the first Ethernet
+		/// adapter found on the system.
+		///
+		/// Throws a SystemException if no Ethernet adapter is available.
+
+	static std::string nodeId();
+		/// Returns the Ethernet address (format "xx:xx:xx:xx:xx:xx")
+		/// of the first Ethernet adapter found on the system.
+		///
+		/// Throws a SystemException if no Ethernet adapter is available.
+
+	static unsigned processorCount();
+		/// Returns the number of processors installed in the system.
+		///
+		/// If the number of processors cannot be determined, returns 1.
+
+	static Poco::UInt32 libraryVersion();
+		/// Returns the POCO C++ Libraries version as a hexadecimal
+		/// number in format 0xAABBCCDD, where
+		///    - AA is the major version number,
+		///    - BB is the minor version number,
+		///    - CC is the revision number, and
+		///    - DD is the patch level number.
+		///
+		/// Some patch level ranges have special meanings:
+		///    - Dx mark development releases,
+		///    - Ax mark alpha releases, and
+		///    - Bx mark beta releases.
+
+	static Poco::Int32 os();
+		/// Return the operating system as defined
+		/// in the include Foundation/Platform.h (POCO_OS)
+
+	static Poco::Int32 arch();
+		/// Return the underlying cpu architecture that runs this operating system
+		/// as defined in Foundation/Platform (POCO_ARCH)
+
+	static bool isUnix();
+		/// Return true if the operating system belongs to the Linux family
+
+	static bool isWindows();
+		/// Return true if the operating system belongs to the Windows family
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_INCLUDED
diff --git a/Poco/Environment_UNIX.h b/Poco/Environment_UNIX.h
new file mode 100644
index 0000000..d6ae543
--- /dev/null
+++ b/Poco/Environment_UNIX.h
@@ -0,0 +1,56 @@
+//
+// Environment_UNIX.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Environment
+//
+// Definition of the EnvironmentImpl class for Unix.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_UNIX_INCLUDED
+#define Foundation_Environment_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Foundation_API EnvironmentImpl
+{
+public:
+	typedef UInt8 NodeId[6]; /// Ethernet address.
+
+	static std::string getImpl(const std::string& name);	
+	static bool hasImpl(const std::string& name);	
+	static void setImpl(const std::string& name, const std::string& value);
+	static std::string osNameImpl();
+	static std::string osDisplayNameImpl();
+	static std::string osVersionImpl();
+	static std::string osArchitectureImpl();
+	static std::string nodeNameImpl();
+	static void nodeIdImpl(NodeId& id);
+	static unsigned processorCountImpl();
+
+private:
+	typedef std::map<std::string, std::string> StringMap;
+	
+	static StringMap _map;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_UNIX_INCLUDED
diff --git a/Poco/Environment_VX.h b/Poco/Environment_VX.h
new file mode 100644
index 0000000..8eb178d
--- /dev/null
+++ b/Poco/Environment_VX.h
@@ -0,0 +1,56 @@
+//
+// Environment_VX.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Environment
+//
+// Definition of the EnvironmentImpl class for VxWorks.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_VX_INCLUDED
+#define Foundation_Environment_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Foundation_API EnvironmentImpl
+{
+public:
+	typedef UInt8 NodeId[6]; /// Ethernet address.
+
+	static std::string getImpl(const std::string& name);	
+	static bool hasImpl(const std::string& name);	
+	static void setImpl(const std::string& name, const std::string& value);
+	static std::string osNameImpl();
+	static std::string osDisplayNameImpl();
+	static std::string osVersionImpl();
+	static std::string osArchitectureImpl();
+	static std::string nodeNameImpl();
+	static void nodeIdImpl(NodeId& id);
+	static unsigned processorCountImpl();
+
+private:
+	typedef std::map<std::string, std::string> StringMap;
+	
+	static StringMap _map;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_VX_INCLUDED
diff --git a/Poco/Environment_WIN32.h b/Poco/Environment_WIN32.h
new file mode 100644
index 0000000..bfac7c5
--- /dev/null
+++ b/Poco/Environment_WIN32.h
@@ -0,0 +1,48 @@
+//
+// Environment_WIN32.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Environment
+//
+// Definition of the EnvironmentImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_WIN32_INCLUDED
+#define Foundation_Environment_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EnvironmentImpl
+{
+public:
+	typedef UInt8 NodeId[6]; /// Ethernet address.
+
+	static std::string getImpl(const std::string& name);	
+	static bool hasImpl(const std::string& name);	
+	static void setImpl(const std::string& name, const std::string& value);
+	static std::string osNameImpl();
+	static std::string osDisplayNameImpl();
+	static std::string osVersionImpl();
+	static std::string osArchitectureImpl();
+	static std::string nodeNameImpl();
+	static void nodeIdImpl(NodeId& id);
+	static unsigned processorCountImpl();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_WIN32_INCLUDED
diff --git a/Poco/Environment_WIN32U.h b/Poco/Environment_WIN32U.h
new file mode 100644
index 0000000..b54afb2
--- /dev/null
+++ b/Poco/Environment_WIN32U.h
@@ -0,0 +1,48 @@
+//
+// Environment_WIN32U.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Environment
+//
+// Definition of the EnvironmentImpl class for WIN32.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_WIN32U_INCLUDED
+#define Foundation_Environment_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EnvironmentImpl
+{
+public:
+	typedef UInt8 NodeId[6]; /// Ethernet address.
+
+	static std::string getImpl(const std::string& name);	
+	static bool hasImpl(const std::string& name);	
+	static void setImpl(const std::string& name, const std::string& value);
+	static std::string osNameImpl();	
+	static std::string osDisplayNameImpl();
+	static std::string osVersionImpl();
+	static std::string osArchitectureImpl();
+	static std::string nodeNameImpl();
+	static void nodeIdImpl(NodeId& id);
+	static unsigned processorCountImpl();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_WIN32U_INCLUDED
diff --git a/Poco/Environment_WINCE.h b/Poco/Environment_WINCE.h
new file mode 100644
index 0000000..0c92bc5
--- /dev/null
+++ b/Poco/Environment_WINCE.h
@@ -0,0 +1,59 @@
+//
+// Environment_WINCE.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Environment
+//
+// Definition of the EnvironmentImpl class for WINCE.
+//
+// Copyright (c) 2009-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Environment_WINCE_INCLUDED
+#define Foundation_Environment_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EnvironmentImpl
+{
+public:
+	typedef UInt8 NodeId[6]; /// Ethernet address.
+
+	static std::string getImpl(const std::string& name);	
+	static bool hasImpl(const std::string& name);	
+	static void setImpl(const std::string& name, const std::string& value);
+	static std::string osNameImpl();	
+	static std::string osDisplayNameImpl();
+	static std::string osVersionImpl();
+	static std::string osArchitectureImpl();
+	static std::string nodeNameImpl();
+	static void nodeIdImpl(NodeId& id);
+	static unsigned processorCountImpl();
+	
+private:
+	static bool envVar(const std::string& name, std::string* value);
+	
+	static const std::string TEMP;
+	static const std::string TMP;
+	static const std::string HOMEPATH;
+	static const std::string COMPUTERNAME;
+	static const std::string OS;
+	static const std::string NUMBER_OF_PROCESSORS;
+	static const std::string PROCESSOR_ARCHITECTURE;	
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Environment_WINCE_INCLUDED
diff --git a/Poco/Error.h b/Poco/Error.h
new file mode 100644
index 0000000..935ee22
--- /dev/null
+++ b/Poco/Error.h
@@ -0,0 +1,52 @@
+//
+// Error.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Error
+//
+// Definition of the Error class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Error_INCLUDED
+#define Foundation_Error_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Error
+	/// The Error class provides utility functions
+	/// for error reporting.
+{
+public:
+
+#ifdef POCO_OS_FAMILY_WINDOWS
+	static DWORD last();
+		/// Utility function returning the last error.
+
+	static std::string getMessage(DWORD errorCode);
+		/// Utility function translating numeric error code to string.
+#else
+	static int last();
+		/// Utility function returning the last error.
+
+	static std::string getMessage(int errorCode);
+		/// Utility function translating numeric error code to string.
+#endif
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Error_INCLUDED
diff --git a/Poco/ErrorHandler.h b/Poco/ErrorHandler.h
new file mode 100644
index 0000000..a3eea3b
--- /dev/null
+++ b/Poco/ErrorHandler.h
@@ -0,0 +1,120 @@
+//
+// ErrorHandler.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ErrorHandler
+//
+// Definition of the ErrorHandler class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ErrorHandler_INCLUDED
+#define Foundation_ErrorHandler_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+class Foundation_API ErrorHandler
+	/// This is the base class for thread error handlers.
+	///
+	/// An unhandled exception that causes a thread to terminate is usually
+	/// silently ignored, since the class library cannot do anything meaningful
+	/// about it.
+	/// 
+	/// The Thread class provides the possibility to register a
+	/// global ErrorHandler that is invoked whenever a thread has
+	/// been terminated by an unhandled exception.
+	/// The ErrorHandler must be derived from this class and can
+	/// provide implementations of all three exception() overloads.
+	///
+	/// The ErrorHandler is always invoked within the context of
+	/// the offending thread.
+{
+public:
+	ErrorHandler();
+		/// Creates the ErrorHandler.
+
+	virtual ~ErrorHandler();
+		/// Destroys the ErrorHandler.
+
+	virtual void exception(const Exception& exc);
+		/// Called when a Poco::Exception (or a subclass)
+		/// caused the thread to terminate.
+		///
+		/// This method should not throw any exception - it would
+		/// be silently ignored.
+		///
+		/// The default implementation just breaks into the debugger.
+		
+	virtual void exception(const std::exception& exc);
+		/// Called when a std::exception (or a subclass)
+		/// caused the thread to terminate.		
+		///
+		/// This method should not throw any exception - it would
+		/// be silently ignored.
+		///
+		/// The default implementation just breaks into the debugger.
+
+	virtual void exception();
+		/// Called when an exception that is neither a
+		/// Poco::Exception nor a std::exception caused
+		/// the thread to terminate.
+		///
+		/// This method should not throw any exception - it would
+		/// be silently ignored.
+		///
+		/// The default implementation just breaks into the debugger.
+		
+	static void handle(const Exception& exc);
+		/// Invokes the currently registered ErrorHandler.
+		
+	static void handle(const std::exception& exc);
+		/// Invokes the currently registered ErrorHandler.
+	
+	static void handle();
+		/// Invokes the currently registered ErrorHandler.
+	
+	static ErrorHandler* set(ErrorHandler* pHandler);
+		/// Registers the given handler as the current error handler.
+		///
+		/// Returns the previously registered handler.
+
+	static ErrorHandler* get();
+		/// Returns a pointer to the currently registered
+		/// ErrorHandler.
+
+protected:	
+	static ErrorHandler* defaultHandler();
+		/// Returns the default ErrorHandler.	
+		
+private:
+	static ErrorHandler* _pHandler;
+	static FastMutex     _mutex;
+};
+
+
+//
+// inlines
+//
+inline ErrorHandler* ErrorHandler::get()
+{
+	return _pHandler;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ErrorHandler_INCLUDED
diff --git a/Poco/Event.h b/Poco/Event.h
new file mode 100644
index 0000000..c6e20b6
--- /dev/null
+++ b/Poco/Event.h
@@ -0,0 +1,123 @@
+//
+// Event.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Event
+//
+// Definition of the Event class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Event_INCLUDED
+#define Foundation_Event_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/Event_WIN32.h"
+#elif defined(POCO_VXWORKS)
+#include "Poco/Event_VX.h"
+#else
+#include "Poco/Event_POSIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API Event: private EventImpl
+	/// An Event is a synchronization object that
+	/// allows one thread to signal one or more
+	/// other threads that a certain event
+	/// has happened.
+	/// Usually, one thread signals an event,
+	/// while one or more other threads wait
+	/// for an event to become signalled.
+{
+public:
+	Event(bool autoReset = true);
+		/// Creates the event. If autoReset is true,
+		/// the event is automatically reset after
+		/// a wait() successfully returns.
+		
+	~Event();
+		/// Destroys the event.
+
+	void set();
+		/// Signals the event. If autoReset is true,
+		/// only one thread waiting for the event 
+		/// can resume execution.
+		/// If autoReset is false, all waiting threads
+		/// can resume execution.
+
+	void wait();
+		/// Waits for the event to become signalled.
+
+	void wait(long milliseconds);
+		/// Waits for the event to become signalled.
+		/// Throws a TimeoutException if the event
+		/// does not become signalled within the specified
+		/// time interval.
+
+	bool tryWait(long milliseconds);
+		/// Waits for the event to become signalled.
+		/// Returns true if the event
+		/// became signalled within the specified
+		/// time interval, false otherwise.
+
+	void reset();
+		/// Resets the event to unsignalled state.
+	
+private:
+	Event(const Event&);
+	Event& operator = (const Event&);
+};
+
+
+//
+// inlines
+//
+inline void Event::set()
+{
+	setImpl();
+}
+
+
+inline void Event::wait()
+{
+	waitImpl();
+}
+
+
+inline void Event::wait(long milliseconds)
+{
+	if (!waitImpl(milliseconds))
+		throw TimeoutException();
+}
+
+
+inline bool Event::tryWait(long milliseconds)
+{
+	return waitImpl(milliseconds);
+}
+
+
+inline void Event::reset()
+{
+	resetImpl();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Event_INCLUDED
diff --git a/Poco/EventArgs.h b/Poco/EventArgs.h
new file mode 100644
index 0000000..0066790
--- /dev/null
+++ b/Poco/EventArgs.h
@@ -0,0 +1,45 @@
+//
+// EventArgs.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  EventArgs
+//
+// Definition of EventArgs.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_EventArgs_INCLUDED
+#define Foundation_EventArgs_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EventArgs
+	/// The purpose of the EventArgs class is to be used as parameter
+	/// when one doesn't want to send any data.
+	///
+	/// One can use EventArgs as a base class for one's own event arguments
+	/// but with the arguments being a template parameter this is not
+	/// necessary.
+{
+public:
+	EventArgs();
+	
+	virtual ~EventArgs();
+};
+
+
+} // namespace Poco
+
+
+#endif
diff --git a/Poco/EventChannel.h b/Poco/EventChannel.h
new file mode 100644
index 0000000..0797516
--- /dev/null
+++ b/Poco/EventChannel.h
@@ -0,0 +1,54 @@
+//
+// EventChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  EventChannel
+//
+// Definition of the EventChannel class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_EventChannel_INCLUDED
+#define Foundation_EventChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Message.h"
+#include "Poco/BasicEvent.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EventChannel: public Channel
+	/// The EventChannel fires the messageLogged event for every log message
+	/// received. This can be used to hook custom log message processing into
+	/// the logging framework. 
+{
+public:
+	Poco::BasicEvent<const Message> messageLogged;
+		/// Fired when a message is logged by calling the log() method.
+
+	EventChannel();
+		/// Creates the EventChannel.
+
+	void log(const Message& msg);
+		/// Fires the messageLogged event.
+
+protected:
+	~EventChannel();
+		/// Destroys the EventChannel.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_EventChannel_INCLUDED
diff --git a/Poco/EventLogChannel.h b/Poco/EventLogChannel.h
new file mode 100644
index 0000000..bcaf3a4
--- /dev/null
+++ b/Poco/EventLogChannel.h
@@ -0,0 +1,105 @@
+//
+// EventLogChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  EventLogChannel
+//
+// Definition of the EventLogChannel class specific to WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_EventLogChannel_INCLUDED
+#define Foundation_EventLogChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EventLogChannel: public Channel
+	/// This Windows-only channel works with the Windows NT Event Log
+	/// service.
+	///
+	/// To work properly, the EventLogChannel class requires that either
+	/// the PocoFoundation.dll or the PocoMsg.dll Dynamic Link Library
+	/// containing the message definition resources can be found in $PATH.
+{
+public:
+	EventLogChannel();
+		/// Creates the EventLogChannel.
+		/// The name of the current application (or more correctly,
+		/// the name of its executable) is taken as event source name.
+		
+	EventLogChannel(const std::string& name);
+		/// Creates the EventLogChannel with the given event source name.
+		
+	EventLogChannel(const std::string& name, const std::string& host);
+		/// Creates an EventLogChannel with the given event source
+		/// name that routes messages to the given host.
+		
+	void open();
+		/// Opens the EventLogChannel. If necessary, the
+		/// required registry entries to register a
+		/// message resource DLL are made.
+		
+	void close();
+		/// Closes the EventLogChannel.
+	
+	void log(const Message& msg);
+		/// Logs the given message to the Windows Event Log.
+		///
+		/// The message type and priority are mapped to
+		/// appropriate values for Event Log type and category.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets or changes a configuration property. 
+		///
+		/// The following properties are supported:
+		///
+		///   * name:    The name of the event source.
+		///   * loghost: The name of the host where the Event Log service is running.
+		///              The default is "localhost".
+		///   * host:    same as host.
+		///   * logfile: The name of the log file. The default is "Application".
+		
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the given property.
+
+	static const std::string PROP_NAME;
+	static const std::string PROP_HOST;
+	static const std::string PROP_LOGHOST;
+	static const std::string PROP_LOGFILE;
+
+protected:
+	~EventLogChannel();
+	static int getType(const Message& msg);
+	static int getCategory(const Message& msg);
+	void setUpRegistry() const;
+#if defined(POCO_WIN32_UTF8)
+	static std::wstring findLibrary(const wchar_t* name);
+#else
+	static std::string findLibrary(const char* name);
+#endif
+
+private:
+	std::string _name;
+	std::string _host;
+	std::string _logFile;
+	HANDLE      _h;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_EventLogChannel_INCLUDED
diff --git a/Poco/Event_POSIX.h b/Poco/Event_POSIX.h
new file mode 100644
index 0000000..b7eb83a
--- /dev/null
+++ b/Poco/Event_POSIX.h
@@ -0,0 +1,77 @@
+//
+// Event_POSIX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Event
+//
+// Definition of the EventImpl class for POSIX Threads.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Event_POSIX_INCLUDED
+#define Foundation_Event_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <pthread.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API EventImpl
+{
+protected:
+	EventImpl(bool autoReset);		
+	~EventImpl();
+	void setImpl();
+	void waitImpl();
+	bool waitImpl(long milliseconds);
+	void resetImpl();
+	
+private:
+	bool            _auto;
+	volatile bool   _state;
+	pthread_mutex_t _mutex;
+	pthread_cond_t  _cond;
+};
+
+
+//
+// inlines
+//
+inline void EventImpl::setImpl()
+{
+	if (pthread_mutex_lock(&_mutex))	
+		throw SystemException("cannot signal event (lock)");
+	_state = true;
+	if (pthread_cond_broadcast(&_cond))
+	{
+		pthread_mutex_unlock(&_mutex);
+		throw SystemException("cannot signal event");
+	}
+	pthread_mutex_unlock(&_mutex);
+}
+
+
+inline void EventImpl::resetImpl()
+{
+	if (pthread_mutex_lock(&_mutex))	
+		throw SystemException("cannot reset event");
+	_state = false;
+	pthread_mutex_unlock(&_mutex);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Event_POSIX_INCLUDED
diff --git a/Poco/Event_VX.h b/Poco/Event_VX.h
new file mode 100644
index 0000000..9dd23c7
--- /dev/null
+++ b/Poco/Event_VX.h
@@ -0,0 +1,49 @@
+//
+// Event_VX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Event
+//
+// Definition of the EventImpl class for VxWorks.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Event_VX_INCLUDED
+#define Foundation_Event_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <semLib.h>
+
+
+namespace Poco {
+
+
+class Foundation_API EventImpl
+{
+protected:
+	EventImpl(bool autoReset);		
+	~EventImpl();
+	void setImpl();
+	void waitImpl();
+	bool waitImpl(long milliseconds);
+	void resetImpl();
+	
+private:
+	bool          _auto;
+	volatile bool _state;
+	SEM_ID        _sem;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Event_VX_INCLUDED
diff --git a/Poco/Event_WIN32.h b/Poco/Event_WIN32.h
new file mode 100644
index 0000000..07fdb09
--- /dev/null
+++ b/Poco/Event_WIN32.h
@@ -0,0 +1,68 @@
+//
+// Event_WIN32.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Event
+//
+// Definition of the EventImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Event_WIN32_INCLUDED
+#define Foundation_Event_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API EventImpl
+{
+protected:
+	EventImpl(bool autoReset);		
+	~EventImpl();
+	void setImpl();
+	void waitImpl();
+	bool waitImpl(long milliseconds);
+	void resetImpl();
+	
+private:
+	HANDLE _event;
+};
+
+
+//
+// inlines
+//
+inline void EventImpl::setImpl()
+{
+	if (!SetEvent(_event))
+	{
+		throw SystemException("cannot signal event");
+	}
+}
+
+
+inline void EventImpl::resetImpl()
+{
+	if (!ResetEvent(_event))
+	{
+		throw SystemException("cannot reset event");
+	}
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Event_WIN32_INCLUDED
diff --git a/Poco/Exception.h b/Poco/Exception.h
new file mode 100644
index 0000000..e211c30
--- /dev/null
+++ b/Poco/Exception.h
@@ -0,0 +1,261 @@
+//
+// Exception.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Exception
+//
+// Definition of various Poco exception classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Exception_INCLUDED
+#define Foundation_Exception_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <stdexcept>
+
+
+namespace Poco {
+
+
+class Foundation_API Exception: public std::exception
+	/// This is the base class for all exceptions defined
+	/// in the Poco class library.
+{
+public:
+	Exception(const std::string& msg, int code = 0);
+		/// Creates an exception.
+
+	Exception(const std::string& msg, const std::string& arg, int code = 0);
+		/// Creates an exception.
+
+	Exception(const std::string& msg, const Exception& nested, int code = 0);
+		/// Creates an exception and stores a clone
+		/// of the nested exception.
+
+	Exception(const Exception& exc);
+		/// Copy constructor.
+		
+	~Exception() throw();
+		/// Destroys the exception and deletes the nested exception.
+
+	Exception& operator = (const Exception& exc);
+		/// Assignment operator.
+
+	virtual const char* name() const throw();
+		/// Returns a static string describing the exception.
+		
+	virtual const char* className() const throw();
+		/// Returns the name of the exception class.
+		
+	virtual const char* what() const throw();
+		/// Returns a static string describing the exception.
+		///
+		/// Same as name(), but for compatibility with std::exception.
+		
+	const Exception* nested() const;
+		/// Returns a pointer to the nested exception, or
+		/// null if no nested exception exists.
+			
+	const std::string& message() const;
+		/// Returns the message text.
+			
+	int code() const;
+		/// Returns the exception code if defined.
+		
+	std::string displayText() const;
+		/// Returns a string consisting of the
+		/// message name and the message text.
+
+	virtual Exception* clone() const;
+		/// Creates an exact copy of the exception.
+		///
+		/// The copy can later be thrown again by
+		/// invoking rethrow() on it.
+		
+	virtual void rethrow() const;
+		/// (Re)Throws the exception.
+		///
+		/// This is useful for temporarily storing a
+		/// copy of an exception (see clone()), then
+		/// throwing it again.
+
+protected:
+	Exception(int code = 0);
+		/// Standard constructor.
+
+	void message(const std::string& msg);
+		/// Sets the message for the exception.
+
+	void extendedMessage(const std::string& arg);
+		/// Sets the extended message for the exception.
+		
+private:
+	std::string _msg;
+	Exception*  _pNested;
+	int			_code;
+};
+
+
+//
+// inlines
+//
+inline const Exception* Exception::nested() const
+{
+	return _pNested;
+}
+
+
+inline const std::string& Exception::message() const
+{
+	return _msg;
+}
+
+
+inline void Exception::message(const std::string& msg)
+{
+	_msg = msg;
+}
+
+
+inline int Exception::code() const
+{
+	return _code;
+}
+
+
+//
+// Macros for quickly declaring and implementing exception classes.
+// Unfortunately, we cannot use a template here because character
+// pointers (which we need for specifying the exception name)
+// are not allowed as template arguments.
+//
+#define POCO_DECLARE_EXCEPTION_CODE(API, CLS, BASE, CODE) \
+	class API CLS: public BASE														\
+	{																				\
+	public:																			\
+		CLS(int code = CODE);														\
+		CLS(const std::string& msg, int code = CODE);								\
+		CLS(const std::string& msg, const std::string& arg, int code = CODE);		\
+		CLS(const std::string& msg, const Poco::Exception& exc, int code = CODE);	\
+		CLS(const CLS& exc);														\
+		~CLS() throw();																\
+		CLS& operator = (const CLS& exc);											\
+		const char* name() const throw();											\
+		const char* className() const throw();										\
+		Poco::Exception* clone() const;												\
+		void rethrow() const;														\
+	};
+
+#define POCO_DECLARE_EXCEPTION(API, CLS, BASE) \
+	POCO_DECLARE_EXCEPTION_CODE(API, CLS, BASE, 0)
+
+#define POCO_IMPLEMENT_EXCEPTION(CLS, BASE, NAME)													\
+	CLS::CLS(int code): BASE(code)																	\
+	{																								\
+	}																								\
+	CLS::CLS(const std::string& msg, int code): BASE(msg, code)										\
+	{																								\
+	}																								\
+	CLS::CLS(const std::string& msg, const std::string& arg, int code): BASE(msg, arg, code)		\
+	{																								\
+	}																								\
+	CLS::CLS(const std::string& msg, const Poco::Exception& exc, int code): BASE(msg, exc, code)	\
+	{																								\
+	}																								\
+	CLS::CLS(const CLS& exc): BASE(exc)																\
+	{																								\
+	}																								\
+	CLS::~CLS() throw()																				\
+	{																								\
+	}																								\
+	CLS& CLS::operator = (const CLS& exc)															\
+	{																								\
+		BASE::operator = (exc);																		\
+		return *this;																				\
+	}																								\
+	const char* CLS::name() const throw()															\
+	{																								\
+		return NAME;																				\
+	}																								\
+	const char* CLS::className() const throw()														\
+	{																								\
+		return typeid(*this).name();																\
+	}																								\
+	Poco::Exception* CLS::clone() const																\
+	{																								\
+		return new CLS(*this);																		\
+	}																								\
+	void CLS::rethrow() const																		\
+	{																								\
+		throw *this;																				\
+	}
+
+
+//
+// Standard exception classes
+//
+POCO_DECLARE_EXCEPTION(Foundation_API, LogicException, Exception)
+POCO_DECLARE_EXCEPTION(Foundation_API, AssertionViolationException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, NullPointerException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, NullValueException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, BugcheckException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, InvalidArgumentException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, NotImplementedException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, RangeException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, IllegalStateException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, InvalidAccessException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, SignalException, LogicException)
+POCO_DECLARE_EXCEPTION(Foundation_API, UnhandledException, LogicException)
+
+POCO_DECLARE_EXCEPTION(Foundation_API, RuntimeException, Exception)
+POCO_DECLARE_EXCEPTION(Foundation_API, NotFoundException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, ExistsException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, TimeoutException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, SystemException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, RegularExpressionException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, LibraryLoadException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, LibraryAlreadyLoadedException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, NoThreadAvailableException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, PropertyNotSupportedException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, PoolOverflowException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, NoPermissionException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, OutOfMemoryException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, DataException, RuntimeException)
+
+POCO_DECLARE_EXCEPTION(Foundation_API, DataFormatException, DataException)
+POCO_DECLARE_EXCEPTION(Foundation_API, SyntaxException, DataException)
+POCO_DECLARE_EXCEPTION(Foundation_API, CircularReferenceException, DataException)
+POCO_DECLARE_EXCEPTION(Foundation_API, PathSyntaxException, SyntaxException)
+POCO_DECLARE_EXCEPTION(Foundation_API, IOException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, ProtocolException, IOException)
+POCO_DECLARE_EXCEPTION(Foundation_API, FileException, IOException)
+POCO_DECLARE_EXCEPTION(Foundation_API, FileExistsException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, FileNotFoundException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, PathNotFoundException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, FileReadOnlyException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, FileAccessDeniedException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, CreateFileException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, OpenFileException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, WriteFileException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, ReadFileException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, DirectoryNotEmptyException, FileException)
+POCO_DECLARE_EXCEPTION(Foundation_API, UnknownURISchemeException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, TooManyURIRedirectsException, RuntimeException)
+POCO_DECLARE_EXCEPTION(Foundation_API, URISyntaxException, SyntaxException)
+
+POCO_DECLARE_EXCEPTION(Foundation_API, ApplicationException, Exception)
+POCO_DECLARE_EXCEPTION(Foundation_API, BadCastException, RuntimeException)
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Exception_INCLUDED
diff --git a/Poco/ExpirationDecorator.h b/Poco/ExpirationDecorator.h
new file mode 100644
index 0000000..2e9d40a
--- /dev/null
+++ b/Poco/ExpirationDecorator.h
@@ -0,0 +1,92 @@
+//
+// ExpirationDecorator.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  ExpirationDecorator
+//
+// Implementation of the ExpirationDecorator template.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ExpirationDecorator_INCLUDED
+#define Foundation_ExpirationDecorator_INCLUDED
+
+
+#include "Poco/Timestamp.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+
+
+template <typename TArgs>
+class ExpirationDecorator
+	/// ExpirationDecorator adds an expiration method to values so that they can be used
+	/// with the UniqueExpireCache.
+{
+public:
+	ExpirationDecorator():
+		_value(),
+		_expiresAt()
+	{
+	}
+
+	ExpirationDecorator(const TArgs& p, const Poco::Timespan::TimeDiff& diffInMs):
+			/// Creates an element that will expire in diff milliseconds
+		_value(p),
+		_expiresAt()
+	{
+		_expiresAt += (diffInMs*1000);
+	}
+
+	ExpirationDecorator(const TArgs& p, const Poco::Timespan& timeSpan):
+		/// Creates an element that will expire after the given timeSpan
+		_value(p),
+		_expiresAt()
+	{
+		_expiresAt += timeSpan.totalMicroseconds();
+	}
+
+	ExpirationDecorator(const TArgs& p, const Poco::Timestamp& timeStamp):
+		/// Creates an element that will expire at the given time point
+		_value(p),
+		_expiresAt(timeStamp)
+	{
+	}
+
+
+	~ExpirationDecorator()
+	{
+	}
+	
+	const Poco::Timestamp& getExpiration() const
+	{
+		return _expiresAt;
+	}
+
+	const TArgs& value() const
+	{
+		return _value;
+	}
+
+	TArgs& value()
+	{
+		return _value;
+	}
+
+private:
+	TArgs     _value;
+	Timestamp _expiresAt;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ExpirationDecorator_INCLUDED
diff --git a/Poco/Expire.h b/Poco/Expire.h
new file mode 100644
index 0000000..73f82b4
--- /dev/null
+++ b/Poco/Expire.h
@@ -0,0 +1,194 @@
+//
+// Expire.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  Expire
+//
+// Implementation of the Expire template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Expire_INCLUDED
+#define Foundation_Expire_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractDelegate.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+
+
+template <class TArgs>
+class Expire: public AbstractDelegate<TArgs>
+	/// Decorator for AbstractDelegate adding automatic 
+	/// expiration of registrations to AbstractDelegate's.
+{
+public:
+	Expire(const AbstractDelegate<TArgs>& p, Timestamp::TimeDiff expireMillisecs):
+		_pDelegate(p.clone()), 
+		_expire(expireMillisecs*1000)
+	{
+	}
+
+	Expire(const Expire& expire):
+		AbstractDelegate<TArgs>(expire),
+		_pDelegate(expire._pDelegate->clone()),
+		_expire(expire._expire),
+		_creationTime(expire._creationTime)
+	{
+	}
+
+	~Expire()
+	{
+		delete _pDelegate;
+	}
+	
+	Expire& operator = (const Expire& expire)
+	{
+		if (&expire != this)
+		{
+			delete this->_pDelegate;
+			this->_pDelegate    = expire._pDelegate->clone();
+			this->_expire       = expire._expire;
+			this->_creationTime = expire._creationTime;
+			this->_pTarget = expire._pTarget;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		if (!expired())
+			return this->_pDelegate->notify(sender, arguments);
+		else
+			return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		return other.equals(*_pDelegate);
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new Expire(*this);
+	}
+	
+	void disable()
+	{
+		_pDelegate->disable();
+	}
+
+	const AbstractDelegate<TArgs>* unwrap() const
+	{
+		return this->_pDelegate;
+	}
+
+protected:
+	bool expired() const
+	{
+		return _creationTime.isElapsed(_expire);
+	}
+
+	AbstractDelegate<TArgs>* _pDelegate;
+	Timestamp::TimeDiff _expire;
+	Timestamp _creationTime;
+
+private:
+	Expire();
+};
+
+
+template <>
+class Expire<void>: public AbstractDelegate<void>
+	/// Decorator for AbstractDelegate adding automatic 
+	/// expiration of registrations to AbstractDelegate's.
+{
+public:
+	Expire(const AbstractDelegate<void>& p, Timestamp::TimeDiff expireMillisecs):
+		_pDelegate(p.clone()), 
+		_expire(expireMillisecs*1000)
+	{
+	}
+
+	Expire(const Expire& expire):
+		AbstractDelegate<void>(expire),
+		_pDelegate(expire._pDelegate->clone()),
+		_expire(expire._expire),
+		_creationTime(expire._creationTime)
+	{
+	}
+
+	~Expire()
+	{
+		delete _pDelegate;
+	}
+	
+	Expire& operator = (const Expire& expire)
+	{
+		if (&expire != this)
+		{
+			delete this->_pDelegate;
+			this->_pDelegate    = expire._pDelegate->clone();
+			this->_expire       = expire._expire;
+			this->_creationTime = expire._creationTime;
+			//this->_pTarget = expire._pTarget;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender)
+	{
+		if (!expired())
+			return this->_pDelegate->notify(sender);
+		else
+			return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		return other.equals(*_pDelegate);
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new Expire(*this);
+	}
+	
+	void disable()
+	{
+		_pDelegate->disable();
+	}
+
+	const AbstractDelegate<void>* unwrap() const
+	{
+		return this->_pDelegate;
+	}
+
+protected:
+	bool expired() const
+	{
+		return _creationTime.isElapsed(_expire);
+	}
+
+	AbstractDelegate<void>* _pDelegate;
+	Timestamp::TimeDiff _expire;
+	Timestamp _creationTime;
+
+private:
+	Expire();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Expire_INCLUDED
diff --git a/Poco/ExpireCache.h b/Poco/ExpireCache.h
new file mode 100644
index 0000000..41f0482
--- /dev/null
+++ b/Poco/ExpireCache.h
@@ -0,0 +1,65 @@
+//
+// ExpireCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  ExpireCache
+//
+// Definition of the ExpireCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ExpireCache_INCLUDED
+#define Foundation_ExpireCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/ExpireStrategy.h"
+
+
+namespace Poco {
+
+
+template <
+	class TKey, 
+	class TValue, 
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+> 
+class ExpireCache: public AbstractCache<TKey, TValue, ExpireStrategy<TKey, TValue>, TMutex, TEventMutex>
+	/// An ExpireCache caches entries for a fixed time period (per default 10 minutes).
+	/// Entries expire independently of the access pattern, i.e. after a constant time.
+	/// If you require your objects to expire after they were not accessed for a given time
+	/// period use a Poco::AccessExpireCache.
+	///
+	/// Be careful when using an ExpireCache. A cache is often used
+	/// like cache.has(x) followed by cache.get x). Note that it could happen
+	/// that the "has" call works, then the current execution thread gets descheduled, time passes,
+	/// the entry gets invalid, thus leading to an empty SharedPtr being returned 
+	/// when "get" is invoked.
+{
+public:
+	ExpireCache(Timestamp::TimeDiff expire = 600000): 
+		AbstractCache<TKey, TValue, ExpireStrategy<TKey, TValue>, TMutex, TEventMutex>(ExpireStrategy<TKey, TValue>(expire))
+	{
+	}
+
+	~ExpireCache()
+	{
+	}
+
+private:
+	ExpireCache(const ExpireCache& aCache);
+	ExpireCache& operator = (const ExpireCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ExpireCache_INCLUDED
diff --git a/Poco/ExpireLRUCache.h b/Poco/ExpireLRUCache.h
new file mode 100644
index 0000000..d79281a
--- /dev/null
+++ b/Poco/ExpireLRUCache.h
@@ -0,0 +1,62 @@
+//
+// ExpireLRUCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  ExpireLRUCache
+//
+// Definition of the ExpireLRUCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ExpireLRUCache_INCLUDED
+#define Foundation_ExpireLRUCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/StrategyCollection.h"
+#include "Poco/ExpireStrategy.h"
+#include "Poco/LRUStrategy.h"
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+>
+class ExpireLRUCache: public AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>
+	/// An ExpireLRUCache combines LRU caching and time based expire caching.
+	/// It cache entries for a fixed time period (per default 10 minutes)
+	/// but also limits the size of the cache (per default: 1024).
+{
+public:
+	ExpireLRUCache(long cacheSize = 1024, Timestamp::TimeDiff expire = 600000): 
+		AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>(StrategyCollection<TKey, TValue>())
+	{
+		this->_strategy.pushBack(new LRUStrategy<TKey, TValue>(cacheSize));
+		this->_strategy.pushBack(new ExpireStrategy<TKey, TValue>(expire));
+	}
+
+	~ExpireLRUCache()
+	{
+	}
+
+private:
+	ExpireLRUCache(const ExpireLRUCache& aCache);
+	ExpireLRUCache& operator = (const ExpireLRUCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ExpireLRUCache_INCLUDED
diff --git a/Poco/ExpireStrategy.h b/Poco/ExpireStrategy.h
new file mode 100644
index 0000000..27e471f
--- /dev/null
+++ b/Poco/ExpireStrategy.h
@@ -0,0 +1,132 @@
+//
+// ExpireStrategy.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  ExpireStrategy
+//
+// Definition of the ExpireStrategy class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ExpireStrategy_INCLUDED
+#define Foundation_ExpireStrategy_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/AbstractStrategy.h"
+#include "Poco/Bugcheck.h"
+#include "Poco/Timestamp.h"
+#include "Poco/EventArgs.h"
+#include <set>
+#include <map>
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue
+>
+class ExpireStrategy: public AbstractStrategy<TKey, TValue>
+	/// An ExpireStrategy implements time based expiration of cache entries
+{
+public:
+	typedef std::multimap<Timestamp, TKey>     TimeIndex;
+	typedef typename TimeIndex::iterator       IndexIterator;
+	typedef typename TimeIndex::const_iterator ConstIndexIterator;
+	typedef std::map<TKey, IndexIterator>      Keys;
+	typedef typename Keys::iterator            Iterator;
+
+public:
+	ExpireStrategy(Timestamp::TimeDiff expireTimeInMilliSec): _expireTime(expireTimeInMilliSec * 1000)
+		/// Create an expire strategy. Note that the smallest allowed caching time is 25ms.
+		/// Anything lower than that is not useful with current operating systems.
+	{
+		if (_expireTime < 25000) throw InvalidArgumentException("expireTime must be at least 25 ms");  
+	}
+
+	~ExpireStrategy()
+	{
+	}
+
+	void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
+	{
+		Timestamp now;
+		typename TimeIndex::value_type tiValue(now, args.key());
+		IndexIterator it = _keyIndex.insert(tiValue);
+		typename Keys::value_type kValue(args.key(), it);
+		std::pair<Iterator, bool> stat = _keys.insert(kValue);
+		if (!stat.second)
+		{
+			_keyIndex.erase(stat.first->second);
+			stat.first->second = it;
+		}
+	}
+
+	void onRemove(const void*, const TKey& key)
+	{
+		Iterator it = _keys.find(key);
+		if (it != _keys.end())
+		{
+			_keyIndex.erase(it->second);
+			_keys.erase(it);
+		}
+	}
+
+	void onGet(const void*, const TKey& key)
+	{
+		// get triggers no changes in an expire
+	}
+
+	void onClear(const void*, const EventArgs& args)
+	{
+		_keys.clear();
+		_keyIndex.clear();
+	}
+
+	void onIsValid(const void*, ValidArgs<TKey>& args)
+	{
+		Iterator it = _keys.find(args.key());
+		if (it != _keys.end())
+		{
+			if (it->second->first.isElapsed(_expireTime))
+			{
+				args.invalidate();
+			}
+		}
+		else //not found: probably removed by onReplace
+			args.invalidate();
+	}
+
+	void onReplace(const void*, std::set<TKey>& elemsToRemove)
+	{
+		// Note: replace only informs the cache which elements
+		// it would like to remove!
+		// it does not remove them on its own!
+		IndexIterator it = _keyIndex.begin();
+		while (it != _keyIndex.end() && it->first.isElapsed(_expireTime))
+		{
+			elemsToRemove.insert(it->second);
+			++it;
+		}
+	}
+
+protected:
+	Timestamp::TimeDiff _expireTime;
+	Keys      _keys;     /// For faster replacement of keys, the iterator points to the _keyIndex map
+	TimeIndex _keyIndex; /// Maps time to key value
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ExpireStrategy_INCLUDED
diff --git a/Poco/FIFOBuffer.h b/Poco/FIFOBuffer.h
new file mode 100644
index 0000000..7fc85ca
--- /dev/null
+++ b/Poco/FIFOBuffer.h
@@ -0,0 +1,556 @@
+//
+// FIFOBuffer.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FIFOBuffer
+//
+// Definition of the FIFOBuffer class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FIFOBuffer_INCLUDED
+#define Foundation_FIFOBuffer_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/Buffer.h"
+#include "Poco/BasicEvent.h"
+#include "Poco/Mutex.h"
+#include "Poco/Format.h"
+
+
+namespace Poco {
+
+
+template <class T>
+class BasicFIFOBuffer
+	/// A simple buffer class with support for re-entrant,
+	/// FIFO-style read/write operations, as well as (optional)
+	/// empty/non-empty/full (i.e. writable/readable) transition
+	/// notifications. Buffer can be flagged with end-of-file and
+	/// error flags, which renders it un-readable/writable.
+	///
+	/// Critical portions of code are protected by a recursive mutex.
+	/// However, to achieve thread-safety in cases where multiple
+	/// member function calls are involved and have to be atomic,
+	/// the mutex must be locked externally.
+	/// 
+	/// Buffer size, as well as amount of unread data and
+	/// available space introspections are supported as well.
+	///
+	/// This class is useful anywhere where a FIFO functionality
+	/// is needed.
+{
+public:
+	typedef T Type;
+
+	mutable Poco::BasicEvent<bool> writable;
+		/// Event indicating "writability" of the buffer,
+		/// triggered as follows:
+		///
+		///	* when buffer transitions from non-full to full, 
+		///	  Writable event observers are notified, with 
+		///	  false value as the argument
+		///
+		///	* when buffer transitions from full to non-full,
+		///	  Writable event observers are notified, with 
+		///	  true value as the argument
+
+	mutable Poco::BasicEvent<bool> readable;
+		/// Event indicating "readability" of the buffer,
+		/// triggered as follows:
+		///
+		///	* when buffer transitions from non-empty to empty,
+		///	  Readable event observers are notified, with false  
+		///	  value as the argument
+		///
+		///	* when FIFOBuffer transitions from empty to non-empty,
+		///	  Readable event observers are notified, with true value
+		///	  as the argument
+
+	BasicFIFOBuffer(std::size_t size, bool notify = false):
+		_buffer(size),
+		_begin(0),
+		_used(0),
+		_notify(notify),
+		_eof(false),
+		_error(false)
+		/// Creates the FIFOBuffer.
+	{
+	}
+
+	BasicFIFOBuffer(T* pBuffer, std::size_t size, bool notify = false):
+		_buffer(pBuffer, size),
+		_begin(0),
+		_used(0),
+		_notify(notify),
+		_eof(false),
+		_error(false)
+		/// Creates the FIFOBuffer.
+	{
+	}
+
+	BasicFIFOBuffer(const T* pBuffer, std::size_t size, bool notify = false):
+		_buffer(pBuffer, size),
+		_begin(0),
+		_used(size),
+		_notify(notify),
+		_eof(false),
+		_error(false)
+		/// Creates the FIFOBuffer.
+	{
+	}
+
+	~BasicFIFOBuffer()
+		/// Destroys the FIFOBuffer.
+	{
+	}
+	
+	void resize(std::size_t newSize, bool preserveContent = true)
+		/// Resizes the buffer. If preserveContent is true,
+		/// the content of the old buffer is preserved.
+		/// New size can be larger or smaller than
+		/// the current size, but it must not be 0.
+		/// Additionally, if the new length is smaller
+		/// than currently used length and preserveContent
+		/// is true, InvalidAccessException is thrown.
+	{
+		Mutex::ScopedLock lock(_mutex);
+
+		if (preserveContent && (newSize < _used))
+			throw InvalidAccessException("Can not resize FIFO without data loss.");
+		
+		std::size_t usedBefore = _used;
+		_buffer.resize(newSize, preserveContent);
+		if (!preserveContent) _used = 0;
+		if (_notify) notify(usedBefore);
+	}
+	
+	std::size_t peek(T* pBuffer, std::size_t length) const
+		/// Peeks into the data currently in the FIFO
+		/// without actually extracting it.
+		/// If length is zero, the return is immediate.
+		/// If length is greater than used length,
+		/// it is substituted with the the current FIFO 
+		/// used length.
+		/// 
+		/// Returns the number of elements copied in the 
+		/// supplied buffer.
+	{
+		if (0 == length) return 0;
+		Mutex::ScopedLock lock(_mutex);
+		if (!isReadable()) return 0;
+		if (length > _used) length = _used;
+		std::memcpy(pBuffer, _buffer.begin() + _begin, length * sizeof(T));
+		return length;
+	}
+	
+	std::size_t peek(Poco::Buffer<T>& buffer, std::size_t length = 0) const
+		/// Peeks into the data currently in the FIFO
+		/// without actually extracting it.
+		/// Resizes the supplied buffer to the size of
+		/// data written to it. If length is not
+		/// supplied by the caller or is greater than length 
+		/// of currently used data, the current FIFO used 
+		/// data length is substituted for it.
+		/// 
+		/// Returns the number of elements copied in the 
+		/// supplied buffer.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (!isReadable()) return 0;
+		if (0 == length || length > _used) length = _used;
+		buffer.resize(length);
+		return peek(buffer.begin(), length);
+	}
+	
+	std::size_t read(T* pBuffer, std::size_t length)
+		/// Copies the data currently in the FIFO
+		/// into the supplied buffer, which must be
+		/// preallocated to at least the length size
+		/// before calling this function.
+		/// 
+		/// Returns the size of the copied data.
+	{
+		if (0 == length) return 0;
+		Mutex::ScopedLock lock(_mutex);
+		if (!isReadable()) return 0;
+		std::size_t usedBefore = _used;
+		std::size_t readLen = peek(pBuffer, length);
+		poco_assert (_used >= readLen);
+		_used -= readLen;
+		if (0 == _used) _begin = 0;
+		else _begin += length;
+
+		if (_notify) notify(usedBefore);
+
+		return readLen;
+	}
+	
+	std::size_t read(Poco::Buffer<T>& buffer, std::size_t length = 0)
+		/// Copies the data currently in the FIFO
+		/// into the supplied buffer.
+		/// Resizes the supplied buffer to the size of
+		/// data written to it.
+		/// 
+		/// Returns the size of the copied data.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (!isReadable()) return 0;
+		std::size_t usedBefore = _used;
+		std::size_t readLen = peek(buffer, length);
+		poco_assert (_used >= readLen);
+		_used -= readLen;
+		if (0 == _used) _begin = 0;
+		else _begin += length;
+
+		if (_notify) notify(usedBefore);
+
+		return readLen;
+	}
+
+	std::size_t write(const T* pBuffer, std::size_t length)
+		/// Writes data from supplied buffer to the FIFO buffer.
+		/// If there is no sufficient space for the whole
+		/// buffer to be written, data up to available 
+		/// length is written.
+		/// The length of data to be written is determined from the
+		/// length argument. Function does nothing and returns zero
+		/// if length argument is equal to zero.
+		/// 
+		/// Returns the length of data written.
+	{
+		if (0 == length) return 0;
+
+		Mutex::ScopedLock lock(_mutex);
+		
+		if (!isWritable()) return 0;
+		
+		if (_buffer.size() - (_begin + _used) < length)
+		{
+			std::memmove(_buffer.begin(), begin(), _used * sizeof(T));
+			_begin = 0;
+		}
+
+		std::size_t usedBefore = _used;
+		std::size_t available =  _buffer.size() - _used - _begin;
+		std::size_t len = length > available ? available : length;
+		std::memcpy(begin() + _used, pBuffer, len * sizeof(T));
+		_used += len;
+		poco_assert (_used <= _buffer.size());
+		if (_notify) notify(usedBefore);
+
+		return len;
+	}
+
+	std::size_t write(const Buffer<T>& buffer, std::size_t length = 0)
+		/// Writes data from supplied buffer to the FIFO buffer.
+		/// If there is no sufficient space for the whole
+		/// buffer to be written, data up to available 
+		/// length is written.
+		/// The length of data to be written is determined from the
+		/// length argument or buffer size (when length argument is
+		/// default zero or greater than buffer size).
+		/// 
+		/// Returns the length of data written.
+	{
+		if (length == 0 || length > buffer.size())
+			length = buffer.size();
+
+		return write(buffer.begin(), length);
+	}
+
+	std::size_t size() const
+		/// Returns the size of the buffer.
+	{
+		return _buffer.size();
+	}
+	
+	std::size_t used() const
+		/// Returns the size of the used portion of the buffer.
+	{
+		return _used;
+	}
+	
+	std::size_t available() const
+		/// Returns the size of the available portion of the buffer.
+	{
+		return size() - _used;
+	}
+
+	void drain(std::size_t length = 0)
+		/// Drains length number of elements from the buffer.
+		/// If length is zero or greater than buffer current
+		/// content length, buffer is emptied.
+	{
+		Mutex::ScopedLock lock(_mutex);
+
+		std::size_t usedBefore = _used;
+
+		if (0 == length || length >= _used)
+		{
+			_begin = 0;
+			_used = 0;
+		}
+		else
+		{
+			_begin += length;
+			_used -= length;
+		}
+
+		if (_notify) notify(usedBefore);
+	}
+
+	void copy(const T* ptr, std::size_t length)
+		/// Copies the supplied data to the buffer and adjusts
+		/// the used buffer size.
+	{
+		poco_check_ptr(ptr);
+		if (0 == length) return;
+
+		Mutex::ScopedLock lock(_mutex);
+		
+		if (length > available())
+			throw Poco::InvalidAccessException("Cannot extend buffer.");
+		
+		if (!isWritable())
+			throw Poco::InvalidAccessException("Buffer not writable.");
+
+		std::memcpy(begin() + _used, ptr, length * sizeof(T));
+		std::size_t usedBefore = _used;
+		_used += length;
+		if (_notify) notify(usedBefore);
+	}
+
+	void advance(std::size_t length)
+		/// Advances buffer by length elements.
+		/// Should be called AFTER the data 
+		/// was copied into the buffer.
+	{
+		Mutex::ScopedLock lock(_mutex);
+
+		if (length > available())
+			throw Poco::InvalidAccessException("Cannot extend buffer.");
+		
+		if (!isWritable())
+			throw Poco::InvalidAccessException("Buffer not writable.");
+
+		if (_buffer.size() - (_begin + _used) < length)
+		{
+			std::memmove(_buffer.begin(), begin(), _used * sizeof(T));
+			_begin = 0;
+		}
+
+		std::size_t usedBefore = _used;
+		_used += length;
+		if (_notify) notify(usedBefore);
+	}
+
+	T* begin()
+		/// Returns the pointer to the beginning of the buffer.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_begin != 0)
+		{
+			// Move the data to the start of the buffer so begin() and next()
+			// always return consistent pointers with each other and allow writing
+			// to the end of the buffer.
+			std::memmove(_buffer.begin(), _buffer.begin() + _begin, _used * sizeof(T));
+			_begin = 0;
+		}
+		return _buffer.begin();
+	}
+
+	T* next()
+		/// Returns the pointer to the next available position in the buffer.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		return begin() + _used;
+	}
+
+	T& operator [] (std::size_t index)
+		/// Returns value at index position.
+		/// Throws InvalidAccessException if index is larger than 
+		/// the last valid (used) buffer position.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (index >= _used)
+			throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
+
+		return _buffer[_begin + index];
+	}
+
+	const T& operator [] (std::size_t index) const
+		/// Returns value at index position.
+		/// Throws InvalidAccessException if index is larger than 
+		/// the last valid (used) buffer position.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (index >= _used)
+			throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
+
+		return _buffer[_begin + index];
+	}
+
+	const Buffer<T>& buffer() const
+		/// Returns const reference to the underlying buffer.
+	{
+		return _buffer;
+	}
+	
+	void setError(bool error = true)
+		/// Sets the error flag on the buffer and empties it.
+		/// If notifications are enabled, they will be triggered 
+		/// if appropriate.
+		/// 
+		/// Setting error flag to true prevents reading and writing
+		/// to the buffer; to re-enable FIFOBuffer for reading/writing,
+		/// the error flag must be set to false.
+	{
+		if (error)
+		{
+			bool f = false;
+			Mutex::ScopedLock lock(_mutex);
+			if (error && isReadable() && _notify) readable.notify(this, f);
+			if (error && isWritable() && _notify) writable.notify(this, f);
+			_error = error;
+			_used = 0;
+		}
+		else
+		{
+			bool t = true;
+			Mutex::ScopedLock lock(_mutex);
+			_error = false;
+			if (_notify && !_eof) writable.notify(this, t);
+		}
+	}
+
+	bool isValid() const
+		/// Returns true if error flag is not set on the buffer,
+		/// otherwise returns false.
+	{
+		return !_error;
+	}
+
+	void setEOF(bool eof = true)
+		/// Sets end-of-file flag on the buffer.
+		/// 
+		/// Setting EOF flag to true prevents writing to the
+		/// buffer; reading from the buffer will still be
+		/// allowed until all data present in the buffer at the 
+		/// EOF set time is drained. After that, to re-enable 
+		/// FIFOBuffer for reading/writing, EOF must be
+		/// set to false.
+		/// 
+		/// Setting EOF flag to false clears EOF state if it
+		/// was previously set. If EOF was not set, it has no
+		/// effect.
+	{
+		Mutex::ScopedLock lock(_mutex);
+		bool flag = !eof;
+		if (_notify) writable.notify(this, flag);
+		_eof = eof;
+	}
+
+	bool hasEOF() const
+		/// Returns true if EOF flag has been set.
+	{
+		return _eof;
+	}
+
+	bool isEOF() const
+		/// Returns true if EOF flag has been set and buffer is empty.
+	{
+		return isEmpty() && _eof;
+	}
+
+	bool isEmpty() const
+		/// Returns true is buffer is empty, false otherwise.
+	{
+		return 0 == _used;
+	}
+
+	bool isFull() const
+		/// Returns true is buffer is full, false otherwise.
+	{
+		return size() == _used;
+	}
+
+	bool isReadable() const
+		/// Returns true if buffer contains data and is not
+		/// in error state.
+	{
+		return !isEmpty() && isValid();
+	}
+
+	bool isWritable() const
+		/// Returns true if buffer is not full and is not
+		/// in error state.
+	{
+		return !isFull() && isValid() && !_eof;
+	}
+
+	void setNotify(bool notify = true)
+		/// Enables/disables notifications.
+	{
+		_notify = notify;
+	}
+
+	bool getNotify() const
+		/// Returns true if notifications are enabled, false otherwise.
+	{
+		return _notify;
+	}
+
+	Mutex& mutex()
+		/// Returns reference to mutex.
+	{
+		return _mutex;
+	}
+
+private:
+	void notify(std::size_t usedBefore)
+	{
+		bool t = true, f = false;
+		if (usedBefore == 0 && _used > 0)
+			readable.notify(this, t);
+		else if (usedBefore > 0 && 0 == _used)
+			readable.notify(this, f);
+		
+		if (usedBefore == _buffer.size() && _used < _buffer.size())
+			writable.notify(this, t);
+		else if (usedBefore < _buffer.size() && _used == _buffer.size())
+			writable.notify(this, f);
+	}
+
+	BasicFIFOBuffer();
+	BasicFIFOBuffer(const BasicFIFOBuffer&);
+	BasicFIFOBuffer& operator = (const BasicFIFOBuffer&);
+
+	Buffer<T>     _buffer;
+	std::size_t   _begin;
+	std::size_t   _used;
+	bool          _notify;
+	mutable Mutex _mutex;
+	bool          _eof;
+	bool          _error;
+};
+
+
+//
+// We provide an instantiation for char
+//
+typedef BasicFIFOBuffer<char> FIFOBuffer;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FIFOBuffer_INCLUDED
diff --git a/Poco/FIFOBufferStream.h b/Poco/FIFOBufferStream.h
new file mode 100644
index 0000000..6c1e1eb
--- /dev/null
+++ b/Poco/FIFOBufferStream.h
@@ -0,0 +1,154 @@
+//
+// FIFOBufferStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  FIFOBufferStream
+//
+// Definition of the FIFOBufferStream class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FIFOBufferStream_INCLUDED
+#define Foundation_FIFOBufferStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/FIFOBuffer.h"
+#include "Poco/BufferedBidirectionalStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API FIFOBufferStreamBuf: public BufferedBidirectionalStreamBuf
+	/// This is the streambuf class used for reading from and writing to a FIFOBuffer.
+	/// FIFOBuffer is enabled for emtpy/non-empty/full state transitions notifications.
+{
+public:
+	
+	FIFOBufferStreamBuf();
+		/// Creates a FIFOBufferStreamBuf.
+
+	explicit FIFOBufferStreamBuf(FIFOBuffer& fifoBuffer);
+		/// Creates a FIFOBufferStreamBuf and assigns the given buffer to it.
+
+	FIFOBufferStreamBuf(char* pBuffer, std::size_t length);
+		/// Creates a FIFOBufferStreamBuf and assigns the given buffer to it.
+
+	FIFOBufferStreamBuf(const char* pBuffer, std::size_t length);
+		/// Creates a FIFOBufferStreamBuf and assigns the given buffer to it.
+
+	explicit FIFOBufferStreamBuf(std::size_t length);
+		/// Creates a FIFOBufferStreamBuf of the given length.
+
+	~FIFOBufferStreamBuf();
+		/// Destroys the FIFOBufferStreamBuf.
+
+	FIFOBuffer& fifoBuffer();
+		/// Returns the underlying FIFO buffer reference.
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE = 1024
+	};
+
+	FIFOBuffer* _pFIFOBuffer;
+	FIFOBuffer& _fifoBuffer;
+};
+
+
+class Foundation_API FIFOIOS: public virtual std::ios
+	/// The base class for FIFOBufferInputStream and
+	/// FIFOBufferStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	explicit FIFOIOS(FIFOBuffer& buffer);
+		/// Creates a FIFOIOS and assigns the given buffer to it.
+
+	FIFOIOS(char* pBuffer, std::size_t length);
+		/// Creates a FIFOIOS and assigns the given buffer to it.
+
+	FIFOIOS(const char* pBuffer, std::size_t length);
+		/// Creates a FIFOIOS and assigns the given buffer to it.
+
+	explicit FIFOIOS(std::size_t length);
+		/// Creates a FIFOIOS of the given length.
+		
+	~FIFOIOS();
+		/// Destroys the FIFOIOS.
+		///
+		/// Flushes the buffer.
+		
+	FIFOBufferStreamBuf* rdbuf();
+		/// Returns a pointer to the internal FIFOBufferStreamBuf.
+		
+	void close();
+		/// Flushes the stream.
+
+protected:
+	FIFOBufferStreamBuf _buf;
+};
+
+
+class Foundation_API FIFOBufferStream: public FIFOIOS, public std::iostream
+	/// An output stream for writing to a FIFO.
+{
+public:
+	Poco::BasicEvent<bool>& readable;
+	Poco::BasicEvent<bool>& writable;
+
+	explicit FIFOBufferStream(FIFOBuffer& buffer);
+		/// Creates the FIFOBufferStream with supplied buffer as initial value.
+
+	FIFOBufferStream(char* pBuffer, std::size_t length);
+		/// Creates a FIFOBufferStream and assigns the given buffer to it.
+
+	FIFOBufferStream(const char* pBuffer, std::size_t length);
+		/// Creates a FIFOBufferStream and assigns the given buffer to it.
+
+	explicit FIFOBufferStream(std::size_t length);
+		/// Creates a FIFOBufferStream of the given length.
+
+	~FIFOBufferStream();
+		/// Destroys the FIFOBufferStream.
+		///
+		/// Flushes the buffer.
+
+private:
+	FIFOBufferStream();
+	FIFOBufferStream(const FIFOBufferStream& other);
+	FIFOBufferStream& operator =(const FIFOBufferStream& other);
+};
+
+
+///
+/// inlines
+///
+
+
+inline FIFOBuffer& FIFOBufferStreamBuf::fifoBuffer()
+{
+	return _fifoBuffer;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FIFOBufferStream_INCLUDED
diff --git a/Poco/FIFOEvent.h b/Poco/FIFOEvent.h
new file mode 100644
index 0000000..404044c
--- /dev/null
+++ b/Poco/FIFOEvent.h
@@ -0,0 +1,63 @@
+//
+// FIFOEvent.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  FIFOEvent
+//
+// Implementation of the FIFOEvent template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FIFOEvent_INCLUDED
+#define Foundation_FIFOEvent_INCLUDED
+
+
+#include "Poco/AbstractEvent.h"
+#include "Poco/FIFOStrategy.h"
+#include "Poco/AbstractDelegate.h"
+
+
+namespace Poco {
+
+
+//@ deprecated
+template <class TArgs, class TMutex = FastMutex> 
+class FIFOEvent: public AbstractEvent < 
+	TArgs, 
+	FIFOStrategy<TArgs, AbstractDelegate<TArgs> >,
+	AbstractDelegate<TArgs>,
+	TMutex
+>
+	/// A FIFOEvent uses internally a FIFOStrategy which guarantees
+	/// that delegates are invoked in the order they were added to
+	/// the event.
+	///
+	/// Note that as of release 1.4.2, this is the default behavior
+	/// implemented by BasicEvent, so this class is provided
+	/// for backwards compatibility only.
+{
+public:
+	FIFOEvent()
+	{
+	}
+
+	~FIFOEvent()
+	{
+	}
+
+private:
+	FIFOEvent(const FIFOEvent& e);
+	FIFOEvent& operator = (const FIFOEvent& e);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FIFOEvent_INCLUDED
diff --git a/Poco/FIFOStrategy.h b/Poco/FIFOStrategy.h
new file mode 100644
index 0000000..79c2276
--- /dev/null
+++ b/Poco/FIFOStrategy.h
@@ -0,0 +1,59 @@
+//
+// FIFOStrategy.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  FIFOStragegy
+//
+// Implementation of the FIFOStrategy template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FIFOStrategy_INCLUDED
+#define Foundation_FIFOStrategy_INCLUDED
+
+
+#include "Poco/DefaultStrategy.h"
+
+
+namespace Poco {
+
+
+//@ deprecated
+template <class TArgs, class TDelegate> 
+class FIFOStrategy: public DefaultStrategy<TArgs, TDelegate>
+	/// Note: As of release 1.4.2, DefaultStrategy already 
+	/// implements FIFO behavior, so this class is provided
+	/// for backwards compatibility only.
+{
+public:
+	FIFOStrategy()
+	{
+	}
+
+	FIFOStrategy(const FIFOStrategy& s):
+		DefaultStrategy<TArgs, TDelegate>(s)
+	{
+	}
+
+	~FIFOStrategy()
+	{
+	}
+
+	FIFOStrategy& operator = (const FIFOStrategy& s)
+	{
+		DefaultStrategy<TArgs, TDelegate>::operator = (s);
+		return *this;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FIFOStrategy_INCLUDED
diff --git a/Poco/FPEnvironment.h b/Poco/FPEnvironment.h
new file mode 100644
index 0000000..4602f57
--- /dev/null
+++ b/Poco/FPEnvironment.h
@@ -0,0 +1,207 @@
+//
+// FPEnvironment.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definitions of class FPEnvironment.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_INCLUDED
+#define Foundation_FPEnvironment_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(POCO_NO_FPENVIRONMENT)
+#include "Poco/FPEnvironment_DUMMY.h"
+#elif defined(__osf__)
+#include "Poco/FPEnvironment_DEC.h"
+#elif defined(sun) || defined(__sun)
+#include "Poco/FPEnvironment_SUN.h"
+#elif defined(__QNX__)
+#include "Poco/FPEnvironment_QNX.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/FPEnvironment_C99.h"
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/FPEnvironment_WIN32.h"
+#else
+#include "Poco/FPEnvironment_DUMMY.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API FPEnvironment: private FPEnvironmentImpl
+	/// Instances of this class can be used to save
+	/// and later restore the current floating
+	/// point environment (consisting of rounding
+	/// mode and floating-point flags).
+	/// The class also provides various static
+	/// methods to query certain properties
+	/// of a floating-point number.
+{
+public:
+	enum RoundingMode
+	{
+		FP_ROUND_DOWNWARD   = FP_ROUND_DOWNWARD_IMPL,
+		FP_ROUND_UPWARD     = FP_ROUND_UPWARD_IMPL,
+		FP_ROUND_TONEAREST  = FP_ROUND_TONEAREST_IMPL,
+		FP_ROUND_TOWARDZERO = FP_ROUND_TOWARDZERO_IMPL
+	};
+
+	enum Flag
+	{
+		FP_DIVIDE_BY_ZERO = FP_DIVIDE_BY_ZERO_IMPL,
+		FP_INEXACT        = FP_INEXACT_IMPL,
+		FP_OVERFLOW       = FP_OVERFLOW_IMPL,
+		FP_UNDERFLOW      = FP_UNDERFLOW_IMPL,
+		FP_INVALID        = FP_INVALID_IMPL
+	};
+
+	FPEnvironment();
+		/// Standard constructor.
+		/// Remembers the current environment.
+
+	FPEnvironment(RoundingMode mode);
+		/// Remembers the current environment and
+		/// sets the given rounding mode.
+
+	FPEnvironment(const FPEnvironment& env);
+		/// Copy constructor.
+
+	~FPEnvironment();
+		/// Restores the previous environment (unless
+		/// keepCurrent() has been called previously)
+
+	FPEnvironment& operator = (const FPEnvironment& env);
+		/// Assignment operator
+
+	void keepCurrent();
+		/// Keep the current environment even after
+		/// destroying the FPEnvironment object.
+
+	static void clearFlags();
+		/// Resets all flags.
+
+	static bool isFlag(Flag flag);
+		/// Returns true iff the given flag is set.
+
+	static void setRoundingMode(RoundingMode mode);
+		/// Sets the rounding mode.
+
+	static RoundingMode getRoundingMode();
+		/// Returns the current rounding mode.
+
+	static bool isInfinite(float value);
+	static bool isInfinite(double value);
+	static bool isInfinite(long double value);
+		/// Returns true iff the given number is infinite.
+
+	static bool isNaN(float value);
+	static bool isNaN(double value);
+	static bool isNaN(long double value);
+		/// Returns true iff the given number is NaN.
+
+	static float copySign(float target, float source);
+	static double copySign(double target, double source);
+	static long double copySign(long double target, long double source);
+		/// Copies the sign from source to target.
+};
+
+
+//
+// For convenience, we provide a shorter name for
+// the FPEnvironment class.
+//
+typedef FPEnvironment FPE;
+
+
+//
+// inline's
+//
+inline bool FPEnvironment::isFlag(Flag flag)
+{
+	return isFlagImpl(FlagImpl(flag));
+}
+
+
+inline void FPEnvironment::setRoundingMode(RoundingMode mode)
+{
+	setRoundingModeImpl(RoundingModeImpl(mode));
+}
+
+
+inline FPEnvironment::RoundingMode FPEnvironment::getRoundingMode()
+{
+	return RoundingMode(getRoundingModeImpl());
+}
+
+
+inline bool FPEnvironment::isInfinite(float value)
+{
+	return isInfiniteImpl(value);
+}
+
+
+inline bool FPEnvironment::isInfinite(double value)
+{
+	return isInfiniteImpl(value);
+}
+
+
+inline bool FPEnvironment::isInfinite(long double value)
+{
+	return isInfiniteImpl(value);
+}
+
+
+inline bool FPEnvironment::isNaN(float value)
+{
+	return isNaNImpl(value);
+}
+
+
+inline bool FPEnvironment::isNaN(double value)
+{
+	return isNaNImpl(value);
+}
+
+
+inline bool FPEnvironment::isNaN(long double value)
+{
+	return isNaNImpl(value);
+}
+
+
+inline float FPEnvironment::copySign(float target, float source)
+{
+	return copySignImpl(target, source);
+}
+
+
+inline double FPEnvironment::copySign(double target, double source)
+{
+	return copySignImpl(target, source);
+}
+
+
+inline long double FPEnvironment::copySign(long double target, long double source)
+{
+	return copySignImpl(target, source);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_INCLUDED
diff --git a/Poco/FPEnvironment_C99.h b/Poco/FPEnvironment_C99.h
new file mode 100644
index 0000000..0b192f5
--- /dev/null
+++ b/Poco/FPEnvironment_C99.h
@@ -0,0 +1,125 @@
+//
+// FPEnvironment_C99.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definitions of class FPEnvironmentImpl for C99.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_C99_INCLUDED
+#define Foundation_FPEnvironment_C99_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <fenv.h>
+#include <cmath>
+
+
+namespace Poco {
+
+
+class FPEnvironmentImpl
+{
+protected:
+	enum RoundingModeImpl
+	{
+		FP_ROUND_DOWNWARD_IMPL   = FE_DOWNWARD,
+		FP_ROUND_UPWARD_IMPL     = FE_UPWARD,
+		FP_ROUND_TONEAREST_IMPL  = FE_TONEAREST,
+		FP_ROUND_TOWARDZERO_IMPL = FE_TOWARDZERO
+	};
+	enum FlagImpl
+	{
+		FP_DIVIDE_BY_ZERO_IMPL = FE_DIVBYZERO,
+		FP_INEXACT_IMPL        = FE_INEXACT,
+		FP_OVERFLOW_IMPL       = FE_OVERFLOW,
+		FP_UNDERFLOW_IMPL      = FE_UNDERFLOW,
+		FP_INVALID_IMPL        = FE_INVALID
+	};
+	FPEnvironmentImpl();
+	FPEnvironmentImpl(const FPEnvironmentImpl& env);
+	~FPEnvironmentImpl();
+	FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
+	void keepCurrentImpl();		
+	static void clearFlagsImpl();
+	static bool isFlagImpl(FlagImpl flag);	
+	static void setRoundingModeImpl(RoundingModeImpl mode);
+	static RoundingModeImpl getRoundingModeImpl();
+	static bool isInfiniteImpl(float value);		
+	static bool isInfiniteImpl(double value);
+	static bool isInfiniteImpl(long double value);
+	static bool isNaNImpl(float value);		
+	static bool isNaNImpl(double value);
+	static bool isNaNImpl(long double value);
+	static float copySignImpl(float target, float source);		
+	static double copySignImpl(double target, double source);
+	static long double copySignImpl(long double target, long double source);
+
+private:
+	fenv_t _env;
+};
+
+
+//
+// inlines
+//
+inline bool FPEnvironmentImpl::isInfiniteImpl(float value)
+{
+	return std::isinf(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(double value)
+{
+	return std::isinf(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(long double value)
+{
+	return std::isinf((double) value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(float value)
+{
+	return std::isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(double value)
+{
+	return std::isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(long double value)
+{
+	return std::isnan((double) value) != 0;
+}
+
+
+inline float FPEnvironmentImpl::copySignImpl(float target, float source)
+{
+	return copysignf(target, source);
+}
+
+
+inline double FPEnvironmentImpl::copySignImpl(double target, double source)
+{
+	return copysign(target, source);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_C99_INCLUDED
diff --git a/Poco/FPEnvironment_DEC.h b/Poco/FPEnvironment_DEC.h
new file mode 100644
index 0000000..b55794a
--- /dev/null
+++ b/Poco/FPEnvironment_DEC.h
@@ -0,0 +1,89 @@
+//
+// FPEnvironment_DEC.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definitions of class FPEnvironmentImpl for Tru64 and OpenVMS Alpha.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_DEC_INCLUDED
+#define Foundation_FPEnvironment_DEC_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#if defined(__VMS)
+#include <ieeedef.h>
+#else
+#include <machine/fpu.h>
+#endif
+
+
+namespace Poco {
+
+
+class FPEnvironmentImpl
+{
+protected:
+	enum RoundingModeImpl
+	{
+		FP_ROUND_DOWNWARD_IMPL   = 0,
+		FP_ROUND_UPWARD_IMPL     = 0,
+		FP_ROUND_TONEAREST_IMPL  = 0,
+		FP_ROUND_TOWARDZERO_IMPL = 0
+	};
+	enum FlagImpl
+	{
+#if defined(__VMS)
+		FP_DIVIDE_BY_ZERO_IMPL = IEEE$M_STATUS_DZE,
+		FP_INEXACT_IMPL        = IEEE$M_STATUS_INE,
+		FP_OVERFLOW_IMPL       = IEEE$M_STATUS_OVF,
+		FP_UNDERFLOW_IMPL      = IEEE$M_STATUS_UNF,
+		FP_INVALID_IMPL        = IEEE$M_STATUS_INV
+#else
+		FP_DIVIDE_BY_ZERO_IMPL = IEEE_STATUS_DZE,
+		FP_INEXACT_IMPL        = IEEE_STATUS_INE,
+		FP_OVERFLOW_IMPL       = IEEE_STATUS_OVF,
+		FP_UNDERFLOW_IMPL      = IEEE_STATUS_UNF,
+		FP_INVALID_IMPL        = IEEE_STATUS_INV
+#endif
+	};
+	FPEnvironmentImpl();
+	FPEnvironmentImpl(const FPEnvironmentImpl& env);
+	~FPEnvironmentImpl();
+	FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
+	void keepCurrentImpl();		
+	static void clearFlagsImpl();
+	static bool isFlagImpl(FlagImpl flag);	
+	static void setRoundingModeImpl(RoundingModeImpl mode);
+	static RoundingModeImpl getRoundingModeImpl();
+	static bool isInfiniteImpl(float value);		
+	static bool isInfiniteImpl(double value);
+	static bool isInfiniteImpl(long double value);
+	static bool isNaNImpl(float value);		
+	static bool isNaNImpl(double value);
+	static bool isNaNImpl(long double value);
+	static float copySignImpl(float target, float source);		
+	static double copySignImpl(double target, double source);
+	static long double copySignImpl(long double target, long double source);
+
+private:
+#if defined(__VMS)
+	struct _ieee _env;
+#else
+	unsigned long _env;
+#endif
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_DEC_INCLUDED
diff --git a/Poco/FPEnvironment_DUMMY.h b/Poco/FPEnvironment_DUMMY.h
new file mode 100644
index 0000000..5571c12
--- /dev/null
+++ b/Poco/FPEnvironment_DUMMY.h
@@ -0,0 +1,125 @@
+//
+// FPEnvironment_DUMMY.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definition of class FPEnvironmentImpl for platforms that do not
+// support IEEE 754 extensions.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_DUMMY_INCLUDED
+#define Foundation_FPEnvironment_DUMMY_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <cmath>
+
+
+namespace Poco {
+
+
+class Foundation_API FPEnvironmentImpl
+{
+protected:
+	enum RoundingModeImpl
+	{
+		FP_ROUND_DOWNWARD_IMPL,
+		FP_ROUND_UPWARD_IMPL,
+		FP_ROUND_TONEAREST_IMPL,
+		FP_ROUND_TOWARDZERO_IMPL
+	};
+	enum FlagImpl
+	{
+		FP_DIVIDE_BY_ZERO_IMPL,
+		FP_INEXACT_IMPL,
+		FP_OVERFLOW_IMPL,
+		FP_UNDERFLOW_IMPL,
+		FP_INVALID_IMPL
+	};
+	FPEnvironmentImpl();
+	FPEnvironmentImpl(const FPEnvironmentImpl& env);
+	~FPEnvironmentImpl();
+	FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
+	void keepCurrentImpl();
+	static void clearFlagsImpl();
+	static bool isFlagImpl(FlagImpl flag);
+	static void setRoundingModeImpl(RoundingModeImpl mode);
+	static RoundingModeImpl getRoundingModeImpl();
+	static bool isInfiniteImpl(float value);
+	static bool isInfiniteImpl(double value);
+	static bool isInfiniteImpl(long double value);
+	static bool isNaNImpl(float value);
+	static bool isNaNImpl(double value);
+	static bool isNaNImpl(long double value);
+	static float copySignImpl(float target, float source);
+	static double copySignImpl(double target, double source);
+	static long double copySignImpl(long double target, long double source);
+
+private:
+	static RoundingModeImpl _roundingMode;
+};
+
+
+//
+// inlines
+//
+inline bool FPEnvironmentImpl::isInfiniteImpl(float value)
+{
+	return std::isinf(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(double value)
+{
+	return std::isinf(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(long double value)
+{
+	return std::isinf((double) value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(float value)
+{
+	return std::isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(double value)
+{
+	return std::isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(long double value)
+{
+	return std::isnan((double) value) != 0;
+}
+
+
+inline float FPEnvironmentImpl::copySignImpl(float target, float source)
+{
+	return copysignf(target, source);
+}
+
+
+inline double FPEnvironmentImpl::copySignImpl(double target, double source)
+{
+	return copysign(target, source);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_DUMMY_INCLUDED
diff --git a/Poco/FPEnvironment_QNX.h b/Poco/FPEnvironment_QNX.h
new file mode 100644
index 0000000..1eef825
--- /dev/null
+++ b/Poco/FPEnvironment_QNX.h
@@ -0,0 +1,133 @@
+//
+// FPEnvironment_QNX.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definitions of class FPEnvironmentImpl for QNX.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_QNX_INCLUDED
+#define Foundation_FPEnvironment_QNX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <fenv.h>
+#include <cmath>
+
+
+namespace Poco {
+
+
+class FPEnvironmentImpl
+{
+protected:
+	enum RoundingModeImpl
+	{
+		FP_ROUND_DOWNWARD_IMPL   = FE_DOWNWARD,
+		FP_ROUND_UPWARD_IMPL     = FE_UPWARD,
+		FP_ROUND_TONEAREST_IMPL  = FE_TONEAREST,
+		FP_ROUND_TOWARDZERO_IMPL = FE_TOWARDZERO
+	};
+	enum FlagImpl
+	{
+		FP_DIVIDE_BY_ZERO_IMPL = FE_DIVBYZERO,
+		FP_INEXACT_IMPL        = FE_INEXACT,
+		FP_OVERFLOW_IMPL       = FE_OVERFLOW,
+		FP_UNDERFLOW_IMPL      = FE_UNDERFLOW,
+		FP_INVALID_IMPL        = FE_INVALID
+	};
+	FPEnvironmentImpl();
+	FPEnvironmentImpl(const FPEnvironmentImpl& env);
+	~FPEnvironmentImpl();
+	FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
+	void keepCurrentImpl();		
+	static void clearFlagsImpl();
+	static bool isFlagImpl(FlagImpl flag);	
+	static void setRoundingModeImpl(RoundingModeImpl mode);
+	static RoundingModeImpl getRoundingModeImpl();
+	static bool isInfiniteImpl(float value);		
+	static bool isInfiniteImpl(double value);
+	static bool isInfiniteImpl(long double value);
+	static bool isNaNImpl(float value);		
+	static bool isNaNImpl(double value);
+	static bool isNaNImpl(long double value);
+	static float copySignImpl(float target, float source);		
+	static double copySignImpl(double target, double source);
+	static long double copySignImpl(long double target, long double source);
+
+private:
+	fenv_t _env;
+};
+
+
+//
+// inlines
+//
+inline bool FPEnvironmentImpl::isInfiniteImpl(float value)
+{
+	using namespace std;
+	return isinf(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(double value)
+{
+	using namespace std;
+	return isinf(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(long double value)
+{
+	using namespace std;
+	return isinf((double) value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(float value)
+{
+	using namespace std;
+	return isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(double value)
+{
+	using namespace std;
+	return isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(long double value)
+{
+	using namespace std;
+	return isnan((double) value) != 0;
+}
+
+
+inline float FPEnvironmentImpl::copySignImpl(float target, float source)
+{
+	using namespace std;
+	return copysignf(target, source);
+}
+
+
+inline double FPEnvironmentImpl::copySignImpl(double target, double source)
+{
+	using namespace std;
+	return copysign(target, source);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_QNX_INCLUDED
diff --git a/Poco/FPEnvironment_SUN.h b/Poco/FPEnvironment_SUN.h
new file mode 100644
index 0000000..d975500
--- /dev/null
+++ b/Poco/FPEnvironment_SUN.h
@@ -0,0 +1,74 @@
+//
+// FPEnvironment_SUN.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definitions of class FPEnvironmentImpl for Solaris.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_SUN_INCLUDED
+#define Foundation_FPEnvironment_SUN_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <ieeefp.h>
+
+
+namespace Poco {
+
+
+class FPEnvironmentImpl
+{
+protected:
+	enum RoundingModeImpl
+	{
+		FP_ROUND_DOWNWARD_IMPL   = FP_RM,
+		FP_ROUND_UPWARD_IMPL     = FP_RP,
+		FP_ROUND_TONEAREST_IMPL  = FP_RN,
+		FP_ROUND_TOWARDZERO_IMPL = FP_RZ
+	};
+	enum FlagImpl
+	{
+		FP_DIVIDE_BY_ZERO_IMPL = FP_X_DZ,
+		FP_INEXACT_IMPL        = FP_X_IMP,
+		FP_OVERFLOW_IMPL       = FP_X_OFL,
+		FP_UNDERFLOW_IMPL      = FP_X_UFL,
+		FP_INVALID_IMPL        = FP_X_INV
+	};
+	FPEnvironmentImpl();
+	FPEnvironmentImpl(const FPEnvironmentImpl& env);
+	~FPEnvironmentImpl();
+	FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
+	void keepCurrentImpl();		
+	static void clearFlagsImpl();
+	static bool isFlagImpl(FlagImpl flag);	
+	static void setRoundingModeImpl(RoundingModeImpl mode);
+	static RoundingModeImpl getRoundingModeImpl();
+	static bool isInfiniteImpl(float value);		
+	static bool isInfiniteImpl(double value);
+	static bool isInfiniteImpl(long double value);
+	static bool isNaNImpl(float value);		
+	static bool isNaNImpl(double value);
+	static bool isNaNImpl(long double value);
+	static float copySignImpl(float target, float source);		
+	static double copySignImpl(double target, double source);
+	static long double copySignImpl(long double target, long double source);
+
+private:
+	fp_rnd    _rnd;
+	fp_except _exc;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_SUN_INCLUDED
diff --git a/Poco/FPEnvironment_WIN32.h b/Poco/FPEnvironment_WIN32.h
new file mode 100644
index 0000000..2c46ce7
--- /dev/null
+++ b/Poco/FPEnvironment_WIN32.h
@@ -0,0 +1,150 @@
+//
+// FPEnvironment_WIN32.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  FPEnvironment
+//
+// Definitions of class FPEnvironmentImpl for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FPEnvironment_WIN32_INCLUDED
+#define Foundation_FPEnvironment_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <float.h>
+#include <math.h>
+
+#ifndef _SW_INEXACT
+#	define _SW_INEXACT 0x00000001 // inexact (precision)
+#endif
+#ifndef _SW_UNDERFLOW
+#	define _SW_UNDERFLOW 0x00000002 // underflow
+#endif
+#ifndef _SW_OVERFLOW
+#	define _SW_OVERFLOW 0x00000004 // overflow
+#endif
+#ifndef _SW_ZERODIVIDE
+#	define _SW_ZERODIVIDE 0x00000008 // zero divide
+#endif
+#ifndef _SW_INVALID
+#	define _SW_INVALID 0x00000010 // invalid
+#endif
+#ifndef _SW_DENORMAL
+#	define _SW_DENORMAL 0x00080000 // denormal status bit
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API FPEnvironmentImpl
+{
+protected:
+	enum RoundingModeImpl
+	{
+		FP_ROUND_DOWNWARD_IMPL   = _RC_DOWN,
+		FP_ROUND_UPWARD_IMPL     = _RC_UP,
+		FP_ROUND_TONEAREST_IMPL  = _RC_NEAR,
+		FP_ROUND_TOWARDZERO_IMPL = _RC_CHOP
+	};
+	enum FlagImpl
+	{
+		FP_DIVIDE_BY_ZERO_IMPL = _SW_ZERODIVIDE,
+		FP_INEXACT_IMPL        = _SW_INEXACT,
+		FP_OVERFLOW_IMPL       = _SW_OVERFLOW,
+		FP_UNDERFLOW_IMPL      = _SW_UNDERFLOW,
+		FP_INVALID_IMPL        = _SW_INVALID
+	};
+	FPEnvironmentImpl();
+	FPEnvironmentImpl(const FPEnvironmentImpl& env);
+	~FPEnvironmentImpl();
+	FPEnvironmentImpl& operator = (const FPEnvironmentImpl& env);
+	void keepCurrentImpl();
+	static void clearFlagsImpl();
+	static bool isFlagImpl(FlagImpl flag);	
+	static void setRoundingModeImpl(RoundingModeImpl mode);
+	static RoundingModeImpl getRoundingModeImpl();
+	static bool isInfiniteImpl(float value);		
+	static bool isInfiniteImpl(double value);
+	static bool isInfiniteImpl(long double value);
+	static bool isNaNImpl(float value);		
+	static bool isNaNImpl(double value);
+	static bool isNaNImpl(long double value);
+	static float copySignImpl(float target, float source);		
+	static double copySignImpl(double target, double source);
+	static long double copySignImpl(long double target, long double source);
+
+private:
+	unsigned _env;
+};
+
+
+//
+// inlines
+//
+inline bool FPEnvironmentImpl::isInfiniteImpl(float value)
+{
+	return _finite(value) == 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(double value)
+{
+	return _finite(value) == 0;
+}
+
+
+inline bool FPEnvironmentImpl::isInfiniteImpl(long double value)
+{
+	return _finite(value) == 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(float value)
+{
+	return _isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(double value)
+{
+	return _isnan(value) != 0;
+}
+
+
+inline bool FPEnvironmentImpl::isNaNImpl(long double value)
+{
+	return _isnan(value) != 0;
+}
+
+
+inline float FPEnvironmentImpl::copySignImpl(float target, float source)
+{
+	return float(_copysign(target, source));
+}
+
+
+inline double FPEnvironmentImpl::copySignImpl(double target, double source)
+{
+	return _copysign(target, source);
+}
+
+
+inline long double FPEnvironmentImpl::copySignImpl(long double target, long double source)
+{
+	return (source > 0 && target > 0) || (source < 0 && target < 0) ? target : -target;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FPEnvironment_WIN32_INCLUDED
diff --git a/Poco/File.h b/Poco/File.h
new file mode 100644
index 0000000..afecf32
--- /dev/null
+++ b/Poco/File.h
@@ -0,0 +1,315 @@
+//
+// File.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  File
+//
+// Definition of the File class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_File_INCLUDED
+#define Foundation_File_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include <vector>
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+#if defined(_WIN32_WCE)
+#include "File_WINCE.h"
+#else
+#include "Poco/File_WIN32U.h"
+#endif
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/File_WIN32.h"
+#elif defined(POCO_VXWORKS)
+#include "Poco/File_VX.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/File_UNIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Path;
+
+
+class Foundation_API File: private FileImpl
+	/// The File class provides methods for working with a file.
+	///
+	/// Regarding paths passed to the various methods, note that
+	/// platform-specific limitations regarding maximum length
+	/// of the entire path and its components apply.
+	///
+	/// On Windows, if compiled with UTF-8 support (POCO_WIN32_UTF8)
+	/// the implementation tries to work around the rather low
+	/// 260 characters MAX_PATH limit by adding the "\\?\" prefix if
+	/// a path is absolute and exceeds MAX_PATH characters in length.
+	/// Note that various limitations regarding usage of the "\\?\"
+	/// prefix apply in that case, e.g. the path must
+	/// not contain relative components ("." and "..") and must not
+	/// use the forward slash ("/") as directory separator.
+{
+public:
+	typedef FileSizeImpl FileSize;
+
+	enum LinkType
+		/// Type of link for linkTo().
+	{
+		LINK_HARD     = 0, /// hard link
+		LINK_SYMBOLIC = 1  /// symbolic link
+	};
+
+	File();
+		/// Creates the file.
+
+	File(const std::string& path);
+		/// Creates the file.
+
+	File(const char* path);
+		/// Creates the file.
+
+	File(const Path& path);
+		/// Creates the file.
+
+	File(const File& file);
+		/// Copy constructor.
+
+	virtual ~File();
+		/// Destroys the file.
+
+	File& operator = (const File& file);
+		/// Assignment operator.
+
+	File& operator = (const std::string& path);
+		/// Assignment operator.
+
+	File& operator = (const char* path);
+		/// Assignment operator.
+
+	File& operator = (const Path& path);
+		/// Assignment operator.
+
+	void swap(File& file);
+		/// Swaps the file with another one.
+
+	const std::string& path() const;
+		/// Returns the path.
+
+	bool exists() const;
+		/// Returns true iff the file exists.
+
+	bool canRead() const;
+		/// Returns true iff the file is readable.
+
+	bool canWrite() const;
+		/// Returns true iff the file is writeable.
+
+	bool canExecute() const;
+		/// Returns true iff the file is executable.
+		///
+		/// On Windows, the file must have
+		/// the extension ".EXE" to be executable.
+		/// On Unix platforms, the executable permission
+		/// bit must be set.
+
+	bool isFile() const;
+		/// Returns true iff the file is a regular file.
+
+	bool isLink() const;
+		/// Returns true iff the file is a symbolic link.
+
+	bool isDirectory() const;
+		/// Returns true iff the file is a directory.
+
+	bool isDevice() const;
+		/// Returns true iff the file is a device.
+
+	bool isHidden() const;
+		/// Returns true if the file is hidden.
+		///
+		/// On Windows platforms, the file's hidden
+		/// attribute is set for this to be true.
+		///
+		/// On Unix platforms, the file name must
+		/// begin with a period for this to be true.
+
+	Timestamp created() const;
+		/// Returns the creation date of the file.
+		///
+		/// Not all platforms or filesystems (e.g. Linux and most Unix
+		/// platforms with the exception of FreeBSD and Mac OS X)
+		/// maintain the creation date of a file.
+		/// On such platforms, created() returns
+		/// the time of the last inode modification.
+
+	Timestamp getLastModified() const;
+		/// Returns the modification date of the file.
+
+	File& setLastModified(const Timestamp& ts);
+		/// Sets the modification date of the file.
+
+	FileSize getSize() const;
+		/// Returns the size of the file in bytes.
+
+	File& setSize(FileSize size);
+		/// Sets the size of the file in bytes. Can be used
+		/// to truncate a file.
+
+	File& setWriteable(bool flag = true);
+		/// Makes the file writeable (if flag is true), or
+		/// non-writeable (if flag is false) by setting the
+		/// file's flags in the filesystem accordingly.
+
+	File& setReadOnly(bool flag = true);
+		/// Makes the file non-writeable (if flag is true), or
+		/// writeable (if flag is false) by setting the
+		/// file's flags in the filesystem accordingly.
+
+	File& setExecutable(bool flag = true);
+		/// Makes the file executable (if flag is true), or
+		/// non-executable (if flag is false) by setting
+		/// the file's permission bits accordingly.
+		///
+		/// Does nothing on Windows.
+
+	void copyTo(const std::string& path) const;
+		/// Copies the file (or directory) to the given path.
+		/// The target path can be a directory.
+		///
+		/// A directory is copied recursively.
+
+	void moveTo(const std::string& path);
+		/// Copies the file (or directory) to the given path and
+		/// removes the original file. The target path can be a directory.
+
+	void renameTo(const std::string& path);
+		/// Renames the file to the new name.
+
+	void linkTo(const std::string& path, LinkType type = LINK_SYMBOLIC) const;
+		/// Creates a link (symbolic or hard, depending on type argument)
+		/// at the given path to the file or directory.
+		///
+		/// May not be supported on all platforms.
+		/// Furthermore, some operating systems do not allow creating
+		/// hard links to directories.
+
+	void remove(bool recursive = false);
+		/// Deletes the file. If recursive is true and the
+		/// file is a directory, recursively deletes all
+		/// files in the directory.
+
+	bool createFile();
+		/// Creates a new, empty file in an atomic operation.
+		/// Returns true if the file has been created and false
+		/// if the file already exists. Throws an exception if
+		/// an error occurs.
+
+	bool createDirectory();
+		/// Creates a directory. Returns true if the directory
+		/// has been created and false if it already exists.
+		/// Throws an exception if an error occurs.
+
+	void createDirectories();
+		/// Creates a directory (and all parent directories
+		/// if necessary).
+
+	void list(std::vector<std::string>& files) const;
+		/// Fills the vector with the names of all
+		/// files in the directory.
+
+	void list(std::vector<File>& files) const;
+		/// Fills the vector with the names of all
+		/// files in the directory.
+
+	FileSize totalSpace() const;
+		/// Returns the total size in bytes of the partition containing this path.
+
+	FileSize usableSpace() const;
+		/// Returns the number of usable free bytes on the partition containing this path.
+
+	FileSize freeSpace() const;
+		/// Returns the number of free bytes on the partition containing this path.
+
+	bool operator == (const File& file) const;
+	bool operator != (const File& file) const;
+	bool operator <  (const File& file) const;
+	bool operator <= (const File& file) const;
+	bool operator >  (const File& file) const;
+	bool operator >= (const File& file) const;
+
+	static void handleLastError(const std::string& path);
+		/// For internal use only. Throws an appropriate
+		/// exception for the last file-related error.
+
+protected:
+	void copyDirectory(const std::string& path) const;
+		/// Copies a directory. Used internally by copyTo().
+};
+
+
+//
+// inlines
+//
+inline const std::string& File::path() const
+{
+	return getPathImpl();
+}
+
+
+inline bool File::operator == (const File& file) const
+{
+	return getPathImpl() == file.getPathImpl();
+}
+
+
+inline bool File::operator != (const File& file) const
+{
+	return getPathImpl() != file.getPathImpl();
+}
+
+
+inline bool File::operator < (const File& file) const
+{
+	return getPathImpl() < file.getPathImpl();
+}
+
+
+inline bool File::operator <= (const File& file) const
+{
+	return getPathImpl() <= file.getPathImpl();
+}
+
+
+inline bool File::operator > (const File& file) const
+{
+	return getPathImpl() > file.getPathImpl();
+}
+
+
+inline bool File::operator >= (const File& file) const
+{
+	return getPathImpl() >= file.getPathImpl();
+}
+
+
+inline void swap(File& f1, File& f2)
+{
+	f1.swap(f2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_File_INCLUDED
diff --git a/Poco/FileChannel.h b/Poco/FileChannel.h
new file mode 100644
index 0000000..84348bc
--- /dev/null
+++ b/Poco/FileChannel.h
@@ -0,0 +1,270 @@
+//
+// FileChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  FileChannel
+//
+// Definition of the FileChannel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FileChannel_INCLUDED
+#define Foundation_FileChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Timespan.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+class LogFile;
+class RotateStrategy;
+class ArchiveStrategy;
+class PurgeStrategy;
+
+
+class Foundation_API FileChannel: public Channel
+	/// A Channel that writes to a file. This class supports
+	/// flexible log file rotation and archiving, as well
+	/// as automatic purging of archived log files.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is in the text. 
+	///
+	/// The FileChannel support log file rotation based
+	/// on log file size or time intervals.
+	/// Archived log files can be compressed in gzip format.
+	/// Older archived files can be automatically deleted
+	/// (purged).
+	///
+	/// The rotation strategy can be specified with the
+	/// "rotation" property, which can take one of the
+	/// follwing values:
+	///
+	///   * never:         no log rotation
+	///   * [day,][hh]:mm: the file is rotated on specified day/time
+	///                    day - day is specified as long or short day name (Monday|Mon, Tuesday|Tue, ... );
+	///                          day can be omitted, in which case log is rotated every day
+	///                    hh  - valid hour range is 00-23;
+	///                          hour can be omitted, in which case log is rotated every hour
+	///                    mm  - valid minute range is 00-59;
+	///                          minute must be specified
+	///   * daily:         the file is rotated daily
+	///   * weekly:        the file is rotated every seven days
+	///   * monthly:       the file is rotated every 30 days
+	///   * <n> minutes:   the file is rotated every <n> minutes, 
+	///                    where <n> is an integer greater than zero.
+	///   * <n> hours:     the file is rotated every <n> hours, where
+	///                    <n> is an integer greater than zero.
+	///   * <n> days:      the file is rotated every <n> days, where
+	///                    <n> is an integer greater than zero.
+	///   * <n> weeks:     the file is rotated every <n> weeks, where
+	///                    <n> is an integer greater than zero.
+	///   * <n> months:    the file is rotated every <n> months, where
+	///                    <n> is an integer greater than zero and
+	///                    a month has 30 days.
+	///   * <n>:           the file is rotated when its size exceeds
+	///                    <n> bytes.
+	///   * <n> K:         the file is rotated when its size exceeds
+	///                    <n> Kilobytes.
+	///   * <n> M:         the file is rotated when its size exceeds
+	///                    <n> Megabytes.
+	///
+	/// NOTE: For periodic log file rotation (daily, weekly, monthly, etc.),
+	/// the date and time of log file creation or last rotation is
+	/// written into the first line of the log file. This is because
+	/// there is no reliable way to find out the real creation date of
+	/// a file on many platforms (e.g., most Unix platforms do not
+	/// provide the creation date, and Windows has its own issues
+	/// with its "File System Tunneling Capabilities").
+	///
+	/// Using the "archive" property it is possible to specify
+	/// how archived log files are named. The following values
+	/// for the "archive" property are supported:
+	///
+	///   * number:     A number, starting with 0, is appended to
+	///                 the name of archived log files. The newest
+	///                 archived log file always has the number 0.
+	///                 For example, if the log file is named
+	///                 "access.log", and it fulfils the criteria
+	///                 for rotation, the file is renamed to
+	///                 "access.log.0". If a file named "access.log.0"
+	///                 already exists, it is renamed to "access.log.1",
+	///                 and so on.
+	///   * timestamp:  A timestamp is appended to the log file name.
+	///                 For example, if the log file is named
+	///                 "access.log", and it fulfils the criteria
+	///                 for rotation, the file is renamed to
+	///                 "access.log.20050802110300".
+	///
+	/// Using the "times" property it is possible to specify
+	/// time mode for the day/time based rotation. The following values
+	/// for the "times" property are supported:
+	///
+	///   * utc:        Rotation strategy is based on UTC time (default).
+	///   * local:      Rotation strategy is based on local time.
+	///
+	/// Archived log files can be compressed using the gzip compression
+	/// method. Compressing can be controlled with the "compress"
+	/// property. The following values for the "compress" property
+	/// are supported:
+	///
+	///   * true:       Compress archived log files.
+	///   * false:      Do not compress archived log files.
+	///
+	/// Archived log files can be automatically purged, either if
+	/// they reach a certain age, or if the number of archived
+	/// log files reaches a given maximum number. This is 
+	/// controlled by the purgeAge and purgeCount properties.
+	///
+	/// The purgeAge property can have the following values:
+	///
+	///   * <n> [seconds]: the maximum age is <n> seconds.
+	///   * <n> minutes:   the maximum age is <n> minutes.
+	///   * <n> hours:     the maximum age is <n> hours.
+	///   * <n> days:      the maximum age is <n> days.
+	///   * <n> weeks:     the maximum age is <n> weeks.
+	///   * <n> months:    the maximum age is <n> months, where a month has 30 days.
+	///
+	/// The purgeCount property has an integer value that specifies the maximum number
+	/// of archived log files. If the number is exceeded, archived log files are
+	/// deleted, starting with the oldest. When "none" or empty string are
+	/// supplied, they reset purgeCount to none (no purging).
+	///
+	/// The flush property specifies whether each log message is flushed
+	/// immediately to the log file (which may hurt application performance,
+	/// but ensures that everything is in the log in case of a system crash),
+	//  or whether it's allowed to stay in the system's file buffer for some time. 
+	/// Valid values are:
+	///
+	///   * true:  Every essages is immediately flushed to the log file (default).
+	///   * false: Messages are not immediately flushed to the log file.
+	///
+	/// The rotateOnOpen property specifies whether an existing log file should be 
+	/// rotated (and archived) when the channel is opened. Valid values are:
+	///
+	///   * true:  The log file is rotated (and archived) when the channel is opened.
+	///   * false: Log messages will be appended to an existing log file,
+	///            if it exists (unless other conditions for a rotation are met). 
+	///            This is the default.
+	///
+	/// For a more lightweight file channel class, see SimpleFileChannel.
+{
+public:
+	FileChannel();
+		/// Creates the FileChannel.
+
+	FileChannel(const std::string& path);
+		/// Creates the FileChannel for a file with the given path.
+
+	void open();
+		/// Opens the FileChannel and creates the log file if necessary.
+		
+	void close();
+		/// Closes the FileChannel.
+
+	void log(const Message& msg);
+		/// Logs the given message to the file.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given name. 
+		/// 
+		/// The following properties are supported:
+		///   * path:         The log file's path.
+		///   * rotation:     The log file's rotation mode. See the 
+		///                   FileChannel class for details.
+		///   * archive:      The log file's archive mode. See the
+		///                   FileChannel class for details.
+		///   * times:        The log file's time mode. See the
+		///                   FileChannel class for details.
+		///   * compress:     Enable or disable compression of
+		///                   archived files. See the FileChannel class
+		///                   for details.
+		///   * purgeAge:     Maximum age of an archived log file before
+		///                   it is purged. See the FileChannel class for
+		///                   details.
+		///   * purgeCount:   Maximum number of archived log files before
+		///                   files are purged. See the FileChannel class
+		///                   for details.
+		///   * flush:        Specifies whether messages are immediately
+		///                   flushed to the log file. See the FileChannel class
+		///                   for details.
+		///   * rotateOnOpen: Specifies whether an existing log file should be 
+		///                   rotated and archived when the channel is opened.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+		/// See setProperty() for a description of the supported
+		/// properties.
+
+	Timestamp creationDate() const;
+		/// Returns the log file's creation date.
+		
+	UInt64 size() const;
+		/// Returns the log file's current size in bytes.
+
+	const std::string& path() const;
+		/// Returns the log file's path.
+
+	static const std::string PROP_PATH;
+	static const std::string PROP_ROTATION;
+	static const std::string PROP_ARCHIVE;
+	static const std::string PROP_TIMES;
+	static const std::string PROP_COMPRESS;
+	static const std::string PROP_PURGEAGE;
+	static const std::string PROP_PURGECOUNT;
+	static const std::string PROP_FLUSH;
+	static const std::string PROP_ROTATEONOPEN;
+
+protected:
+	~FileChannel();
+	void setRotation(const std::string& rotation);
+	void setArchive(const std::string& archive);
+	void setCompress(const std::string& compress);
+	void setPurgeAge(const std::string& age);
+	void setPurgeCount(const std::string& count);
+	void setFlush(const std::string& flush);
+	void setRotateOnOpen(const std::string& rotateOnOpen);
+	void purge();
+
+private:
+	bool setNoPurge(const std::string& value);
+	int extractDigit(const std::string& value, std::string::const_iterator* nextToDigit = NULL) const;
+	void setPurgeStrategy(PurgeStrategy* strategy);
+	Timespan::TimeDiff extractFactor(const std::string& value, std::string::const_iterator start) const;
+
+	std::string      _path;
+	std::string      _times;
+	std::string      _rotation;
+	std::string      _archive;
+	bool             _compress;
+	std::string      _purgeAge;
+	std::string      _purgeCount;
+	bool             _flush;
+	bool             _rotateOnOpen;
+	LogFile*         _pFile;
+	RotateStrategy*  _pRotateStrategy;
+	ArchiveStrategy* _pArchiveStrategy;
+	PurgeStrategy*   _pPurgeStrategy;
+	FastMutex        _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FileChannel_INCLUDED
diff --git a/Poco/FileStream.h b/Poco/FileStream.h
new file mode 100644
index 0000000..cea56c9
--- /dev/null
+++ b/Poco/FileStream.h
@@ -0,0 +1,176 @@
+//
+// FileStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  FileStream
+//
+// Definition of the FileStreamBuf, FileInputStream and FileOutputStream classes.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FileStream_INCLUDED
+#define Foundation_FileStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/FileStream_WIN32.h"
+#else
+#include "Poco/FileStream_POSIX.h"
+#endif
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API FileIOS: public virtual std::ios
+	/// The base class for FileInputStream and FileOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+	///
+	/// Files are always opened in binary mode, a text mode
+	/// with CR-LF translation is not supported. Thus, the
+	/// file is always opened as if the std::ios::binary flag
+	/// was specified.
+	/// Use an InputLineEndingConverter or OutputLineEndingConverter
+	/// if you require CR-LF translation.
+	///
+	/// On Windows platforms, if POCO_WIN32_UTF8 is #define'd,
+	/// UTF-8 encoded Unicode paths are correctly handled.
+{
+public:
+	FileIOS(std::ios::openmode defaultMode);
+		/// Creates the basic stream.
+		
+	~FileIOS();
+		/// Destroys the stream.
+
+	void open(const std::string& path, std::ios::openmode mode);
+		/// Opens the file specified by path, using the given mode.
+		///
+		/// Throws a FileException (or a similar exception) if the file 
+		/// does not exist or is not accessible for other reasons and
+		/// a new file cannot be created.
+
+	void close();
+		/// Closes the file stream.
+		///
+		/// If, for an output stream, the close operation fails (because
+		/// the contents of the stream buffer cannot synced back to
+		/// the filesystem), the bad bit is set in the stream state.
+
+	FileStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	FileStreamBuf _buf;
+	std::ios::openmode _defaultMode;
+};
+
+
+class Foundation_API FileInputStream: public FileIOS, public std::istream
+	/// An input stream for reading from a file.
+	///
+	/// Files are always opened in binary mode, a text mode
+	/// with CR-LF translation is not supported. Thus, the
+	/// file is always opened as if the std::ios::binary flag
+	/// was specified.
+	/// Use an InputLineEndingConverter if you require CR-LF translation.
+	///
+	/// On Windows platforms, if POCO_WIN32_UTF8 is #define'd,
+	/// UTF-8 encoded Unicode paths are correctly handled.
+{
+public:
+	FileInputStream();
+		/// Creates an unopened FileInputStream.
+	
+	FileInputStream(const std::string& path, std::ios::openmode mode = std::ios::in);
+		/// Creates the FileInputStream for the file given by path, using
+		/// the given mode.
+		///
+		/// The std::ios::in flag is always set, regardless of the actual
+		/// value specified for mode.
+		///
+		/// Throws a FileNotFoundException (or a similar exception) if the file 
+		/// does not exist or is not accessible for other reasons.
+
+	~FileInputStream();
+		/// Destroys the stream.
+};
+
+
+class Foundation_API FileOutputStream: public FileIOS, public std::ostream
+	/// An output stream for writing to a file.
+	///
+	/// Files are always opened in binary mode, a text mode
+	/// with CR-LF translation is not supported. Thus, the
+	/// file is always opened as if the std::ios::binary flag
+	/// was specified.
+	/// Use an OutputLineEndingConverter if you require CR-LF translation.
+	///
+	/// On Windows platforms, if POCO_WIN32_UTF8 is #define'd,
+	/// UTF-8 encoded Unicode paths are correctly handled.
+{
+public:
+	FileOutputStream();
+		/// Creats an unopened FileOutputStream.
+		
+	FileOutputStream(const std::string& path, std::ios::openmode mode = std::ios::out | std::ios::trunc);
+		/// Creates the FileOutputStream for the file given by path, using
+		/// the given mode.
+		///
+		/// The std::ios::out is always set, regardless of the actual 
+		/// value specified for mode.
+		///
+		/// Throws a FileException (or a similar exception) if the file 
+		/// does not exist or is not accessible for other reasons and
+		/// a new file cannot be created.
+
+	~FileOutputStream();
+		/// Destroys the FileOutputStream.
+};
+
+
+class Foundation_API FileStream: public FileIOS, public std::iostream
+	/// A stream for reading from and writing to a file.
+	///
+	/// Files are always opened in binary mode, a text mode
+	/// with CR-LF translation is not supported. Thus, the
+	/// file is always opened as if the std::ios::binary flag
+	/// was specified.
+	/// Use an InputLineEndingConverter or OutputLineEndingConverter
+	/// if you require CR-LF translation.
+	///
+	/// A seek (seekg() or seekp()) operation will always set the 
+	/// read position and the write position simultaneously to the
+	/// same value.
+	///
+	/// On Windows platforms, if POCO_WIN32_UTF8 is #define'd,
+	/// UTF-8 encoded Unicode paths are correctly handled.
+{
+public:
+	FileStream();
+		/// Creats an unopened FileStream.
+	
+	FileStream(const std::string& path, std::ios::openmode mode = std::ios::out | std::ios::in);
+		/// Creates the FileStream for the file given by path, using
+		/// the given mode.
+
+	~FileStream();
+		/// Destroys the FileOutputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FileStream_INCLUDED
diff --git a/Poco/FileStreamFactory.h b/Poco/FileStreamFactory.h
new file mode 100644
index 0000000..01364cf
--- /dev/null
+++ b/Poco/FileStreamFactory.h
@@ -0,0 +1,61 @@
+//
+// FileStreamFactory.h
+//
+// Library: Foundation
+// Package: URI
+// Module:  FileStreamFactory
+//
+// Definition of the FileStreamFactory class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FileStreamFactory_INCLUDED
+#define Foundation_FileStreamFactory_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/URIStreamFactory.h"
+
+
+namespace Poco {
+
+
+class Path;
+
+
+class Foundation_API FileStreamFactory: public URIStreamFactory
+	/// An implementation of the URIStreamFactory interface
+	/// that handles file URIs.
+{
+public:
+	FileStreamFactory();
+		/// Creates the FileStreamFactory.
+
+	~FileStreamFactory();
+		/// Destroys the FileStreamFactory.
+		
+	std::istream* open(const URI& uri);
+		/// Creates and opens a file stream in binary mode for the given URI.
+		/// The URI must be either a file URI or a relative URI reference
+		/// containing a path to a local file.
+		///
+		/// Throws an FileNotFound exception if the file cannot
+		/// be opened.
+		
+	std::istream* open(const Path& path);
+		/// Creates and opens a file stream in binary mode for the given path.
+		///
+		/// Throws an FileNotFound exception if the file cannot
+		/// be opened.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FileStreamFactory_INCLUDED
diff --git a/Poco/FileStream_POSIX.h b/Poco/FileStream_POSIX.h
new file mode 100644
index 0000000..f5fa25c
--- /dev/null
+++ b/Poco/FileStream_POSIX.h
@@ -0,0 +1,72 @@
+//
+// FileStream_POSIX.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  FileStream
+//
+// Definition of the FileStreamBuf, FileInputStream and FileOutputStream classes.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FileStream_POSIX_INCLUDED
+#define Foundation_FileStream_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferedBidirectionalStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API FileStreamBuf: public BufferedBidirectionalStreamBuf
+	/// This stream buffer handles Fileio
+{
+public:
+	FileStreamBuf();
+		/// Creates a FileStreamBuf.
+		
+	~FileStreamBuf();
+		/// Destroys the FileStream.
+
+	void open(const std::string& path, std::ios::openmode mode);
+		/// Opens the given file in the given mode.
+
+	bool close();
+		/// Closes the File stream buffer. Returns true if successful,
+		/// false otherwise.
+
+	std::streampos seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode mode = std::ios::in | std::ios::out);
+		/// Change position by offset, according to way and mode.
+
+	std::streampos seekpos(std::streampos pos, std::ios::openmode mode = std::ios::in | std::ios::out);
+		/// Change to specified position, according to mode.
+
+protected:
+	enum
+	{
+		BUFFER_SIZE = 4096
+	};
+
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	std::string _path;
+	int _fd;
+	std::streamoff _pos;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FileStream_WIN32_INCLUDED
diff --git a/Poco/FileStream_WIN32.h b/Poco/FileStream_WIN32.h
new file mode 100644
index 0000000..5382f84
--- /dev/null
+++ b/Poco/FileStream_WIN32.h
@@ -0,0 +1,71 @@
+//
+// FileStream_WIN32.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  FileStream
+//
+// Definition of the FileStreamBuf, FileInputStream and FileOutputStream classes.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FileStream_WIN32_INCLUDED
+#define Foundation_FileStream_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferedBidirectionalStreamBuf.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API FileStreamBuf: public BufferedBidirectionalStreamBuf
+	/// This stream buffer handles Fileio
+{
+public:
+	FileStreamBuf();
+		/// Creates a FileStreamBuf.
+
+	~FileStreamBuf();
+		/// Destroys the FileStream.
+
+	void open(const std::string& path, std::ios::openmode mode);
+		/// Opens the given file in the given mode.
+
+	bool close();
+		/// Closes the File stream buffer. Returns true if successful,
+		/// false otherwise.
+
+	std::streampos seekoff(std::streamoff off, std::ios::seekdir dir, std::ios::openmode mode = std::ios::in | std::ios::out);
+		/// change position by offset, according to way and mode
+
+	std::streampos seekpos(std::streampos pos, std::ios::openmode mode = std::ios::in | std::ios::out);
+		/// change to specified position, according to mode
+
+protected:
+	enum
+	{
+		BUFFER_SIZE = 4096
+	};
+
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	std::string _path;
+	HANDLE _handle;
+	UInt64 _pos;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FileStream_WIN32_INCLUDED
diff --git a/Poco/File_UNIX.h b/Poco/File_UNIX.h
new file mode 100644
index 0000000..34a15c5
--- /dev/null
+++ b/Poco/File_UNIX.h
@@ -0,0 +1,86 @@
+//
+// File_UNIX.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  File
+//
+// Definition of the FileImpl class for Unix.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_File_UNIX_INCLUDED
+#define Foundation_File_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class FileImpl
+{
+protected:
+	typedef UInt64 FileSizeImpl;
+
+	FileImpl();
+	FileImpl(const std::string& path);
+	virtual ~FileImpl();
+	void swapImpl(FileImpl& file);
+	void setPathImpl(const std::string& path);
+	const std::string& getPathImpl() const;
+	bool existsImpl() const;
+	bool canReadImpl() const;
+	bool canWriteImpl() const;
+	bool canExecuteImpl() const;
+	bool isFileImpl() const;
+	bool isDirectoryImpl() const;
+	bool isLinkImpl() const;
+	bool isDeviceImpl() const;
+	bool isHiddenImpl() const;
+	Timestamp createdImpl() const;
+	Timestamp getLastModifiedImpl() const;
+	void setLastModifiedImpl(const Timestamp& ts);
+	FileSizeImpl getSizeImpl() const;
+	void setSizeImpl(FileSizeImpl size);
+	void setWriteableImpl(bool flag = true);
+	void setExecutableImpl(bool flag = true);
+	void copyToImpl(const std::string& path) const;
+	void renameToImpl(const std::string& path);
+	void linkToImpl(const std::string& path, int type) const;
+	void removeImpl();
+	bool createFileImpl();
+	bool createDirectoryImpl();
+	FileSizeImpl totalSpaceImpl() const;
+	FileSizeImpl usableSpaceImpl() const;
+	FileSizeImpl freeSpaceImpl() const;
+	static void handleLastErrorImpl(const std::string& path);
+
+private:
+	std::string _path;
+
+	friend class DirectoryIteratorImpl;
+	friend class LinuxDirectoryWatcherStrategy;
+	friend class BSDDirectoryWatcherStrategy;
+};
+
+
+//
+// inlines
+//
+inline const std::string& FileImpl::getPathImpl() const
+{
+	return _path;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_File_UNIX_INCLUDED
diff --git a/Poco/File_VX.h b/Poco/File_VX.h
new file mode 100644
index 0000000..3d66f96
--- /dev/null
+++ b/Poco/File_VX.h
@@ -0,0 +1,84 @@
+//
+// File_VX.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  File
+//
+// Definition of the FileImpl class for VxWorks.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_File_VX_INCLUDED
+#define Foundation_File_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class FileImpl
+{
+protected:
+	typedef UInt64 FileSizeImpl;
+
+	FileImpl();
+	FileImpl(const std::string& path);
+	virtual ~FileImpl();
+	void swapImpl(FileImpl& file);
+	void setPathImpl(const std::string& path);
+	const std::string& getPathImpl() const;
+	bool existsImpl() const;
+	bool canReadImpl() const;
+	bool canWriteImpl() const;
+	bool canExecuteImpl() const;
+	bool isFileImpl() const;
+	bool isDirectoryImpl() const;
+	bool isLinkImpl() const;
+	bool isDeviceImpl() const;
+	bool isHiddenImpl() const;
+	Timestamp createdImpl() const;
+	Timestamp getLastModifiedImpl() const;
+	void setLastModifiedImpl(const Timestamp& ts);
+	FileSizeImpl getSizeImpl() const;
+	void setSizeImpl(FileSizeImpl size);
+	void setWriteableImpl(bool flag = true);
+	void setExecutableImpl(bool flag = true);
+	void copyToImpl(const std::string& path) const;
+	void renameToImpl(const std::string& path);
+	void linkToImpl(const std::string& path, int type) const;
+	void removeImpl();
+	bool createFileImpl();
+	bool createDirectoryImpl();
+	FileSizeImpl totalSpaceImpl() const;
+	FileSizeImpl usableSpaceImpl() const;
+	FileSizeImpl freeSpaceImpl() const;
+	static void handleLastErrorImpl(const std::string& path);
+
+private:
+	std::string _path;
+
+	friend class DirectoryIteratorImpl;
+};
+
+
+//
+// inlines
+//
+inline const std::string& FileImpl::getPathImpl() const
+{
+	return _path;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_File_VX_INCLUDED
diff --git a/Poco/File_WIN32.h b/Poco/File_WIN32.h
new file mode 100644
index 0000000..2d8b888
--- /dev/null
+++ b/Poco/File_WIN32.h
@@ -0,0 +1,87 @@
+//
+// File_WIN32.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  File
+//
+// Definition of the FileImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_File_WIN32_INCLUDED
+#define Foundation_File_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+
+
+class Foundation_API FileImpl
+{
+protected:
+	typedef UInt64 FileSizeImpl;
+
+	FileImpl();
+	FileImpl(const std::string& path);
+	virtual ~FileImpl();
+	void swapImpl(FileImpl& file);
+	void setPathImpl(const std::string& path);
+	const std::string& getPathImpl() const;
+	bool existsImpl() const;
+	bool canReadImpl() const;
+	bool canWriteImpl() const;
+	bool canExecuteImpl() const;
+	bool isFileImpl() const;
+	bool isDirectoryImpl() const;
+	bool isLinkImpl() const;
+	bool isDeviceImpl() const;
+	bool isHiddenImpl() const;
+	Timestamp createdImpl() const;
+	Timestamp getLastModifiedImpl() const;
+	void setLastModifiedImpl(const Timestamp& ts);
+	FileSizeImpl getSizeImpl() const;
+	void setSizeImpl(FileSizeImpl size);
+	void setWriteableImpl(bool flag = true);
+	void setExecutableImpl(bool flag = true);
+	void copyToImpl(const std::string& path) const;
+	void renameToImpl(const std::string& path);
+	void linkToImpl(const std::string& path, int type) const;
+	void removeImpl();
+	bool createFileImpl();
+	bool createDirectoryImpl();
+	FileSizeImpl totalSpaceImpl() const;
+	FileSizeImpl usableSpaceImpl() const;
+	FileSizeImpl freeSpaceImpl() const;
+	static void handleLastErrorImpl(const std::string& path);
+
+private:
+	std::string _path;
+
+	friend class FileHandle;
+	friend class DirectoryIteratorImpl;
+	friend class WindowsDirectoryWatcherStrategy;
+};
+
+
+//
+// inlines
+//
+inline const std::string& FileImpl::getPathImpl() const
+{
+	return _path;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_File_WIN32_INCLUDED
diff --git a/Poco/File_WIN32U.h b/Poco/File_WIN32U.h
new file mode 100644
index 0000000..835da87
--- /dev/null
+++ b/Poco/File_WIN32U.h
@@ -0,0 +1,91 @@
+//
+// File_WIN32U.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  File
+//
+// Definition of the Unicode FileImpl class for WIN32.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_File_WIN32U_INCLUDED
+#define Foundation_File_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+
+
+class Foundation_API FileImpl
+{
+protected:
+	typedef UInt64 FileSizeImpl;
+
+	FileImpl();
+	FileImpl(const std::string& path);
+	virtual ~FileImpl();
+	void swapImpl(FileImpl& file);
+	void setPathImpl(const std::string& path);
+	const std::string& getPathImpl() const;
+	bool existsImpl() const;
+	bool canReadImpl() const;
+	bool canWriteImpl() const;
+	bool canExecuteImpl() const;
+	bool isFileImpl() const;
+	bool isDirectoryImpl() const;
+	bool isLinkImpl() const;
+	bool isDeviceImpl() const;
+	bool isHiddenImpl() const;
+	Timestamp createdImpl() const;
+	Timestamp getLastModifiedImpl() const;
+	void setLastModifiedImpl(const Timestamp& ts);
+	FileSizeImpl getSizeImpl() const;
+	void setSizeImpl(FileSizeImpl size);
+	void setWriteableImpl(bool flag = true);
+	void setExecutableImpl(bool flag = true);
+	void copyToImpl(const std::string& path) const;
+	void renameToImpl(const std::string& path);
+	void linkToImpl(const std::string& path, int type) const;
+	void removeImpl();
+	bool createFileImpl();
+	bool createDirectoryImpl();
+	FileSizeImpl totalSpaceImpl() const;
+	FileSizeImpl usableSpaceImpl() const;
+	FileSizeImpl freeSpaceImpl() const;
+	static void handleLastErrorImpl(const std::string& path);
+	static void convertPath(const std::string& utf8Path, std::wstring& utf16Path);
+
+private:
+	std::string  _path;
+	std::wstring _upath;
+
+	friend class FileHandle;
+	friend class DirectoryIteratorImpl;
+	friend class WindowsDirectoryWatcherStrategy;
+	friend class FileStreamBuf;
+	friend class LogFileImpl;
+};
+
+
+//
+// inlines
+//
+inline const std::string& FileImpl::getPathImpl() const
+{
+	return _path;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_File_WIN32U_INCLUDED
diff --git a/Poco/File_WINCE.h b/Poco/File_WINCE.h
new file mode 100644
index 0000000..c1ba4f3
--- /dev/null
+++ b/Poco/File_WINCE.h
@@ -0,0 +1,90 @@
+//
+// File_WIN32U.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  File
+//
+// Definition of the Unicode FileImpl class for WIN32.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_File_WINCE_INCLUDED
+#define Foundation_File_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+
+
+class Foundation_API FileImpl
+{
+protected:
+	typedef UInt64 FileSizeImpl;
+
+	FileImpl();
+	FileImpl(const std::string& path);
+	virtual ~FileImpl();
+	void swapImpl(FileImpl& file);
+	void setPathImpl(const std::string& path);
+	const std::string& getPathImpl() const;
+	bool existsImpl() const;
+	bool canReadImpl() const;
+	bool canWriteImpl() const;
+	bool canExecuteImpl() const;
+	bool isFileImpl() const;
+	bool isDirectoryImpl() const;
+	bool isLinkImpl() const;
+	bool isDeviceImpl() const;
+	bool isHiddenImpl() const;
+	Timestamp createdImpl() const;
+	Timestamp getLastModifiedImpl() const;
+	void setLastModifiedImpl(const Timestamp& ts);
+	FileSizeImpl getSizeImpl() const;
+	void setSizeImpl(FileSizeImpl size);
+	void setWriteableImpl(bool flag = true);
+	void setExecutableImpl(bool flag = true);
+	void copyToImpl(const std::string& path) const;
+	void renameToImpl(const std::string& path);
+	void linkToImpl(const std::string& path, int type) const;
+	void removeImpl();
+	bool createFileImpl();
+	bool createDirectoryImpl();
+	FileSizeImpl totalSpaceImpl() const;
+	FileSizeImpl usableSpaceImpl() const;
+	FileSizeImpl freeSpaceImpl() const;
+	static void handleLastErrorImpl(const std::string& path);
+	static void convertPath(const std::string& utf8Path, std::wstring& utf16Path);
+
+private:
+	std::string  _path;
+	std::wstring _upath;
+
+	friend class FileHandle;
+	friend class DirectoryIteratorImpl;
+	friend class FileStreamBuf;
+	friend class LogFileImpl;
+};
+
+
+//
+// inlines
+//
+inline const std::string& FileImpl::getPathImpl() const
+{
+	return _path;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_File_WINCE_INCLUDED
diff --git a/Poco/Format.h b/Poco/Format.h
new file mode 100644
index 0000000..e4b093a
--- /dev/null
+++ b/Poco/Format.h
@@ -0,0 +1,138 @@
+//
+// Format.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Format
+//
+// Definition of the format freestanding function.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Format_INCLUDED
+#define Foundation_Format_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Any.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+std::string Foundation_API format(const std::string& fmt, const Any& value);
+	/// This function implements sprintf-style formatting in a typesafe way.
+	/// Various variants of the function are available, supporting a
+	/// different number of arguments (up to six).
+	///
+	/// The formatting is controlled by the format string in fmt.
+	/// Format strings are quite similar to those of the std::printf() function, but
+	/// there are some minor differences.
+	///
+	/// The format string can consist of any sequence of characters; certain
+	/// characters have a special meaning. Characters without a special meaning
+	/// are copied verbatim to the result. A percent sign (%) marks the beginning
+	/// of a format specification. Format specifications have the following syntax:
+	///
+	///   %[<index>][<flags>][<width>][.<precision>][<modifier>]<type>
+	///
+	/// Index, flags, width, precision and prefix are optional. The only required part of
+	/// the format specification, apart from the percent sign, is the type.
+	///
+	/// The optional index argument has the format "[<n>]" and allows to
+	/// address an argument by its zero-based position (see the example below).
+	///
+	/// Following are valid type specifications and their meaning:
+	///
+	///   * b boolean (true = 1, false = 0)
+	///   * c character
+	///   * d signed decimal integer
+	///   * i signed decimal integer
+	///   * o unsigned octal integer
+	///   * u unsigned decimal integer
+	///   * x unsigned hexadecimal integer (lower case)
+	///   * X unsigned hexadecimal integer (upper case)
+	///   * e signed floating-point value in the form [-]d.dddde[<sign>]dd[d]
+	///   * E signed floating-point value in the form [-]d.ddddE[<sign>]dd[d]
+	///   * f signed floating-point value in the form [-]dddd.dddd
+	///   * s std::string
+	///   * z std::size_t
+	///
+	/// The following flags are supported:
+	///
+	///   * - left align the result within the given field width
+	///   * + prefix the output value with a sign (+ or -) if the output value is of a signed type
+	///   * 0 if width is prefixed with 0, zeros are added until the minimum width is reached
+	///   * # For o, x, X, the # flag prefixes any nonzero output value with 0, 0x, or 0X, respectively; 
+	///     for e, E, f, the # flag forces the output value to contain a decimal point in all cases.
+	///
+	/// The following modifiers are supported:
+	///
+	///   * (none) argument is char (c), int (d, i), unsigned (o, u, x, X) double (e, E, f, g, G) or string (s)
+	///   * l      argument is long (d, i), unsigned long (o, u, x, X) or long double (e, E, f, g, G)
+	///   * L      argument is long long (d, i), unsigned long long (o, u, x, X)
+	///   * h      argument is short (d, i), unsigned short (o, u, x, X) or float (e, E, f, g, G)
+	///   * ?      argument is any signed or unsigned int, short, long, or 64-bit integer (d, i, o, x, X)
+	///
+	/// The width argument is a nonnegative decimal integer controlling the minimum number of characters printed.
+	/// If the number of characters in the output value is less than the specified width, blanks or
+	/// leading zeros are added, according to the specified flags (-, +, 0).
+	///
+	/// Precision is a nonnegative decimal integer, preceded by a period (.), which specifies the number of characters 
+	/// to be printed, the number of decimal places, or the number of significant digits.
+	///
+	/// Throws an InvalidArgumentException if an argument index is out of range.
+	///
+	/// Starting with release 1.4.3, an argument that does not match the format
+	/// specifier no longer results in a BadCastException. The string [ERRFMT] is 
+	/// written to the result string instead.
+	/// 
+	/// If there are more format specifiers than values, the format specifiers without a corresponding value
+	/// are copied verbatim to output.
+	///
+	/// If there are more values than format specifiers, the superfluous values are ignored.
+	///
+	/// Usage Examples:
+	///     std::string s1 = format("The answer to life, the universe, and everything is %d", 42);
+	///     std::string s2 = format("second: %[1]d, first: %[0]d", 1, 2);
+
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+std::string Foundation_API format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value);
+	/// Appends the formatted string to result.
+	
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+void Foundation_API format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+
+void Foundation_API format(std::string& result, const std::string& fmt, const std::vector<Any>& values);
+	/// Supports a variable number of arguments and is used by
+	/// all other variants of format().
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Format_INCLUDED
diff --git a/Poco/Formatter.h b/Poco/Formatter.h
new file mode 100644
index 0000000..678d594
--- /dev/null
+++ b/Poco/Formatter.h
@@ -0,0 +1,74 @@
+//
+// Formatter.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  Formatter
+//
+// Definition of the Formatter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Formatter_INCLUDED
+#define Foundation_Formatter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Configurable.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Message;
+
+
+class Foundation_API Formatter: public Configurable, public RefCountedObject
+	/// The base class for all Formatter classes.
+	///
+	/// A formatter basically takes a Message object
+	/// and formats it into a string. How the formatting
+	/// is exactly done is up to the implementation of
+	/// Formatter. For example, a very simple implementation
+	/// might simply take the message's Text (see Message::getText()).
+	/// A useful implementation should at least take the Message's
+	/// Time, Priority and Text fields and put them into a string.
+	///
+	/// The Formatter class supports the Configurable
+	/// interface, so the behaviour of certain formatters
+	/// is configurable.
+	/// 
+	/// Trivial implementations of of getProperty() and 
+	/// setProperty() are provided.
+	///
+	/// Subclasses must at least provide a format() method.
+{
+public:
+	Formatter();
+		/// Creates the formatter.
+		
+	virtual ~Formatter();
+		/// Destroys the formatter.
+
+	virtual void format(const Message& msg, std::string& text) = 0;
+		/// Formats the message and places the result in text. 
+		/// Subclasses must override this method.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Throws a PropertyNotSupportedException.
+
+	std::string getProperty(const std::string& name) const;
+		/// Throws a PropertyNotSupportedException.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Formatter_INCLUDED
diff --git a/Poco/FormattingChannel.h b/Poco/FormattingChannel.h
new file mode 100644
index 0000000..f4dfded
--- /dev/null
+++ b/Poco/FormattingChannel.h
@@ -0,0 +1,96 @@
+//
+// FormattingChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  Formatter
+//
+// Definition of the FormattingChannel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FormattingChannel_INCLUDED
+#define Foundation_FormattingChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+
+
+namespace Poco {
+
+
+class Formatter;
+
+
+class Foundation_API FormattingChannel: public Channel
+	/// The FormattingChannel is a filter channel that routes
+	/// a Message through a Formatter before passing it on
+	/// to the destination channel.
+{
+public:
+	FormattingChannel();
+		/// Creates a FormattingChannel.
+		
+	FormattingChannel(Formatter* pFormatter);
+		/// Creates a FormattingChannel and attaches a Formatter.
+		
+	FormattingChannel(Formatter* pFormatter, Channel* pChannel);
+		/// Creates a FormattingChannel and attaches a Formatter
+		/// and a Channel.
+		
+	void setFormatter(Formatter* pFormatter);
+		/// Sets the Formatter used to format the messages
+		/// before they are passed on. If null, the message
+		/// is passed on unmodified.
+		
+	Formatter* getFormatter() const;
+		/// Returns the Formatter used to format messages,
+		/// which may be null.
+
+	void setChannel(Channel* pChannel);
+		/// Sets the destination channel to which the formatted 
+		/// messages are passed on.
+		
+	Channel* getChannel() const;
+		/// Returns the channel to which the formatted
+		/// messages are passed on.
+		
+	void log(const Message& msg);
+		/// Formats the given Message using the Formatter and
+		/// passes the formatted message on to the destination
+		/// Channel.
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets or changes a configuration property.
+		///
+		/// Only the "channel" and "formatter" properties are supported, which allow
+		/// setting the target channel and formatter, respectively, via the LoggingRegistry.
+		/// The "channel" and "formatter" properties are set-only.
+		///
+		/// Unsupported properties are passed to the attached Channel.
+
+	void open();
+		/// Opens the attached channel.
+		
+	void close();
+		/// Closes the attached channel.
+
+protected:
+	~FormattingChannel();
+
+private:
+	Formatter* _pFormatter;
+	Channel* _pChannel;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FormattingChannel_INCLUDED
diff --git a/Poco/Foundation.h b/Poco/Foundation.h
new file mode 100644
index 0000000..750c777
--- /dev/null
+++ b/Poco/Foundation.h
@@ -0,0 +1,168 @@
+//
+// Foundation.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Foundation
+//
+// Basic definitions for the POCO Foundation library.
+// This file must be the first file included by every other Foundation
+// header file.
+//
+// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Foundation_INCLUDED
+#define Foundation_Foundation_INCLUDED
+
+
+//
+// Include library configuration
+//
+#include "Poco/Config.h"
+
+
+//
+// Ensure that POCO_DLL is default unless POCO_STATIC is defined
+//
+#if defined(_WIN32) && defined(_DLL)
+	#if !defined(POCO_DLL) && !defined(POCO_STATIC)
+		#define POCO_DLL
+	#endif
+#endif
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Foundation_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Foundation_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && defined(POCO_DLL)
+	#if defined(Foundation_EXPORTS)
+		#define Foundation_API __declspec(dllexport)
+	#else
+		#define Foundation_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Foundation_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Foundation_API __attribute__ ((visibility ("default")))
+	#else
+		#define Foundation_API
+	#endif
+#endif
+
+
+//
+// Automatically link Foundation library.
+//
+#if defined(_MSC_VER)
+	#if defined(POCO_DLL)
+		#if defined(_DEBUG)
+			#define POCO_LIB_SUFFIX "d.lib"
+		#else
+			#define POCO_LIB_SUFFIX ".lib"
+		#endif
+	#elif defined(_DLL)
+		#if defined(_DEBUG)
+			#define POCO_LIB_SUFFIX "mdd.lib"
+		#else
+			#define POCO_LIB_SUFFIX "md.lib"
+		#endif
+	#else
+		#if defined(_DEBUG)
+			#define POCO_LIB_SUFFIX "mtd.lib"
+		#else
+			#define POCO_LIB_SUFFIX "mt.lib"
+		#endif
+	#endif
+
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Foundation_EXPORTS)
+		#pragma comment(lib, "PocoFoundation" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+//
+// Include platform-specific definitions
+//
+#include "Poco/Platform.h"
+#if defined(_WIN32)
+	#include "Poco/Platform_WIN32.h"
+#elif defined(POCO_VXWORKS)
+	#include "Poco/Platform_VX.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+	#include "Poco/Platform_POSIX.h"
+#endif
+
+
+//
+// Include alignment settings early
+//
+#include "Poco/Alignment.h"
+
+//
+// Cleanup inconsistencies
+//
+#ifdef POCO_OS_FAMILY_WINDOWS
+	#if defined(POCO_WIN32_UTF8) && defined(POCO_NO_WSTRING)
+		#error POCO_WIN32_UTF8 and POCO_NO_WSTRING are mutually exclusive.
+	#endif
+#else
+	#ifdef POCO_WIN32_UTF8
+		#undef POCO_WIN32_UTF8
+	#endif
+#endif
+
+
+//
+// POCO_JOIN
+//
+// The following piece of macro magic joins the two
+// arguments together, even when one of the arguments is
+// itself a macro (see 16.3.1 in C++ standard).  The key
+// is that macro expansion of macro arguments does not
+// occur in POCO_DO_JOIN2 but does in POCO_DO_JOIN.
+//
+#define POCO_JOIN(X, Y) POCO_DO_JOIN(X, Y)
+#define POCO_DO_JOIN(X, Y) POCO_DO_JOIN2(X, Y)
+#define POCO_DO_JOIN2(X, Y) X##Y
+
+
+//
+// POCO_DEPRECATED
+//
+// A macro expanding to a compiler-specific clause to
+// mark a class or function as deprecated.
+//
+#if defined(POCO_NO_DEPRECATED)
+#define POCO_DEPRECATED
+#elif defined(_GNUC_)
+#define POCO_DEPRECATED __attribute__((deprecated))
+#elif defined(__clang__)
+#define POCO_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+#define POCO_DEPRECATED __declspec(deprecated)
+#else
+#define POCO_DEPRECATED
+#endif
+
+
+//
+// Pull in basic definitions
+//
+#include "Poco/Bugcheck.h"
+#include "Poco/Types.h"
+#include <string>
+
+
+#endif // Foundation_Foundation_INCLUDED
diff --git a/Poco/FunctionDelegate.h b/Poco/FunctionDelegate.h
new file mode 100644
index 0000000..9aec96d
--- /dev/null
+++ b/Poco/FunctionDelegate.h
@@ -0,0 +1,438 @@
+//
+// FunctionDelegate.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  FunctionDelegate
+//
+// Implementation of the FunctionDelegate template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FunctionDelegate_INCLUDED
+#define Foundation_FunctionDelegate_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractDelegate.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class TArgs, bool hasSender = true, bool senderIsConst = true> 
+class FunctionDelegate: public AbstractDelegate<TArgs>
+	/// Wraps a freestanding function or static member function 
+	/// for use as a Delegate.
+{
+public:
+	typedef void (*NotifyFunction)(const void*, TArgs&);
+
+	FunctionDelegate(NotifyFunction function):
+		_function(function)
+	{
+	}
+
+	FunctionDelegate(const FunctionDelegate& delegate):
+		AbstractDelegate<TArgs>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	~FunctionDelegate()
+	{
+	}
+	
+	FunctionDelegate& operator = (const FunctionDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(sender, arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+		return pOtherDelegate && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new FunctionDelegate(*this);
+	}
+	
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionDelegate();
+};
+
+
+template <class TArgs> 
+class FunctionDelegate<TArgs, true, false>: public AbstractDelegate<TArgs>
+{
+public:
+	typedef void (*NotifyFunction)(void*, TArgs&);
+
+	FunctionDelegate(NotifyFunction function):
+		_function(function)
+	{
+	}
+
+	FunctionDelegate(const FunctionDelegate& delegate):
+		AbstractDelegate<TArgs>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	~FunctionDelegate()
+	{
+	}
+	
+	FunctionDelegate& operator = (const FunctionDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(const_cast<void*>(sender), arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+		return pOtherDelegate && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new FunctionDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionDelegate();
+};
+
+
+template <class TArgs, bool senderIsConst> 
+class FunctionDelegate<TArgs, false, senderIsConst>: public AbstractDelegate<TArgs>
+{
+public:
+	typedef void (*NotifyFunction)(TArgs&);
+
+	FunctionDelegate(NotifyFunction function):
+		_function(function)
+	{
+	}
+
+	FunctionDelegate(const FunctionDelegate& delegate):
+		AbstractDelegate<TArgs>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	~FunctionDelegate()
+	{
+	}
+	
+	FunctionDelegate& operator = (const FunctionDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+		}
+		return *this;
+	}
+
+	bool notify(const void* /*sender*/, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(arguments);
+			return true; 
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+		return pOtherDelegate && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new FunctionDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionDelegate();
+};
+
+
+template <> 
+class FunctionDelegate<void, true, true>: public AbstractDelegate<void>
+	/// Wraps a freestanding function or static member function 
+	/// for use as a Delegate.
+{
+public:
+	typedef void (*NotifyFunction)(const void*);
+
+	FunctionDelegate(NotifyFunction function):
+		_function(function)
+	{
+	}
+
+	FunctionDelegate(const FunctionDelegate& delegate):
+		AbstractDelegate<void>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	~FunctionDelegate()
+	{
+	}
+	
+	FunctionDelegate& operator = (const FunctionDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(sender);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+		return pOtherDelegate && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new FunctionDelegate(*this);
+	}
+	
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionDelegate();
+};
+
+
+template <> 
+class FunctionDelegate<void, true, false>: public AbstractDelegate<void>
+{
+public:
+	typedef void (*NotifyFunction)(void*);
+
+	FunctionDelegate(NotifyFunction function):
+		_function(function)
+	{
+	}
+
+	FunctionDelegate(const FunctionDelegate& delegate):
+		AbstractDelegate<void>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	~FunctionDelegate()
+	{
+	}
+	
+	FunctionDelegate& operator = (const FunctionDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(const_cast<void*>(sender));
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+		return pOtherDelegate && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new FunctionDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionDelegate();
+};
+
+
+template <bool senderIsConst> 
+class FunctionDelegate<void, false, senderIsConst>: public AbstractDelegate<void>
+{
+public:
+	typedef void (*NotifyFunction)();
+
+	FunctionDelegate(NotifyFunction function):
+		_function(function)
+	{
+	}
+
+	FunctionDelegate(const FunctionDelegate& delegate):
+		AbstractDelegate<void>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	~FunctionDelegate()
+	{
+	}
+	
+	FunctionDelegate& operator = (const FunctionDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+		}
+		return *this;
+	}
+
+	bool notify(const void* /*sender*/)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)();
+			return true; 
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const FunctionDelegate* pOtherDelegate = dynamic_cast<const FunctionDelegate*>(other.unwrap());
+		return pOtherDelegate && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new FunctionDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionDelegate();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FunctionDelegate_INCLUDED
diff --git a/Poco/FunctionPriorityDelegate.h b/Poco/FunctionPriorityDelegate.h
new file mode 100644
index 0000000..60e6592
--- /dev/null
+++ b/Poco/FunctionPriorityDelegate.h
@@ -0,0 +1,450 @@
+//
+// FunctionPriorityDelegate.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  FunctionPriorityDelegate
+//
+// Implementation of the FunctionPriorityDelegate template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_FunctionPriorityDelegate_INCLUDED
+#define Foundation_FunctionPriorityDelegate_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractPriorityDelegate.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class TArgs, bool useSender = true, bool senderIsConst = true> 
+class FunctionPriorityDelegate: public AbstractPriorityDelegate<TArgs>
+	/// Wraps a freestanding function or static member function 
+	/// for use as a PriorityDelegate.
+{
+public:
+	typedef void (*NotifyFunction)(const void*, TArgs&);
+
+	FunctionPriorityDelegate(NotifyFunction function, int prio):
+		AbstractPriorityDelegate<TArgs>(prio),
+		_function(function)
+	{
+	}
+	
+	FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+		AbstractPriorityDelegate<TArgs>(delegate),
+		_function(delegate._function)
+	{
+	}
+	
+	FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+			this->_priority = delegate._priority;
+		}
+		return *this;
+	}
+
+	~FunctionPriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(sender, arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new FunctionPriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionPriorityDelegate();
+};
+
+
+template <class TArgs> 
+class FunctionPriorityDelegate<TArgs, true, false>: public AbstractPriorityDelegate<TArgs>
+{
+public:
+	typedef void (*NotifyFunction)(void*, TArgs&);
+
+	FunctionPriorityDelegate(NotifyFunction function, int prio):
+		AbstractPriorityDelegate<TArgs>(prio),
+		_function(function)
+	{
+	}
+	
+	FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+		AbstractPriorityDelegate<TArgs>(delegate),
+		_function(delegate._function)
+	{
+	}
+	
+	FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+			this->_priority = delegate._priority;
+		}
+		return *this;
+	}
+
+	~FunctionPriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(const_cast<void*>(sender), arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new FunctionPriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionPriorityDelegate();
+};
+
+
+template <class TArgs> 
+class FunctionPriorityDelegate<TArgs, false>: public AbstractPriorityDelegate<TArgs>
+{
+public:
+	typedef void (*NotifyFunction)(TArgs&);
+
+	FunctionPriorityDelegate(NotifyFunction function, int prio):
+		AbstractPriorityDelegate<TArgs>(prio),
+		_function(function)
+	{
+	}
+	
+	FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+		AbstractPriorityDelegate<TArgs>(delegate),
+		_function(delegate._function)
+	{
+	}
+	
+	FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+			this->_priority = delegate._priority;
+		}
+		return *this;
+	}
+
+	~FunctionPriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(arguments);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new FunctionPriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionPriorityDelegate();
+};
+
+
+template <>
+class FunctionPriorityDelegate<void, true, true>: public AbstractPriorityDelegate<void>
+	/// Wraps a freestanding function or static member function
+	/// for use as a PriorityDelegate.
+{
+public:
+	typedef void (*NotifyFunction)(const void*);
+
+	FunctionPriorityDelegate(NotifyFunction function, int prio):
+		AbstractPriorityDelegate<void>(prio),
+		_function(function)
+	{
+	}
+
+	FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+		AbstractPriorityDelegate<void>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+			this->_priority = delegate._priority;
+		}
+		return *this;
+	}
+
+	~FunctionPriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(sender);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new FunctionPriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionPriorityDelegate();
+};
+
+
+template <>
+class FunctionPriorityDelegate<void, true, false>: public AbstractPriorityDelegate<void>
+{
+public:
+	typedef void (*NotifyFunction)(void*);
+
+	FunctionPriorityDelegate(NotifyFunction function, int prio):
+		AbstractPriorityDelegate<void>(prio),
+		_function(function)
+	{
+	}
+
+	FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+		AbstractPriorityDelegate<void>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+			this->_priority = delegate._priority;
+		}
+		return *this;
+	}
+
+	~FunctionPriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)(const_cast<void*>(sender));
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new FunctionPriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionPriorityDelegate();
+};
+
+
+template <>
+class FunctionPriorityDelegate<void, false>: public AbstractPriorityDelegate<void>
+{
+public:
+	typedef void (*NotifyFunction)();
+
+	FunctionPriorityDelegate(NotifyFunction function, int prio):
+		AbstractPriorityDelegate<void>(prio),
+		_function(function)
+	{
+	}
+
+	FunctionPriorityDelegate(const FunctionPriorityDelegate& delegate):
+		AbstractPriorityDelegate<void>(delegate),
+		_function(delegate._function)
+	{
+	}
+
+	FunctionPriorityDelegate& operator = (const FunctionPriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_function = delegate._function;
+			this->_priority = delegate._priority;
+		}
+		return *this;
+	}
+
+	~FunctionPriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_function)
+		{
+			(*_function)();
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const FunctionPriorityDelegate* pOtherDelegate = dynamic_cast<const FunctionPriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _function == pOtherDelegate->_function;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new FunctionPriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_function = 0;
+	}
+
+protected:
+	NotifyFunction _function;
+	Mutex _mutex;
+
+private:
+	FunctionPriorityDelegate();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_FunctionPriorityDelegate_INCLUDED
diff --git a/Poco/Glob.h b/Poco/Glob.h
new file mode 100644
index 0000000..bdaccc6
--- /dev/null
+++ b/Poco/Glob.h
@@ -0,0 +1,152 @@
+//
+// Glob.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  Glob
+//
+// Definition of the Glob class.
+//
+// Copyright (c) 2004-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Glob_INCLUDED
+#define Foundation_Glob_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextIterator.h"
+#include <set>
+
+
+namespace Poco {
+
+
+class Path;
+
+
+class Foundation_API Glob
+	/// This class implements glob-style pattern matching
+	/// as known from Unix shells.
+	///
+	/// In the pattern string, '*' matches any sequence of characters,
+	/// '?' matches any single character, [SET] matches any single character 
+	/// in the specified set, [!SET] matches any character not in the  
+	/// specified set.
+	///
+	/// A set is composed of characters or ranges; a range looks like
+	/// character hyphen character (as in 0-9 or A-Z).
+	/// [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
+	/// Any other character in the pattern must be matched exactly.
+	///
+	/// To suppress the special syntactic significance of any of '[]*?!-\',
+	/// and match the character exactly, precede it with a backslash.
+	///
+	/// All strings are assumed to be UTF-8 encoded.
+{
+public:
+	enum Options
+		/// Flags that modify the matching behavior.
+	{
+		GLOB_DEFAULT         = 0x00, /// default behavior
+		GLOB_DOT_SPECIAL     = 0x01, /// '*' and '?' do not match '.' at beginning of subject
+		GLOB_FOLLOW_SYMLINKS = 0x02, /// follow symbolic links
+		GLOB_CASELESS        = 0x04, /// ignore case when comparing characters
+		GLOB_DIRS_ONLY       = 0x80  /// only glob for directories (for internal use only)
+	};
+	
+	Glob(const std::string& pattern, int options = 0);
+		/// Creates the Glob, using the given pattern. The pattern
+		/// must not be an empty string.
+		///
+		/// If the GLOB_DOT_SPECIAL option is specified, '*' and '?' do 
+		/// not match '.' at the beginning of a matched subject. This is useful for
+		/// making dot-files invisible in good old Unix-style.
+
+	~Glob();
+		/// Destroys the Glob.
+		
+	bool match(const std::string& subject);
+		/// Matches the given subject against the glob pattern.
+		/// Returns true if the subject matches the pattern, false
+		/// otherwise.
+		
+	static void glob(const std::string& pathPattern, std::set<std::string>& files, int options = 0);
+		/// Creates a set of files that match the given pathPattern.
+		///
+		/// The path may be give in either Unix, Windows or VMS syntax and
+		/// is automatically expanded by calling Path::expand().
+		///
+		/// The pattern may contain wildcard expressions even in intermediate
+		/// directory names (e.g. /usr/include/*/*.h).
+		///
+		/// Note that, for obvious reasons, escaping characters in a pattern
+		/// with a backslash does not work in Windows-style paths.
+		///
+		/// Directories that for whatever reason cannot be traversed are
+		/// ignored.
+
+	static void glob(const char* pathPattern, std::set<std::string>& files, int options = 0);
+		/// Creates a set of files that match the given pathPattern.
+		///
+		/// The path may be give in either Unix, Windows or VMS syntax and
+		/// is automatically expanded by calling Path::expand().
+		///
+		/// The pattern may contain wildcard expressions even in intermediate
+		/// directory names (e.g. /usr/include/*/*.h).
+		///
+		/// Note that, for obvious reasons, escaping characters in a pattern
+		/// with a backslash does not work in Windows-style paths.
+		///
+		/// Directories that for whatever reason cannot be traversed are
+		/// ignored.
+
+	static void glob(const Path& pathPattern, std::set<std::string>& files, int options = 0);
+		/// Creates a set of files that match the given pathPattern.
+		///
+		/// The pattern may contain wildcard expressions even in intermediate
+		/// directory names (e.g. /usr/include/*/*.h).
+		///
+		/// Note that, for obvious reasons, escaping characters in a pattern
+		/// with a backslash does not work in Windows-style paths.
+		///
+		/// Directories that for whatever reason cannot be traversed are
+		/// ignored.
+
+	static void glob(const Path& pathPattern, const Path& basePath, std::set<std::string>& files, int options = 0);
+		/// Creates a set of files that match the given pathPattern, starting from basePath.
+		///
+		/// The pattern may contain wildcard expressions even in intermediate
+		/// directory names (e.g. /usr/include/*/*.h).
+		///
+		/// Note that, for obvious reasons, escaping characters in a pattern
+		/// with a backslash does not work in Windows-style paths.
+		///
+		/// Directories that for whatever reason cannot be traversed are
+		/// ignored.
+
+protected:
+	bool match(TextIterator& itp, const TextIterator& endp, TextIterator& its, const TextIterator& ends);
+	bool matchAfterAsterisk(TextIterator itp, const TextIterator& endp, TextIterator its, const TextIterator& ends);
+	bool matchSet(TextIterator& itp, const TextIterator& endp, int c);
+	static void collect(const Path& pathPattern, const Path& base, const Path& current, const std::string& pattern, std::set<std::string>& files, int options);
+	static bool isDirectory(const Path& path, bool followSymlink);
+	
+private:
+	std::string _pattern;
+	int         _options;
+
+	Glob();
+	Glob(const Glob&);
+	Glob& operator = (const Glob&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Glob_INCLUDED
diff --git a/Poco/HMACEngine.h b/Poco/HMACEngine.h
new file mode 100644
index 0000000..0593e7d
--- /dev/null
+++ b/Poco/HMACEngine.h
@@ -0,0 +1,146 @@
+//
+// HMACEngine.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  HMACEngine
+//
+// Definition of the HMACEngine class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HMACEngine_INCLUDED
+#define Foundation_HMACEngine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DigestEngine.h"
+#include <cstring>
+
+
+namespace Poco {
+
+
+template <class Engine>
+class HMACEngine: public DigestEngine
+	/// This class implementes the HMAC message
+	/// authentication code algorithm, as specified
+	/// in RFC 2104. The underlying DigestEngine
+	/// (MD5Engine, SHA1Engine, etc.) must be given as 
+	/// template argument.
+	/// Since the HMACEngine is a DigestEngine, it can
+	/// be used with the DigestStream class to create
+	/// a HMAC for a stream.
+{
+public:
+	enum
+	{
+		BLOCK_SIZE  = Engine::BLOCK_SIZE,
+		DIGEST_SIZE = Engine::DIGEST_SIZE
+	};
+	
+	HMACEngine(const std::string& passphrase)
+	{
+		init(passphrase.data(), passphrase.length());
+	}
+	
+	HMACEngine(const char* passphrase, std::size_t length)
+	{
+		poco_check_ptr (passphrase);
+
+		init(passphrase, length);
+	}
+	
+	~HMACEngine()
+	{
+		std::memset(_ipad, 0, BLOCK_SIZE);
+		std::memset(_opad, 0, BLOCK_SIZE);
+		delete [] _ipad;
+		delete [] _opad;
+	}
+		
+	std::size_t digestLength() const
+	{
+		return DIGEST_SIZE;
+	}
+	
+	void reset()
+	{
+		_engine.reset();
+		_engine.update(_ipad, BLOCK_SIZE);
+	}
+	
+	const DigestEngine::Digest& digest()
+	{
+		const DigestEngine::Digest& d = _engine.digest();
+		char db[DIGEST_SIZE];
+		char* pdb = db;
+		for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end(); ++it)
+			*pdb++ = *it;
+		_engine.reset();
+		_engine.update(_opad, BLOCK_SIZE);
+		_engine.update(db, DIGEST_SIZE);
+		const DigestEngine::Digest& result = _engine.digest();
+		reset();
+		return result;
+	}
+
+protected:
+	void init(const char* passphrase, std::size_t length)
+	{
+		_ipad = new char[BLOCK_SIZE];
+		_opad = new char[BLOCK_SIZE];
+		std::memset(_ipad, 0, BLOCK_SIZE);
+		std::memset(_opad, 0, BLOCK_SIZE);
+		if (length > BLOCK_SIZE)
+		{
+			_engine.reset();
+			_engine.update(passphrase, length);
+			const DigestEngine::Digest& d = _engine.digest();
+			char* ipad = _ipad;
+			char* opad = _opad;
+			int n = BLOCK_SIZE;
+			for (DigestEngine::Digest::const_iterator it = d.begin(); it != d.end() && n-- > 0; ++it)
+			{
+				*ipad++ = *it;
+				*opad++ = *it;
+			}
+		}
+		else
+		{
+			std::memcpy(_ipad, passphrase, length);
+			std::memcpy(_opad, passphrase, length);
+		}
+		for (int i = 0; i < BLOCK_SIZE; ++i)
+		{
+			_ipad[i] ^= 0x36;
+			_opad[i] ^= 0x5c;
+		}
+		reset();
+	}
+	
+	void updateImpl(const void* data, std::size_t length)
+	{
+		_engine.update(data, length);
+	}
+
+private:
+	HMACEngine();
+	HMACEngine(const HMACEngine&);
+	HMACEngine& operator = (const HMACEngine&);
+
+	Engine _engine;
+	char*  _ipad;
+	char*  _opad;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HMACEngine_INCLUDED
diff --git a/Poco/Hash.h b/Poco/Hash.h
new file mode 100644
index 0000000..7aafb66
--- /dev/null
+++ b/Poco/Hash.h
@@ -0,0 +1,105 @@
+//
+// Hash.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  Hash
+//
+// Definition of the Hash class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Hash_INCLUDED
+#define Foundation_Hash_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <cstddef>
+
+
+namespace Poco {
+
+
+std::size_t Foundation_API hash(Int8 n);
+std::size_t Foundation_API hash(UInt8 n);
+std::size_t Foundation_API hash(Int16 n);
+std::size_t Foundation_API hash(UInt16 n);
+std::size_t Foundation_API hash(Int32 n);
+std::size_t Foundation_API hash(UInt32 n);
+std::size_t Foundation_API hash(Int64 n);
+std::size_t Foundation_API hash(UInt64 n);
+std::size_t Foundation_API hash(const std::string& str);
+
+
+template <class T>
+struct Hash
+	/// A generic hash function.
+{
+	std::size_t operator () (T value) const
+		/// Returns the hash for the given value.
+	{
+		return Poco::hash(value);
+	}
+};
+
+
+//
+// inlines
+//
+inline std::size_t hash(Int8 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(UInt8 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(Int16 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(UInt16 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(Int32 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(UInt32 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(Int64 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+inline std::size_t hash(UInt64 n)
+{
+	return static_cast<std::size_t>(n)*2654435761U; 
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Hash_INCLUDED
diff --git a/Poco/HashFunction.h b/Poco/HashFunction.h
new file mode 100644
index 0000000..c451d06
--- /dev/null
+++ b/Poco/HashFunction.h
@@ -0,0 +1,57 @@
+//
+// HashFunction.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  HashFunction
+//
+// Definition of the HashFunction class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HashFunction_INCLUDED
+#define Foundation_HashFunction_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Hash.h"
+
+
+namespace Poco {
+
+
+//@ deprecated
+template <class T>
+struct HashFunction
+	/// A generic hash function.
+{
+	UInt32 operator () (T key, UInt32 maxValue) const
+		/// Returns the hash value for the given key.
+	{
+		return static_cast<UInt32>(Poco::hash(key)) % maxValue;
+	}
+};
+
+
+//@ deprecated
+template <>
+struct HashFunction<std::string>
+	/// A generic hash function.
+{
+	UInt32 operator () (const std::string& key, UInt32 maxValue) const
+		/// Returns the hash value for the given key.
+	{
+		return static_cast<UInt32>(Poco::hash(key)) % maxValue;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HashFunctions_INCLUDED
diff --git a/Poco/HashMap.h b/Poco/HashMap.h
new file mode 100644
index 0000000..5153f2b
--- /dev/null
+++ b/Poco/HashMap.h
@@ -0,0 +1,228 @@
+//
+// HashMap.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  HashMap
+//
+// Definition of the HashMap class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HashMap_INCLUDED
+#define Foundation_HashMap_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/LinearHashTable.h"
+#include "Poco/Exception.h"
+#include <utility>
+
+
+namespace Poco {
+
+
+template <class Key, class Value>
+struct HashMapEntry
+	/// This class template is used internally by HashMap.
+{
+	Key   first;
+	Value second;
+	
+	HashMapEntry():
+		first(),
+		second()
+	{
+	}
+	
+	HashMapEntry(const Key& key):
+		first(key),
+		second()
+	{
+	}
+
+	HashMapEntry(const Key& key, const Value& value):
+		first(key),
+		second(value)
+	{
+	}
+	
+	bool operator == (const HashMapEntry& entry) const
+	{
+		return first == entry.first;
+	}
+
+	bool operator != (const HashMapEntry& entry) const
+	{
+		return first != entry.first;
+	}
+};
+
+
+template <class HME, class KeyHashFunc>
+struct HashMapEntryHash
+	/// This class template is used internally by HashMap.
+{
+	std::size_t operator () (const HME& entry) const
+	{
+		return _func(entry.first);
+	}
+
+private:
+	KeyHashFunc _func;
+};
+
+
+template <class Key, class Mapped, class HashFunc = Hash<Key> >
+class HashMap
+	/// This class implements a map using a LinearHashTable.
+	///
+	/// A HashMap can be used just like a std::map.
+{
+public:
+	typedef Key                 KeyType;
+	typedef Mapped              MappedType;
+	typedef Mapped&             Reference;
+	typedef const Mapped&       ConstReference;
+	typedef Mapped*             Pointer;
+	typedef const Mapped*       ConstPointer;
+	
+	typedef HashMapEntry<Key, Mapped>      ValueType;
+	typedef std::pair<KeyType, MappedType> PairType;
+	
+	typedef HashMapEntryHash<ValueType, HashFunc> HashType;
+	typedef LinearHashTable<ValueType, HashType>  HashTable;
+	
+	typedef typename HashTable::Iterator      Iterator;
+	typedef typename HashTable::ConstIterator ConstIterator;
+	
+	HashMap()
+		/// Creates an empty HashMap.
+	{
+	}
+	
+	HashMap(std::size_t initialReserve):
+		_table(initialReserve)
+		/// Creates the HashMap with room for initialReserve entries.
+	{
+	}
+	
+	HashMap& operator = (const HashMap& map)
+		/// Assigns another HashMap.
+	{
+		HashMap tmp(map);
+		swap(tmp);
+		return *this;
+	}
+	
+	void swap(HashMap& map)
+		/// Swaps the HashMap with another one.
+	{
+		_table.swap(map._table);
+	}
+	
+	ConstIterator begin() const
+	{
+		return _table.begin();
+	}
+	
+	ConstIterator end() const
+	{
+		return _table.end();
+	}
+	
+	Iterator begin()
+	{
+		return _table.begin();
+	}
+	
+	Iterator end()
+	{
+		return _table.end();
+	}
+	
+	ConstIterator find(const KeyType& key) const
+	{
+		ValueType value(key);
+		return _table.find(value);
+	}
+
+	Iterator find(const KeyType& key)
+	{
+		ValueType value(key);
+		return _table.find(value);
+	}
+
+	std::size_t count(const KeyType& key) const
+	{
+		ValueType value(key);
+		return _table.find(value) != _table.end() ? 1 : 0;
+	}
+
+	std::pair<Iterator, bool> insert(const PairType& pair)
+	{
+		ValueType value(pair.first, pair.second);
+		return _table.insert(value);
+	}
+
+	std::pair<Iterator, bool> insert(const ValueType& value)
+	{
+		return _table.insert(value);
+	}
+	
+	void erase(Iterator it)
+	{
+		_table.erase(it);
+	}
+	
+	void erase(const KeyType& key)
+	{
+		Iterator it = find(key);
+		_table.erase(it);
+	}
+	
+	void clear()
+	{
+		_table.clear();
+	}
+
+	std::size_t size() const
+	{
+		return _table.size();
+	}
+
+	bool empty() const
+	{
+		return _table.empty();
+	}
+
+	ConstReference operator [] (const KeyType& key) const
+	{
+		ConstIterator it = _table.find(key);
+		if (it != _table.end())
+			return it->second;
+		else
+			throw NotFoundException();
+	}
+
+	Reference operator [] (const KeyType& key)
+	{
+		ValueType value(key);
+		std::pair<Iterator, bool> res = _table.insert(value);
+		return res.first->second;
+	}
+
+private:
+	HashTable _table;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HashMap_INCLUDED
diff --git a/Poco/HashSet.h b/Poco/HashSet.h
new file mode 100644
index 0000000..e24560c
--- /dev/null
+++ b/Poco/HashSet.h
@@ -0,0 +1,177 @@
+//
+// HashSet.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  HashSet
+//
+// Definition of the HashSet class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HashSet_INCLUDED
+#define Foundation_HashSet_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/LinearHashTable.h"
+
+
+namespace Poco {
+
+
+template <class Value, class HashFunc = Hash<Value> >
+class HashSet
+	/// This class implements a set using a LinearHashTable.
+	///
+	/// A HashSet can be used just like a std::set.
+{
+public:
+	typedef Value        ValueType;
+	typedef Value&       Reference;
+	typedef const Value& ConstReference;
+	typedef Value*       Pointer;
+	typedef const Value* ConstPointer;
+	typedef HashFunc     Hash;
+	
+	typedef LinearHashTable<ValueType, Hash> HashTable;
+	
+	typedef typename HashTable::Iterator      Iterator;
+	typedef typename HashTable::ConstIterator ConstIterator;
+
+	HashSet()
+		/// Creates an empty HashSet.
+	{
+	}
+
+	HashSet(std::size_t initialReserve): 
+		_table(initialReserve)
+		/// Creates the HashSet, using the given initialReserve.
+	{
+	}
+	
+	HashSet(const HashSet& set):
+		_table(set._table)
+		/// Creates the HashSet by copying another one.
+	{
+	}
+	
+	~HashSet()
+		/// Destroys the HashSet.
+	{
+	}
+	
+	HashSet& operator = (const HashSet& table)
+		/// Assigns another HashSet.
+	{
+		HashSet tmp(table);
+		swap(tmp);
+		return *this;
+	}
+	
+	void swap(HashSet& set)
+		/// Swaps the HashSet with another one.
+	{
+		_table.swap(set._table);
+	}
+	
+	ConstIterator begin() const
+		/// Returns an iterator pointing to the first entry, if one exists.
+	{
+		return _table.begin();
+	}
+	
+	ConstIterator end() const
+		/// Returns an iterator pointing to the end of the table.
+	{
+		return _table.end();
+	}
+	
+	Iterator begin()
+		/// Returns an iterator pointing to the first entry, if one exists.
+	{
+		return _table.begin();
+	}
+	
+	Iterator end()
+		/// Returns an iterator pointing to the end of the table.
+	{
+		return _table.end();
+	}
+		
+	ConstIterator find(const ValueType& value) const
+		/// Finds an entry in the table.
+	{
+		return _table.find(value);
+	}
+
+	Iterator find(const ValueType& value)
+		/// Finds an entry in the table.
+	{
+		return _table.find(value);
+	}
+	
+	std::size_t count(const ValueType& value) const
+		/// Returns the number of elements with the given
+		/// value, with is either 1 or 0.
+	{
+		return _table.count(value);
+	}
+	
+	std::pair<Iterator, bool> insert(const ValueType& value)
+		/// Inserts an element into the set.
+		///
+		/// If the element already exists in the set,
+		/// a pair(iterator, false) with iterator pointing to the 
+		/// existing element is returned.
+		/// Otherwise, the element is inserted an a 
+		/// pair(iterator, true) with iterator
+		/// pointing to the new element is returned.
+	{
+		return _table.insert(value);
+	}
+	
+	void erase(Iterator it)
+		/// Erases the element pointed to by it.
+	{
+		_table.erase(it);
+	}
+	
+	void erase(const ValueType& value)
+		/// Erases the element with the given value, if it exists.
+	{
+		_table.erase(value);
+	}
+	
+	void clear()
+		/// Erases all elements.
+	{
+		_table.clear();
+	}
+	
+	std::size_t size() const
+		/// Returns the number of elements in the table.
+	{
+		return _table.size();
+	}
+	
+	bool empty() const
+		/// Returns true iff the table is empty.
+	{
+		return _table.empty();
+	}
+
+private:
+	HashTable _table;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HashSet_INCLUDED
diff --git a/Poco/HashStatistic.h b/Poco/HashStatistic.h
new file mode 100644
index 0000000..ac413fb
--- /dev/null
+++ b/Poco/HashStatistic.h
@@ -0,0 +1,126 @@
+//
+// HashStatistic.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  HashStatistic
+//
+// Definition of the HashStatistic class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HashStatistic_INCLUDED
+#define Foundation_HashStatistic_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+//@ deprecated
+class Foundation_API HashStatistic
+	/// HashStatistic class bundles statistical information on the current state of a HashTable
+{
+public:
+	HashStatistic(
+		UInt32 tableSize, 
+		UInt32 numEntries, 
+		UInt32 numZeroEntries, 
+		UInt32 maxEntry, 
+		std::vector<UInt32> details = std::vector<UInt32>());
+		/// Creates the HashStatistic.
+
+	virtual ~HashStatistic();
+		/// Destroys the HashStatistic.
+
+	UInt32 maxPositionsOfTable() const;
+		/// Returns the maximum number of different hash values possible for the table
+
+	UInt32 numberOfEntries() const;
+		/// Returns the total number of entries currently stored in the HashTable
+
+	UInt32 numberOfZeroPositions() const;
+		/// Returns the number of hash positions that contain no entry.
+
+	double avgEntriesPerHash() const;
+		/// Returns the average number of entries per position in the Hashtable, the higher this value the less efficient
+		/// performs hashing. If a large value is returned and getNumberOfZeroPositions also returns a large value, this
+		/// indicates an inefficient hashing function. If the number of zero entries is low, resizing the HashTable, should
+		/// be enough to improve performance
+
+	double avgEntriesPerHashExclZeroEntries() const;
+		/// Same as getAvgEntriesPerHash but hash values that contain no entry are ignored,
+		/// getAvgEntriesPerHashExclZeroEntries >= getAvgEntriesPerHash will always be true.
+
+	UInt32 maxEntriesPerHash() const;
+		/// Returns the maximum number of entries per hash value found in the current table.
+
+	const std::vector<UInt32> detailedEntriesPerHash() const;
+		/// Will either be an empty vector or will contain for each possible hash value, the number of entries currently stored
+
+	std::string toString() const;
+		/// Converts the whole data structure into a string.
+
+private:
+	UInt32 _sizeOfTable;
+	UInt32 _numberOfEntries;
+	UInt32 _numZeroEntries;
+	UInt32 _maxEntriesPerHash;
+	std::vector<UInt32> _detailedEntriesPerHash;
+};
+
+
+inline UInt32 HashStatistic::maxPositionsOfTable() const
+{
+	return _sizeOfTable;
+}
+
+
+inline UInt32 HashStatistic::numberOfEntries() const
+{
+	return _numberOfEntries;
+}
+
+
+inline UInt32 HashStatistic::numberOfZeroPositions() const
+{
+	return _numZeroEntries;
+}
+
+
+inline double HashStatistic::avgEntriesPerHash() const
+{
+	return ((double) numberOfEntries()) / maxPositionsOfTable();
+}
+
+
+inline double HashStatistic::avgEntriesPerHashExclZeroEntries() const
+{
+	return ((double) numberOfEntries()) / (maxPositionsOfTable() - numberOfZeroPositions());
+}
+
+
+inline UInt32 HashStatistic::maxEntriesPerHash() const
+{
+	return _maxEntriesPerHash;
+}
+
+
+inline const std::vector<UInt32> HashStatistic::detailedEntriesPerHash() const
+{
+	return _detailedEntriesPerHash;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HashStatistic_INCLUDED
diff --git a/Poco/HashTable.h b/Poco/HashTable.h
new file mode 100644
index 0000000..e71af1e
--- /dev/null
+++ b/Poco/HashTable.h
@@ -0,0 +1,369 @@
+//
+// HashTable.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  HashTable
+//
+// Definition of the HashTable class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HashTable_INCLUDED
+#define Foundation_HashTable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/HashFunction.h"
+#include "Poco/HashStatistic.h"
+#include <vector>
+#include <map>
+#include <cstddef>
+#include <cstring>
+
+
+namespace Poco {
+
+
+//@ deprecated
+template <class Key, class Value, class KeyHashFunction = HashFunction<Key> >
+class HashTable
+	/// A HashTable stores a key value pair that can be looked up via a hashed key.
+	///
+	/// Collision handling is done via overflow maps(!). With small hash tables performance of this
+	/// data struct will be closer to that a map than a hash table, i.e. slower. On the plus side,
+	/// this class offers remove operations. Also HashTable full errors are not possible. If a fast
+	/// HashTable implementation is needed and the remove operation is not required, use SimpleHashTable
+	/// instead.
+	///
+	/// This class is NOT thread safe.
+{
+public:
+	typedef std::map<Key, Value> HashEntryMap;
+	typedef HashEntryMap**       HashTableVector;
+
+	typedef typename HashEntryMap::const_iterator ConstIterator;
+	typedef typename HashEntryMap::iterator Iterator;
+
+	HashTable(UInt32 initialSize = 251): 
+		_entries(0), 
+		_size(0), 
+		_maxCapacity(initialSize)
+		/// Creates the HashTable.
+	{
+		_entries = new HashEntryMap*[initialSize];
+		memset(_entries, '\0', sizeof(HashEntryMap*)*initialSize);
+	}
+
+	HashTable(const HashTable& ht):
+		_entries(new HashEntryMap*[ht._maxCapacity]),
+		_size(ht._size),
+		_maxCapacity(ht._maxCapacity)
+	{
+		for (UInt32 i = 0; i < _maxCapacity; ++i)
+		{
+			if (ht._entries[i])
+				_entries[i] = new HashEntryMap(ht._entries[i]->begin(), ht._entries[i]->end());
+			else
+				_entries[i] = 0;
+		}
+	}
+
+	~HashTable()
+		/// Destroys the HashTable.
+	{
+		clear();
+	}
+
+	HashTable& operator = (const HashTable& ht)
+	{
+		if (this != &ht)
+		{
+			clear();
+			_maxCapacity = ht._maxCapacity;
+			poco_assert_dbg (_entries == 0);
+			_entries = new HashEntryMap*[_maxCapacity];
+			_size = ht._size;
+
+			for (UInt32 i = 0; i < _maxCapacity; ++i)
+			{
+				if (ht._entries[i])
+					_entries[i] = new HashEntryMap(ht._entries[i]->begin(), ht._entries[i]->end());
+				else
+					_entries[i] = 0;
+			}
+		}
+		return *this;
+	}
+
+	void clear()
+	{
+		if (!_entries)
+			return;
+		for (UInt32 i = 0; i < _maxCapacity; ++i)
+		{
+			delete _entries[i];
+		}
+		delete[] _entries;
+		_entries     = 0;
+		_size        = 0;
+		_maxCapacity = 0;
+	}
+
+	UInt32 insert(const Key& key, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Throws an exception if the entry was already inserted
+	{
+		UInt32 hsh = hash(key);
+		insertRaw(key, hsh, value);
+		return hsh;
+	}
+
+	Value& insertRaw(const Key& key, UInt32 hsh, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Throws an exception if the entry was already inserted
+	{
+		if (!_entries[hsh])
+			_entries[hsh] = new HashEntryMap();
+		std::pair<typename HashEntryMap::iterator, bool> res(_entries[hsh]->insert(std::make_pair(key, value)));
+		if (!res.second)
+			throw InvalidArgumentException("HashTable::insert, key already exists.");
+		_size++;
+		return res.first->second;
+	}
+
+	UInt32 update(const Key& key, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Replaces an existing entry if it finds one
+	{
+		UInt32 hsh = hash(key);
+		updateRaw(key, hsh, value);
+		return hsh;
+	}
+
+	void updateRaw(const Key& key, UInt32 hsh, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Replaces an existing entry if it finds one
+	{
+		if (!_entries[hsh])
+			_entries[hsh] = new HashEntryMap();
+		std::pair<Iterator, bool> res = _entries[hsh]->insert(std::make_pair(key, value));
+		if (res.second == false)
+			res.first->second = value;
+		else
+			_size++;
+	}
+
+	void remove(const Key& key)
+	{
+		UInt32 hsh = hash(key);
+		removeRaw(key, hsh);
+	}
+
+	void removeRaw(const Key& key, UInt32 hsh)
+		/// Performance version, allows to specify the hash value
+	{
+		if (_entries[hsh])
+		{
+			_size -= _entries[hsh]->erase(key);
+		}
+	}
+
+	UInt32 hash(const Key& key) const
+	{
+		return _hash(key, _maxCapacity);
+	}
+
+	const Value& get(const Key& key) const
+		/// Throws an exception if the value does not exist
+	{
+		UInt32 hsh = hash(key);
+		return getRaw(key, hsh);
+	}
+
+	const Value& getRaw(const Key& key, UInt32 hsh) const
+		/// Throws an exception if the value does not exist
+	{
+		if (!_entries[hsh])
+			throw InvalidArgumentException("key not found");
+
+		ConstIterator it = _entries[hsh]->find(key);
+		if (it == _entries[hsh]->end())
+			throw InvalidArgumentException("key not found");
+
+		return it->second;
+	}
+
+	Value& get(const Key& key)
+		/// Throws an exception if the value does not exist
+	{
+		UInt32 hsh = hash(key);
+		return const_cast<Value&>(getRaw(key, hsh));
+	}
+
+	const Value& operator [] (const Key& key) const
+	{
+		return get(key);
+	}
+	
+	Value& operator [] (const Key& key)
+	{
+		UInt32 hsh = hash(key);
+
+		if (!_entries[hsh])
+			return insertRaw(key, hsh, Value());
+			
+		ConstIterator it = _entries[hsh]->find(key);
+		if (it == _entries[hsh]->end())
+			return insertRaw(key, hsh, Value());
+
+		return it->second;
+	}
+	
+	const Key& getKeyRaw(const Key& key, UInt32 hsh)
+		/// Throws an exception if the key does not exist. returns a reference to the internally
+		/// stored key. Useful when someone does an insert and wants for performance reason only to store
+		/// a pointer to the key in another collection
+	{
+		if (!_entries[hsh])
+			throw InvalidArgumentException("key not found");
+		ConstIterator it = _entries[hsh]->find(key);
+		if (it == _entries[hsh]->end())
+			throw InvalidArgumentException("key not found");
+		return it->first;
+	}
+
+	bool get(const Key& key, Value& v) const
+		/// Sets v to the found value, returns false if no value was found
+	{
+		UInt32 hsh = hash(key);
+		return getRaw(key, hsh, v);
+	}
+
+	bool getRaw(const Key& key, UInt32 hsh, Value& v) const
+		/// Sets v to the found value, returns false if no value was found
+	{
+		if (!_entries[hsh])
+			return false;
+
+		ConstIterator it = _entries[hsh]->find(key);
+		if (it == _entries[hsh]->end())
+			return false;
+
+		v = it->second;
+		return true;
+	}
+
+	bool exists(const Key& key)
+	{
+		UInt32 hsh = hash(key);
+		return existsRaw(key, hsh);
+	}
+
+	bool existsRaw(const Key& key, UInt32 hsh)
+	{
+		return _entries[hsh] && (_entries[hsh]->end() != _entries[hsh]->find(key));
+	}
+
+	std::size_t size() const
+		/// Returns the number of elements already inserted into the HashTable
+	{
+		return _size;
+	}
+	
+	UInt32 maxCapacity() const
+	{
+		return _maxCapacity;
+	}
+
+	void resize(UInt32 newSize)
+		/// Resizes the hashtable, rehashes all existing entries. Expensive!
+	{
+		if (_maxCapacity != newSize)
+		{
+			HashTableVector cpy = _entries;
+			_entries = 0;
+			UInt32 oldSize = _maxCapacity;
+			_maxCapacity = newSize;
+			_entries = new HashEntryMap*[_maxCapacity];
+			memset(_entries, '\0', sizeof(HashEntryMap*)*_maxCapacity);
+
+			if (_size == 0)
+			{
+				// no data was yet inserted
+				delete[] cpy;
+				return;
+			}
+			_size = 0;
+			for (UInt32 i = 0; i < oldSize; ++i)
+			{
+				if (cpy[i])
+				{
+					ConstIterator it = cpy[i]->begin();
+					ConstIterator itEnd = cpy[i]->end();
+					for (; it != itEnd; ++it)
+					{
+						insert(it->first, it->second);
+					}
+					delete cpy[i];
+				}
+			}
+			delete[] cpy;
+		}
+	}
+
+	HashStatistic currentState(bool details = false) const
+		/// Returns the current internal state
+	{
+		UInt32 numberOfEntries = (UInt32)_size;
+		UInt32 numZeroEntries = 0;
+		UInt32 maxEntriesPerHash = 0;
+		std::vector<UInt32> detailedEntriesPerHash;
+	#ifdef _DEBUG
+		UInt32 totalSize = 0;
+	#endif
+		for (UInt32 i = 0; i < _maxCapacity; ++i)
+		{
+			if (_entries[i])
+			{
+				UInt32 size = (UInt32)_entries[i]->size();
+				poco_assert_dbg(size != 0);
+				if (size > maxEntriesPerHash)
+					maxEntriesPerHash = size;
+				if (details)
+					detailedEntriesPerHash.push_back(size);
+	#ifdef _DEBUG
+				totalSize += size;
+	#endif
+			}
+			else
+			{
+				numZeroEntries++;
+				if (details)
+					detailedEntriesPerHash.push_back(0);
+			}
+		}
+	#ifdef _DEBUG
+		poco_assert_dbg(totalSize == numberOfEntries);
+	#endif
+		return HashStatistic(_maxCapacity, numberOfEntries, numZeroEntries, maxEntriesPerHash, detailedEntriesPerHash);
+	}
+
+private:
+	HashTableVector _entries;
+	std::size_t     _size;
+	UInt32          _maxCapacity;
+	KeyHashFunction _hash;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HashTable_INCLUDED
diff --git a/Poco/HexBinaryDecoder.h b/Poco/HexBinaryDecoder.h
new file mode 100644
index 0000000..7aab0f6
--- /dev/null
+++ b/Poco/HexBinaryDecoder.h
@@ -0,0 +1,94 @@
+//
+// HexBinaryDecoder.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  HexBinary
+//
+// Definition of the HexBinaryDecoder class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HexBinaryDecoder_INCLUDED
+#define Foundation_HexBinaryDecoder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class Foundation_API HexBinaryDecoderBuf: public UnbufferedStreamBuf
+	/// This streambuf decodes all hexBinary-encoded data read
+	/// from the istream connected to it.
+	/// In hexBinary encoding, each binary octet is encoded as a character tuple,  
+	/// consisting of two hexadecimal digits ([0-9a-fA-F]) representing the octet code.
+	/// See also: XML Schema Part 2: Datatypes (http://www.w3.org/TR/xmlschema-2/),
+	/// section 3.2.15.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	HexBinaryDecoderBuf(std::istream& istr);
+	~HexBinaryDecoderBuf();
+	
+private:
+	int readFromDevice();
+	int readOne();
+
+	std::streambuf& _buf;
+};
+
+
+class Foundation_API HexBinaryDecoderIOS: public virtual std::ios
+	/// The base class for HexBinaryDecoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	HexBinaryDecoderIOS(std::istream& istr);
+	~HexBinaryDecoderIOS();
+	HexBinaryDecoderBuf* rdbuf();
+
+protected:
+	HexBinaryDecoderBuf _buf;
+};
+
+
+class Foundation_API HexBinaryDecoder: public HexBinaryDecoderIOS, public std::istream
+	/// This istream decodes all hexBinary-encoded data read
+	/// from the istream connected to it.
+	/// In hexBinary encoding, each binary octet is encoded as a character tuple,  
+	/// consisting of two hexadecimal digits ([0-9a-fA-F]) representing the octet code.
+	/// See also: XML Schema Part 2: Datatypes (http://www.w3.org/TR/xmlschema-2/),
+	/// section 3.2.15.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	HexBinaryDecoder(std::istream& istr);
+	~HexBinaryDecoder();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HexBinaryDecoder_INCLUDED
diff --git a/Poco/HexBinaryEncoder.h b/Poco/HexBinaryEncoder.h
new file mode 100644
index 0000000..453c3cd
--- /dev/null
+++ b/Poco/HexBinaryEncoder.h
@@ -0,0 +1,117 @@
+//
+// HexBinaryEncoder.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  HexBinary
+//
+// Definition of the HexBinaryEncoder class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_HexBinaryEncoder_INCLUDED
+#define Foundation_HexBinaryEncoder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API HexBinaryEncoderBuf: public UnbufferedStreamBuf
+	/// This streambuf encodes all data written
+	/// to it in hexBinary encoding and forwards it to a connected
+	/// ostream. 
+	/// In hexBinary encoding, each binary octet is encoded as a character tuple,  
+	/// consisting of two hexadecimal digits ([0-9a-fA-F]) representing the octet code.
+	/// See also: XML Schema Part 2: Datatypes (http://www.w3.org/TR/xmlschema-2/),
+	/// section 3.2.15.
+	///
+	/// Note: The characters are directly written
+	/// to the ostream's streambuf, thus bypassing
+	/// the ostream. The ostream's state is therefore
+	/// not updated to match the buffer's state.
+{
+public:
+	HexBinaryEncoderBuf(std::ostream& ostr);
+	~HexBinaryEncoderBuf();
+	
+	int close();
+		/// Closes the stream buffer.
+	
+	void setLineLength(int lineLength);
+		/// Specify the line length.
+		///
+		/// After the given number of characters have been written, 
+		/// a newline character will be written.
+		///
+		/// Specify 0 for an unlimited line length.
+		
+	int getLineLength() const;
+		/// Returns the currently set line length.
+		
+	void setUppercase(bool flag = true);
+		/// Specify whether hex digits a-f are written in upper or lower case.
+	
+private:
+	int writeToDevice(char c);
+
+	int _pos;
+	int _lineLength;
+	int _uppercase;
+	std::streambuf& _buf;
+};
+
+
+class Foundation_API HexBinaryEncoderIOS: public virtual std::ios
+	/// The base class for HexBinaryEncoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	HexBinaryEncoderIOS(std::ostream& ostr);
+	~HexBinaryEncoderIOS();
+	int close();
+	HexBinaryEncoderBuf* rdbuf();
+
+protected:
+	HexBinaryEncoderBuf _buf;
+};
+
+
+class Foundation_API HexBinaryEncoder: public HexBinaryEncoderIOS, public std::ostream
+	/// This ostream encodes all data
+	/// written to it in BinHex encoding and forwards it to
+	/// a connected ostream.
+	/// Always call close() when done
+	/// writing data, to ensure proper
+	/// completion of the encoding operation.
+	/// In hexBinary encoding, each binary octet is encoded as a character tuple,  
+	/// consisting of two hexadecimal digits ([0-9a-fA-F]) representing the octet code.
+	/// See also: XML Schema Part 2: Datatypes (http://www.w3.org/TR/xmlschema-2/),
+	/// section 3.2.15.
+	///
+	/// Note: The characters are directly written
+	/// to the ostream's streambuf, thus bypassing
+	/// the ostream. The ostream's state is therefore
+	/// not updated to match the buffer's state.
+{
+public:
+	HexBinaryEncoder(std::ostream& ostr);
+	~HexBinaryEncoder();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HexBinaryEncoder_INCLUDED
diff --git a/Poco/ISO8859_10Encoding.h b/Poco/ISO8859_10Encoding.h
new file mode 100644
index 0000000..6c6687b
--- /dev/null
+++ b/Poco/ISO8859_10Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_10Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_10Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_10Encoding_INCLUDED
+#define Encodings_ISO8859_10Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_10Encoding: public DoubleByteEncoding
+	/// ISO-8859-10 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT.
+{
+public:
+	ISO8859_10Encoding();
+	~ISO8859_10Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_10Encoding_INCLUDED
diff --git a/Poco/ISO8859_11Encoding.h b/Poco/ISO8859_11Encoding.h
new file mode 100644
index 0000000..c5cd323
--- /dev/null
+++ b/Poco/ISO8859_11Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_11Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_11Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_11Encoding_INCLUDED
+#define Encodings_ISO8859_11Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_11Encoding: public DoubleByteEncoding
+	/// ISO-8859-11 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-11.TXT.
+{
+public:
+	ISO8859_11Encoding();
+	~ISO8859_11Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_11Encoding_INCLUDED
diff --git a/Poco/ISO8859_13Encoding.h b/Poco/ISO8859_13Encoding.h
new file mode 100644
index 0000000..aa39533
--- /dev/null
+++ b/Poco/ISO8859_13Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_13Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_13Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_13Encoding_INCLUDED
+#define Encodings_ISO8859_13Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_13Encoding: public DoubleByteEncoding
+	/// ISO-8859-13 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT.
+{
+public:
+	ISO8859_13Encoding();
+	~ISO8859_13Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_13Encoding_INCLUDED
diff --git a/Poco/ISO8859_14Encoding.h b/Poco/ISO8859_14Encoding.h
new file mode 100644
index 0000000..4d0e00b
--- /dev/null
+++ b/Poco/ISO8859_14Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_14Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_14Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_14Encoding_INCLUDED
+#define Encodings_ISO8859_14Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_14Encoding: public DoubleByteEncoding
+	/// ISO-8859-14 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT.
+{
+public:
+	ISO8859_14Encoding();
+	~ISO8859_14Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_14Encoding_INCLUDED
diff --git a/Poco/ISO8859_16Encoding.h b/Poco/ISO8859_16Encoding.h
new file mode 100644
index 0000000..d5e8b98
--- /dev/null
+++ b/Poco/ISO8859_16Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_16Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_16Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_16Encoding_INCLUDED
+#define Encodings_ISO8859_16Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_16Encoding: public DoubleByteEncoding
+	/// ISO-8859-16 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-16.TXT.
+{
+public:
+	ISO8859_16Encoding();
+	~ISO8859_16Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_16Encoding_INCLUDED
diff --git a/Poco/ISO8859_3Encoding.h b/Poco/ISO8859_3Encoding.h
new file mode 100644
index 0000000..471fd16
--- /dev/null
+++ b/Poco/ISO8859_3Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_3Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_3Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_3Encoding_INCLUDED
+#define Encodings_ISO8859_3Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_3Encoding: public DoubleByteEncoding
+	/// ISO-8859-3 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT.
+{
+public:
+	ISO8859_3Encoding();
+	~ISO8859_3Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_3Encoding_INCLUDED
diff --git a/Poco/ISO8859_4Encoding.h b/Poco/ISO8859_4Encoding.h
new file mode 100644
index 0000000..50af460
--- /dev/null
+++ b/Poco/ISO8859_4Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_4Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_4Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_4Encoding_INCLUDED
+#define Encodings_ISO8859_4Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_4Encoding: public DoubleByteEncoding
+	/// ISO-8859-4 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT.
+{
+public:
+	ISO8859_4Encoding();
+	~ISO8859_4Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_4Encoding_INCLUDED
diff --git a/Poco/ISO8859_5Encoding.h b/Poco/ISO8859_5Encoding.h
new file mode 100644
index 0000000..b8a81ee
--- /dev/null
+++ b/Poco/ISO8859_5Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_5Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_5Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_5Encoding_INCLUDED
+#define Encodings_ISO8859_5Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_5Encoding: public DoubleByteEncoding
+	/// ISO-8859-5 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT.
+{
+public:
+	ISO8859_5Encoding();
+	~ISO8859_5Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_5Encoding_INCLUDED
diff --git a/Poco/ISO8859_6Encoding.h b/Poco/ISO8859_6Encoding.h
new file mode 100644
index 0000000..4cac110
--- /dev/null
+++ b/Poco/ISO8859_6Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_6Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_6Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_6Encoding_INCLUDED
+#define Encodings_ISO8859_6Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_6Encoding: public DoubleByteEncoding
+	/// ISO-8859-6 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT.
+{
+public:
+	ISO8859_6Encoding();
+	~ISO8859_6Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_6Encoding_INCLUDED
diff --git a/Poco/ISO8859_7Encoding.h b/Poco/ISO8859_7Encoding.h
new file mode 100644
index 0000000..d672405
--- /dev/null
+++ b/Poco/ISO8859_7Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_7Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_7Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_7Encoding_INCLUDED
+#define Encodings_ISO8859_7Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_7Encoding: public DoubleByteEncoding
+	/// ISO-8859-7 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT.
+{
+public:
+	ISO8859_7Encoding();
+	~ISO8859_7Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_7Encoding_INCLUDED
diff --git a/Poco/ISO8859_8Encoding.h b/Poco/ISO8859_8Encoding.h
new file mode 100644
index 0000000..0ccc6e4
--- /dev/null
+++ b/Poco/ISO8859_8Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_8Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_8Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_8Encoding_INCLUDED
+#define Encodings_ISO8859_8Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_8Encoding: public DoubleByteEncoding
+	/// ISO-8859-8 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT.
+{
+public:
+	ISO8859_8Encoding();
+	~ISO8859_8Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_8Encoding_INCLUDED
diff --git a/Poco/ISO8859_9Encoding.h b/Poco/ISO8859_9Encoding.h
new file mode 100644
index 0000000..3be8acf
--- /dev/null
+++ b/Poco/ISO8859_9Encoding.h
@@ -0,0 +1,48 @@
+//
+// ISO8859_9Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  ISO8859_9Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_ISO8859_9Encoding_INCLUDED
+#define Encodings_ISO8859_9Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API ISO8859_9Encoding: public DoubleByteEncoding
+	/// ISO-8859-9 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT.
+{
+public:
+	ISO8859_9Encoding();
+	~ISO8859_9Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_ISO8859_9Encoding_INCLUDED
diff --git a/Poco/InflatingStream.h b/Poco/InflatingStream.h
new file mode 100644
index 0000000..6e66faf
--- /dev/null
+++ b/Poco/InflatingStream.h
@@ -0,0 +1,211 @@
+//
+// InflatingStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  ZLibStream
+//
+// Definition of the InflatingInputStream and InflatingOutputStream classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_InflatingStream_INCLUDED
+#define Foundation_InflatingStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+#if defined(POCO_UNBUNDLED)
+#include <zlib.h>
+#else
+#include "Poco/zlib.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API InflatingStreamBuf: public BufferedStreamBuf
+	/// This is the streambuf class used by InflatingInputStream and InflatingOutputStream.
+	/// The actual work is delegated to zlib (see http://zlib.net).
+	/// Both zlib (deflate) streams and gzip streams are supported.
+	/// Output streams should always call close() to ensure
+	/// proper completion of decompression.
+{
+public:
+	enum StreamType
+	{
+		STREAM_ZLIB, /// Expect a zlib header, use Adler-32 checksum.
+		STREAM_GZIP, /// Expect a gzip header, use CRC-32 checksum.
+		STREAM_ZIP   /// STREAM_ZIP is handled as STREAM_ZLIB, except that we do not check the ADLER32 value (must be checked by caller)
+	};
+
+	InflatingStreamBuf(std::istream& istr, StreamType type);
+		/// Creates an InflatingStreamBuf for expanding the compressed data read from
+		/// the give input stream.
+
+	InflatingStreamBuf(std::istream& istr, int windowBits);
+		/// Creates an InflatingStreamBuf for expanding the compressed data read from
+		/// the given input stream.
+		///
+		/// Please refer to the zlib documentation of inflateInit2() for a description
+		/// of the windowBits parameter.
+
+	InflatingStreamBuf(std::ostream& ostr, StreamType type);
+		/// Creates an InflatingStreamBuf for expanding the compressed data passed through
+		/// and forwarding it to the given output stream.
+
+	InflatingStreamBuf(std::ostream& ostr, int windowBits);
+		/// Creates an InflatingStreamBuf for expanding the compressed data passed through
+		/// and forwarding it to the given output stream.
+		///
+		/// Please refer to the zlib documentation of inflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~InflatingStreamBuf();
+		/// Destroys the InflatingStreamBuf.
+		
+	int close();
+		/// Finishes up the stream. 
+		///
+		/// Must be called when inflating to an output stream.
+		
+	void reset();
+		/// Resets the stream buffer.
+		
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+	int sync();
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE  = 1024,
+		INFLATE_BUFFER_SIZE = 32768
+	};
+	
+	std::istream*  _pIstr;
+	std::ostream*  _pOstr;
+	char*    _buffer;
+	z_stream _zstr;
+	bool     _eof;
+	bool     _check;
+};
+
+
+class Foundation_API InflatingIOS: public virtual std::ios
+	/// The base class for InflatingOutputStream and InflatingInputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	InflatingIOS(std::ostream& ostr, InflatingStreamBuf::StreamType type = InflatingStreamBuf::STREAM_ZLIB);
+		/// Creates an InflatingIOS for expanding the compressed data passed through
+		/// and forwarding it to the given output stream.
+		
+	InflatingIOS(std::ostream& ostr, int windowBits);
+		/// Creates an InflatingIOS for expanding the compressed data passed through
+		/// and forwarding it to the given output stream.
+		///
+		/// Please refer to the zlib documentation of inflateInit2() for a description
+		/// of the windowBits parameter.
+
+	InflatingIOS(std::istream& istr, InflatingStreamBuf::StreamType type = InflatingStreamBuf::STREAM_ZLIB);
+		/// Creates an InflatingIOS for expanding the compressed data read from 
+		/// the given input stream.
+
+	InflatingIOS(std::istream& istr, int windowBits);
+		/// Creates an InflatingIOS for expanding the compressed data read from 
+		/// the given input stream.
+		///
+		/// Please refer to the zlib documentation of inflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~InflatingIOS();
+		/// Destroys the InflatingIOS.
+		
+	InflatingStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying stream buffer.
+		
+protected:
+	InflatingStreamBuf _buf;
+};
+
+
+class Foundation_API InflatingOutputStream: public std::ostream, public InflatingIOS
+	/// This stream decompresses all data passing through it
+	/// using zlib's inflate algorithm.
+	///
+	/// After all data has been written to the stream, close()
+	/// must be called to ensure completion of decompression.
+{
+public:
+	InflatingOutputStream(std::ostream& ostr, InflatingStreamBuf::StreamType type = InflatingStreamBuf::STREAM_ZLIB);
+		/// Creates an InflatingOutputStream for expanding the compressed data passed through
+		/// and forwarding it to the given output stream.
+		
+	InflatingOutputStream(std::ostream& ostr, int windowBits);
+		/// Creates an InflatingOutputStream for expanding the compressed data passed through
+		/// and forwarding it to the given output stream.
+		///
+		/// Please refer to the zlib documentation of inflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~InflatingOutputStream();
+		/// Destroys the InflatingOutputStream.
+		
+	int close();
+		/// Finishes up the stream. 
+		///
+		/// Must be called to ensure all data is properly written to
+		/// the target output stream.
+};
+
+
+class Foundation_API InflatingInputStream: public std::istream, public InflatingIOS
+	/// This stream decompresses all data passing through it
+	/// using zlib's inflate algorithm.
+	/// Example:
+	///     std::ifstream istr("data.gz", std::ios::binary);
+	///     InflatingInputStream inflater(istr, InflatingStreamBuf::STREAM_GZIP);
+	///     std::string data;
+	///     inflater >> data;
+	///
+	/// The underlying input stream can contain more than one gzip/deflate stream.
+	/// After a gzip/deflate stream has been processed, reset() can be called
+	/// to inflate the next stream.
+{
+public:
+	InflatingInputStream(std::istream& istr, InflatingStreamBuf::StreamType type = InflatingStreamBuf::STREAM_ZLIB);
+		/// Creates an InflatingInputStream for expanding the compressed data read from 
+		/// the given input stream.
+
+	InflatingInputStream(std::istream& istr, int windowBits);
+		/// Creates an InflatingInputStream for expanding the compressed data read from 
+		/// the given input stream.
+		///
+		/// Please refer to the zlib documentation of inflateInit2() for a description
+		/// of the windowBits parameter.
+
+	~InflatingInputStream();
+		/// Destroys the InflatingInputStream.
+		
+	void reset();
+		/// Resets the zlib machinery so that another zlib stream can be read from
+		/// the same underlying input stream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_InflatingStream_INCLUDED
diff --git a/Poco/Instantiator.h b/Poco/Instantiator.h
new file mode 100644
index 0000000..ce21ebc
--- /dev/null
+++ b/Poco/Instantiator.h
@@ -0,0 +1,82 @@
+//
+// Instantiator.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Instantiator
+//
+// Definition of the Instantiator class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Instantiator_INCLUDED
+#define Foundation_Instantiator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class Base>
+class AbstractInstantiator
+	/// The common base class for all Instantiator instantiations.
+	/// Used by DynamicFactory.
+{
+public:
+	AbstractInstantiator()
+		/// Creates the AbstractInstantiator.
+	{
+	}
+	
+	virtual ~AbstractInstantiator()
+		/// Destroys the AbstractInstantiator.
+	{
+	}
+	
+	virtual Base* createInstance() const = 0;
+		/// Creates an instance of a concrete subclass of Base.	
+
+private:
+	AbstractInstantiator(const AbstractInstantiator&);
+	AbstractInstantiator& operator = (const AbstractInstantiator&);
+};
+
+
+template <class C, class Base>
+class Instantiator: public AbstractInstantiator<Base>
+	/// A template class for the easy instantiation of 
+	/// instantiators. 
+	///
+	/// For the Instantiator to work, the class of which
+	/// instances are to be instantiated must have a no-argument
+	/// constructor.
+{
+public:
+	Instantiator()
+		/// Creates the Instantiator.
+	{
+	}
+	
+	virtual ~Instantiator()
+		/// Destroys the Instantiator.
+	{
+	}
+
+	Base* createInstance() const
+	{
+		return new C;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Instantiator_INCLUDED
diff --git a/Poco/JSON/Array.h b/Poco/JSON/Array.h
new file mode 100644
index 0000000..6a61ad3
--- /dev/null
+++ b/Poco/JSON/Array.h
@@ -0,0 +1,566 @@
+//
+// Array.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Array
+//
+// Definition of the Array class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_Array_INCLUDED
+#define JSON_Array_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Dynamic/Var.h"
+#include <vector>
+#include <sstream>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class Object;
+
+
+class JSON_API Array
+	/// Represents a JSON array. Array provides a representation
+	/// based on shared pointers and optimized for performance. It is possible to
+	/// convert Array to Poco::Dynamic::Array. Conversion requires copying and therefore
+	/// has performance penalty; the benefit is in improved syntax, eg:
+	///
+	///    // use pointers to avoid copying
+	///    using namespace Poco::JSON;
+	///    std::string json = "[ {\"test\" : 0}, { \"test1\" : [1, 2, 3], \"test2\" : 4 } ]";
+	///    Parser parser;
+	///    Var result = parser.parse(json);
+	///    Array::Ptr arr = result.extract<Array::Ptr>();
+	///    Object::Ptr object = arr->getObject(0); // object == {\"test\" : 0}
+	///    int i = object->getElement<int>("test"); // i == 0;
+	///    Object::Ptr subObject = *arr->getObject(1); // subObject == {\"test\" : 0}
+	///    Array subArr::Ptr = subObject->getArray("test1"); // subArr == [1, 2, 3]
+	///    i = result = subArr->get(0); // i == 1;
+	///
+	///    // copy/convert to Poco::Dynamic::Array
+	///    Poco::Dynamic::Array da = *arr;
+	///    i = da[0]["test"];     // i == 0
+	///    i = da[1]["test1"][1]; // i == 2
+	///    i = da[1]["test2"];    // i == 4
+	/// ----
+{
+public:
+	typedef std::vector<Dynamic::Var>                 ValueVec;
+	typedef std::vector<Dynamic::Var>::iterator       Iterator;
+	typedef std::vector<Dynamic::Var>::const_iterator ConstIterator;
+	typedef SharedPtr<Array> Ptr;
+
+	Array(int options = 0);
+		/// Creates an empty Array.
+		///
+		/// If JSON_ESCAPE_UNICODE is specified, when the object is
+		/// stringified, all unicode characters will be escaped in the
+		/// resulting string.
+
+	Array(const Array& copy);
+		/// Creates an Array by copying another one.
+
+#ifdef POCO_ENABLE_CPP11
+
+	Array(Array&& other);
+		/// Move constructor
+
+	Array& operator=(Array&& other);
+		/// Move assignment operator.
+
+#endif // POCO_ENABLE_CPP11
+
+	Array& operator=(const Array& other);
+		/// Assignment operator.
+
+	virtual ~Array();
+		/// Destroys the Array.
+
+	void setEscapeUnicode(bool escape = true);
+		/// Sets the flag for escaping unicode.
+
+	bool getEscapeUnicode() const;
+		/// Returns the flag for escaping unicode.
+
+	ValueVec::const_iterator begin() const;
+		/// Returns the begin iterator for values.
+
+	ValueVec::const_iterator end() const;
+		/// Returns the end iterator for values.
+
+	Dynamic::Var get(unsigned int index) const;
+		/// Retrieves the element at the given index.
+		/// Will return an empty value when the element doesn't exist.
+
+	Array::Ptr getArray(unsigned int index) const;
+		/// Retrieves an array. When the element is not
+		/// an Array or doesn't exist, an empty SharedPtr is returned.
+
+	template<typename T>
+	T getElement(unsigned int index) const
+		/// Retrieves an element and tries to convert it to the
+		/// template type. The convert<T> method of
+		/// Dynamic is called which can also throw
+		/// exceptions for invalid values.
+		/// Note: This will not work for an array or an object.
+	{
+		Dynamic::Var value = get(index);
+		return value.convert<T>();
+	}
+
+	SharedPtr<Object> getObject(unsigned int index) const;
+		/// Retrieves an object. When the element is not
+		/// an object or doesn't exist, an empty SharedPtr is returned.
+
+	std::size_t size() const;
+		/// Returns the size of the array.
+
+	bool isArray(unsigned int index) const;
+		/// Returns true when the element is an array.
+
+	bool isArray(const Dynamic::Var& value) const;
+		/// Returns true when the element is an array.
+
+	bool isArray(ConstIterator& value) const;
+		/// Returns true when the element is an array.
+
+	bool isNull(unsigned int index) const;
+		/// Returns true when the element is null or
+		/// when the element doesn't exist.
+
+	bool isObject(unsigned int index) const;
+		/// Returns true when the element is an object.
+
+	bool isObject(const Dynamic::Var& value) const;
+		/// Returns true when the element is an object.
+
+	bool isObject(ConstIterator& value) const;
+		/// Returns true when the element is an object.
+
+	template<typename T>
+	T optElement(unsigned int index, const T& def) const
+		/// Returns the element at the given index. When
+		/// the element is null, doesn't exist or can't
+		/// be converted to the given type, the default
+		/// value will be returned
+	{
+		T value = def;
+		if (index < _values.size())
+		{
+			try
+			{
+				value = _values[index].convert<T>();
+			}
+			catch (...)
+			{
+				// Default value is returned.
+			}
+		}
+		return value;
+	}
+
+	void add(const Dynamic::Var& value);
+		/// Add the given value to the array
+
+	void set(unsigned int index, const Dynamic::Var& value);
+		/// Update the element on the given index to specified value
+
+	void stringify(std::ostream& out, unsigned int indent = 0, int step = -1) const;
+		/// Prints the array to out. When indent has zero value,
+		/// the array will be printed without newline breaks and spaces between elements.
+
+	void remove(unsigned int index);
+		/// Removes the element on the given index.
+
+	operator const Poco::Dynamic::Array& () const;
+		/// Conversion operator to Dynamic::Array.
+
+	static Poco::Dynamic::Array makeArray(const JSON::Array::Ptr& arr);
+		/// Utility function for creation of array.
+
+	void clear();
+		/// Clears the contents of the array.
+
+private:
+	void resetDynArray() const;
+
+	typedef SharedPtr<Poco::Dynamic::Array> ArrayPtr;
+
+	ValueVec         _values;
+	mutable ArrayPtr _pArray;
+	mutable bool     _modified;
+	// Note:
+	//  The reason we have this flag here (rather than as argument to stringify())
+	//  is because Array can be returned stringified from a Dynamic::Var:toString(),
+	//  so it must know whether to escape unicode or not.
+	bool             _escapeUnicode;
+};
+
+
+//
+// inlines
+//
+
+inline void Array::setEscapeUnicode(bool escape)
+{
+	_escapeUnicode = escape;
+}
+
+
+inline bool Array::getEscapeUnicode() const
+{
+	return _escapeUnicode;
+}
+
+
+inline Array::ValueVec::const_iterator Array::begin() const
+{
+	return _values.begin();
+}
+
+
+inline Array::ValueVec::const_iterator Array::end() const
+
+{
+	return _values.end();
+}
+
+
+inline std::size_t Array::size() const
+{
+	return static_cast<std::size_t>(_values.size());
+}
+
+
+inline bool Array::isArray(unsigned int index) const
+{
+	Dynamic::Var value = get(index);
+	return isArray(value);
+}
+
+
+inline bool Array::isArray(const Dynamic::Var& value) const
+{
+	return value.type() == typeid(Array::Ptr);
+}
+
+
+inline bool Array::isArray(ConstIterator& it) const
+{
+	return it!= end() && isArray(*it);
+}
+
+
+inline void Array::add(const Dynamic::Var& value)
+{
+	_values.push_back(value);
+	_modified = true;
+}
+
+
+inline void Array::set(unsigned int index, const Dynamic::Var& value)
+{
+	if (index >= _values.size()) _values.resize(index + 1);
+	_values[index] = value;
+	_modified = true;
+}
+
+
+inline void Array::remove(unsigned int index)
+{
+	_values.erase(_values.begin() + index);
+}
+
+
+} } // namespace Poco::JSON
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <>
+class VarHolderImpl<JSON::Array::Ptr>: public VarHolder
+{
+public:
+	VarHolderImpl(const JSON::Array::Ptr& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(JSON::Array::Ptr);
+	}
+
+	void convert(Int8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(bool& value) const
+	{
+		value = !_val.isNull() && _val->size() > 0;
+	}
+
+	void convert(float&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(double&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(char&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(std::string& s) const
+	{
+		std::ostringstream oss;
+		_val->stringify(oss, 2);
+		s = oss.str();
+	}
+
+	void convert(DateTime& /*val*/) const
+	{
+		throw BadCastException("Cannot convert Array to DateTime");
+	}
+
+	void convert(LocalDateTime& /*ldt*/) const
+	{
+		throw BadCastException("Cannot convert Array to LocalDateTime");
+	}
+
+	void convert(Timestamp& /*ts*/) const
+	{
+		throw BadCastException("Cannot convert Array to Timestamp");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const JSON::Array::Ptr& value() const
+	{
+		return _val;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	JSON::Array::Ptr _val;
+};
+
+
+template <>
+class VarHolderImpl<JSON::Array>: public VarHolder
+{
+public:
+	VarHolderImpl(const JSON::Array& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(JSON::Array);
+	}
+
+	void convert(Int8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(bool& value) const
+	{
+		value = _val.size() > 0;
+	}
+
+	void convert(float&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(double&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(char&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(std::string& s) const
+	{
+		std::ostringstream oss;
+		_val.stringify(oss, 2);
+		s = oss.str();
+	}
+
+	void convert(DateTime& /*val*/) const
+	{
+		throw BadCastException("Cannot convert Array to DateTime");
+	}
+
+	void convert(LocalDateTime& /*ldt*/) const
+	{
+		throw BadCastException("Cannot convert Array to LocalDateTime");
+	}
+
+	void convert(Timestamp& /*ts*/) const
+	{
+		throw BadCastException("Cannot convert Array to Timestamp");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const JSON::Array& value() const
+	{
+		return _val;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	JSON::Array _val;
+};
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // JSON_Array_INCLUDED
diff --git a/Poco/JSON/Handler.h b/Poco/JSON/Handler.h
new file mode 100644
index 0000000..8c64f34
--- /dev/null
+++ b/Poco/JSON/Handler.h
@@ -0,0 +1,106 @@
+//
+// Handler.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Handler
+//
+// Definition of the Handler class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_Handler_INCLUDED
+#define JSON_Handler_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Dynamic/Struct.h"
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API Handler
+	/// Interface for handling parsing events generated by the JSON Parser.
+	///
+	/// An application can implement a subclass of Handler to implement
+	/// callback-based parsing of a JSON document, similar to how a SAX
+	/// parser would handle XML.
+{
+public:
+	typedef SharedPtr<Handler> Ptr;
+
+	Handler();
+		/// Creates an empty Handler.
+	
+	virtual ~Handler();
+		/// Destroys the Handler.
+
+	virtual void reset() = 0;
+		/// Resets the handler state.
+
+	virtual void startObject() = 0;
+		/// The parser has read a {, meaning a new object will be read.
+
+	virtual void endObject() = 0;
+		/// The parser has read a }, meaning the object is read.
+
+	virtual void startArray() = 0;
+		/// The parser has read a [, meaning a new array will be read.
+
+	virtual void endArray() = 0;
+		/// The parser has read a ], meaning the array is read.
+
+	virtual void key(const std::string& k) = 0;
+		/// A key of an object is read.
+
+	virtual void null() = 0;
+		/// A null value is read.
+
+	virtual void value(int v) = 0;
+		/// An integer value is read.
+
+	virtual void value(unsigned v) = 0;
+		/// An unsigned value is read. This will only be triggered if the
+		/// value cannot fit into a signed int.
+
+#if defined(POCO_HAVE_INT64)
+	virtual void value(Int64 v) = 0;
+		/// A 64-bit integer value is read.
+
+	virtual void value(UInt64 v) = 0;
+		/// An unsigned 64-bit integer value is read. This will only be
+		/// triggered if the value cannot fit into a signed 64-bit integer.
+#endif
+
+	virtual void value(const std::string& value) = 0;
+		/// A string value is read.
+
+	virtual void value(double d) = 0;
+		/// A double value is read.
+
+	virtual void value(bool b) = 0;
+		/// A boolean value is read.
+
+	virtual Poco::Dynamic::Var asVar() const;
+		/// Returns the result of the parser (an object, array or string),
+		/// empty Var if there is no result.
+
+	virtual Poco::DynamicStruct asStruct() const;
+		/// Returns the result of the parser (an object, array or string),
+		/// empty Var if there is no result.
+};
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_Handler_INCLUDED
diff --git a/Poco/JSON/JSON.h b/Poco/JSON/JSON.h
new file mode 100644
index 0000000..36d7623
--- /dev/null
+++ b/Poco/JSON/JSON.h
@@ -0,0 +1,62 @@
+//
+// JSON.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  JSON
+//
+// Basic definitions for the Poco JSON library.
+// This file must be the first file included by every other JSON
+// header file.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSON_INCLUDED
+#define JSON_JSON_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the JSON_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// JSON_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(JSON_EXPORTS)
+		#define JSON_API __declspec(dllexport)
+	#else
+		#define JSON_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(JSON_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define JSON_API __attribute__ ((visibility ("default")))
+	#else
+		#define JSON_API
+	#endif
+#endif
+
+
+//
+// Automatically link JSON library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(JSON_EXPORTS)
+		#pragma comment(lib, "PocoJSON" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // JSON_JSON_INCLUDED
diff --git a/Poco/JSON/JSONException.h b/Poco/JSON/JSONException.h
new file mode 100644
index 0000000..058d36f
--- /dev/null
+++ b/Poco/JSON/JSONException.h
@@ -0,0 +1,35 @@
+//
+// JSONException.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  JSONException
+//
+// Definition of the JSONException class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONException_INCLUDED
+#define JSON_JSONException_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace JSON {
+
+
+POCO_DECLARE_EXCEPTION(JSON_API, JSONException, Poco::Exception)
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONException_INCLUDED
diff --git a/Poco/JSON/Object.h b/Poco/JSON/Object.h
new file mode 100644
index 0000000..8812561
--- /dev/null
+++ b/Poco/JSON/Object.h
@@ -0,0 +1,715 @@
+//
+// Object.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Object
+//
+// Definition of the Object class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_Object_INCLUDED
+#define JSON_Object_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Array.h"
+#include "Poco/JSON/Stringifier.h"
+#include "Poco/JSONString.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/Dynamic/Struct.h"
+#include "Poco/Nullable.h"
+#include <map>
+#include <vector>
+#include <deque>
+#include <iostream>
+#include <sstream>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API Object
+	/// Represents a JSON object. Object provides a representation based on
+	/// shared pointers and optimized for performance. It is possible to
+	/// convert Object to DynamicStruct. Conversion requires copying and therefore
+	/// has performance penalty; the benefit is in improved syntax, eg:
+	///
+	///    std::string json = "{ \"test\" : { \"property\" : \"value\" } }";
+	///    Parser parser;
+	///    Var result = parser.parse(json);
+	///
+	///    // use pointers to avoid copying
+	///    Object::Ptr object = result.extract<Object::Ptr>();
+	///    Var test = object->get("test"); // holds { "property" : "value" }
+	///    Object::Ptr subObject = test.extract<Object::Ptr>();
+	///    test = subObject->get("property");
+	///    std::string val = test.toString(); // val holds "value"
+	///
+	///    // copy/convert to Poco::DynamicStruct
+	///    Poco::DynamicStruct ds = *object;
+	///    val = ds["test"]["property"]; // val holds "value"
+	///
+{
+public:
+	typedef SharedPtr<Object>                   Ptr;
+	typedef std::map<std::string, Dynamic::Var> ValueMap;
+	typedef ValueMap::value_type                ValueType;
+	typedef ValueMap::iterator                  Iterator;
+	typedef ValueMap::const_iterator            ConstIterator;
+	typedef std::vector<std::string>            NameList;
+
+	explicit Object(int options = 0);
+		/// Creates an empty Object.
+		///
+		/// If JSON_PRESERVE_KEY_ORDER is specified, the object will
+		/// preserve the items insertion order. Otherwise, items will be
+		/// sorted by keys.
+		///
+		/// If JSON_ESCAPE_UNICODE is specified, when the object is
+		/// stringified, all unicode characters will be escaped in the
+		/// resulting string.
+
+	Object(const Object& copy);
+		/// Creates an Object by copying another one.
+		///
+		/// Struct is not copied to keep the operation as
+		/// efficient as possible (when needed, it will be generated upon request).
+
+#ifdef POCO_ENABLE_CPP11
+
+	Object(Object&& other);
+		/// Move constructor
+
+	Object &operator =(Object &&other);
+		// Move asignment operator
+
+#endif // POCO_ENABLE_CPP11
+
+	virtual ~Object();
+		/// Destroys the Object.
+
+	Object &operator =(const Object &other);
+		// Assignment operator
+
+	void setEscapeUnicode(bool escape = true);
+		/// Sets the flag for escaping unicode.
+
+	bool getEscapeUnicode() const;
+		/// Returns the flag for escaping unicode.
+
+	Iterator begin();
+		/// Returns begin iterator for values.
+
+	ConstIterator begin() const;
+		/// Returns const begin iterator for values.
+
+	Iterator end();
+		/// Returns end iterator for values.
+
+	ConstIterator end() const;
+		/// Returns const end iterator for values.
+
+	Dynamic::Var get(const std::string& key) const;
+		/// Retrieves a property. An empty value is
+		/// returned when the property doesn't exist.
+
+	Array::Ptr getArray(const std::string& key) const;
+		/// Returns a SharedPtr to an array when the property
+		/// is an array. An empty SharedPtr is returned when
+		/// the element doesn't exist or is not an array.
+
+	Object::Ptr getObject(const std::string& key) const;
+		/// Returns a SharedPtr to an object when the property
+		/// is an object. An empty SharedPtr is returned when
+		/// the property doesn't exist or is not an object
+
+	template<typename T>
+	T getValue(const std::string& key) const
+		/// Retrieves the property with the given name and will
+		/// try to convert the value to the given template type.
+		/// The convert<T>() method of Var is called
+		/// which can also throw exceptions for invalid values.
+		/// Note: This will not work for an array or an object.
+	{
+		Dynamic::Var value = get(key);
+		return value.convert<T>();
+	}
+
+	template<typename T>
+	Poco::Nullable<T> getNullableValue(const std::string& key) const
+		/// Retrieves the property with the given name and will
+		/// try to convert the value to the given template type.
+		///
+		/// The convert<T> method of Var is called
+		/// which can also throw exceptions for invalid values.
+		/// Note: This will not work for an array or an object.
+	{
+		if (isNull(key))
+			return Poco::Nullable<T>();
+
+		Dynamic::Var value = get(key);
+		return value.convert<T>();
+	}
+
+	void getNames(NameList& names) const;
+		/// Fills the supplied vector with all property names.
+
+	NameList getNames() const;
+		/// Returns all property names.
+
+	bool has(const std::string& key) const;
+		/// Returns true when the given property exists.
+
+	bool isArray(const std::string& key) const;
+		/// Returns true when the given property contains an array.
+
+	bool isArray(ConstIterator& it) const;
+		/// Returns true when the given property contains an array.
+
+	bool isNull(const std::string& key) const;
+		/// Returns true when the given property contains a null value.
+
+	bool isObject(const std::string& key) const;
+		/// Returns true when the given property contains an object.
+
+	bool isObject(ConstIterator& it) const;
+		/// Returns true when the given property contains an object.
+
+	template<typename T>
+	T optValue(const std::string& key, const T& def) const
+		/// Returns the value of a property when the property exists
+		/// and can be converted to the given type. Otherwise
+		/// def will be returned.
+	{
+		T value = def;
+		ValueMap::const_iterator it = _values.find(key);
+		if (it != _values.end() && ! it->second.isEmpty())
+		{
+			try
+			{
+				value = it->second.convert<T>();
+			}
+			catch (...)
+			{
+				// The default value will be returned
+			}
+		}
+		return value;
+	}
+
+	std::size_t size() const;
+		/// Returns the number of properties.
+
+	void set(const std::string& key, const Dynamic::Var& value);
+		/// Sets a new value.
+
+	void stringify(std::ostream& out, unsigned int indent = 0, int step = -1) const;
+		/// Prints the object to out stream.
+		///
+		/// When indent is 0, the object will be printed on a single
+		/// line without indentation.
+
+	void remove(const std::string& key);
+		/// Removes the property with the given key.
+
+	static Poco::DynamicStruct makeStruct(const Object::Ptr& obj);
+		/// Utility function for creation of struct.
+
+	operator const Poco::DynamicStruct& () const;
+		/// Cast operator to Poco::DynamiStruct.
+
+	void clear();
+		/// Clears the contents of the object.
+		///
+		/// Insertion order preservation property is left intact.
+
+private:
+	typedef std::deque<ValueMap::const_iterator>  KeyList;
+	typedef Poco::DynamicStruct::Ptr              StructPtr;
+
+	void resetDynStruct() const;
+	void syncKeys(const KeyList& keys);
+
+	template <typename C>
+	void doStringify(const C& container, std::ostream& out, unsigned int indent, unsigned int step) const
+	{
+		int options = Poco::JSON_WRAP_STRINGS;
+		options |= _escapeUnicode ? Poco::JSON_ESCAPE_UNICODE : 0;
+
+		out << '{';
+
+		if (indent > 0) out << std::endl;
+
+		typename C::const_iterator it = container.begin();
+		typename C::const_iterator end = container.end();
+		for (; it != end;)
+		{
+			for (unsigned int i = 0; i < indent; i++) out << ' ';
+
+			Stringifier::stringify(getKey(it), out, indent, step, options);
+			out << ((indent > 0) ? " : " : ":");
+
+			Stringifier::stringify(getValue(it), out, indent + step, step, options);
+
+			if (++it != container.end()) out << ',';
+
+			if (step > 0) out << std::endl;
+		}
+
+		if (indent >= step) indent -= step;
+
+		for (unsigned int i = 0; i < indent; i++) out << ' ';
+
+		out << '}';
+	}
+
+	const std::string& getKey(ValueMap::const_iterator& it) const;
+	const Dynamic::Var& getValue(ValueMap::const_iterator& it) const;
+	const std::string& getKey(KeyList::const_iterator& it) const;
+	const Dynamic::Var& getValue(KeyList::const_iterator& it) const;
+
+	ValueMap          _values;
+	KeyList           _keys;
+	bool              _preserveInsOrder;
+	// Note:
+	//  The reason for this flag (rather than as argument to stringify()) is
+	//  because Object can be returned stringified from Dynamic::Var::toString(),
+	//  so it must know whether to escape unicode or not.
+	bool              _escapeUnicode;
+	mutable StructPtr _pStruct;
+	mutable bool      _modified;
+};
+
+
+//
+// inlines
+//
+
+inline void Object::setEscapeUnicode(bool escape)
+{
+	_escapeUnicode = escape;
+}
+
+
+inline bool Object::getEscapeUnicode() const
+{
+	return _escapeUnicode;
+}
+
+
+inline Object::Iterator Object::begin()
+{
+	return _values.begin();
+}
+
+
+inline Object::ConstIterator Object::begin() const
+{
+	return _values.begin();
+}
+
+
+inline Object::Iterator Object::end()
+{
+	return _values.end();
+}
+
+
+inline Object::ConstIterator Object::end() const
+{
+	return _values.end();
+}
+
+
+inline bool Object::has(const std::string& key) const
+{
+	ValueMap::const_iterator it = _values.find(key);
+	return it != _values.end();
+}
+
+
+inline bool Object::isArray(const std::string& key) const
+{
+	ValueMap::const_iterator it = _values.find(key);
+	return isArray(it);
+}
+
+
+inline bool Object::isArray(ConstIterator& it) const
+{
+	return it != _values.end() && (it->second.type() == typeid(Array::Ptr) || it->second.type() == typeid(Array));
+}
+
+
+inline bool Object::isNull(const std::string& key) const
+{
+	ValueMap::const_iterator it = _values.find(key);
+	return it == _values.end() || it->second.isEmpty();
+}
+
+
+inline bool Object::isObject(const std::string& key) const
+{
+	ValueMap::const_iterator it = _values.find(key);
+	return isObject(it);
+}
+
+
+inline bool Object::isObject(ConstIterator& it) const
+{
+	return it != _values.end() && (it->second.type() == typeid(Object::Ptr) || it->second.type() == typeid(Object));
+}
+
+
+inline std::size_t Object::size() const
+{
+	return static_cast<std::size_t>(_values.size());
+}
+
+
+inline void Object::remove(const std::string& key)
+{
+	_values.erase(key);
+	if (_preserveInsOrder)
+	{
+		KeyList::iterator it = _keys.begin();
+		KeyList::iterator end = _keys.end();
+		for (; it != end; ++it)
+		{
+			if (key == (*it)->first)
+			{
+				_keys.erase(it);
+				break;
+			}
+		}
+	}
+	_modified = true;
+}
+
+
+inline const std::string& Object::getKey(ValueMap::const_iterator& it) const
+{
+	return it->first;
+}
+
+
+inline const Dynamic::Var& Object::getValue(ValueMap::const_iterator& it) const
+{
+	return it->second;
+}
+
+
+inline const Dynamic::Var& Object::getValue(KeyList::const_iterator& it) const
+{
+	ValueMap::const_iterator itv = _values.find((*it)->first);
+	if (itv != _values.end())
+		return itv->second;
+	else
+		throw Poco::NotFoundException();
+}
+
+
+} } // namespace Poco::JSON
+
+
+namespace Poco {
+namespace Dynamic {
+
+
+template <>
+class VarHolderImpl<JSON::Object::Ptr>: public VarHolder
+{
+public:
+	VarHolderImpl(const JSON::Object::Ptr& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(JSON::Object::Ptr);
+	}
+
+	void convert(Int8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(bool& value) const
+	{
+		value = !_val.isNull() && _val->size() > 0;
+	}
+
+	void convert(float&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(double&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(char&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(std::string& s) const
+	{
+		std::ostringstream oss;
+		_val->stringify(oss, 2);
+		s = oss.str();
+	}
+
+	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");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const JSON::Object::Ptr& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	JSON::Object::Ptr _val;
+};
+
+
+template <>
+class VarHolderImpl<JSON::Object>: public VarHolder
+{
+public:
+	VarHolderImpl(const JSON::Object& val): _val(val)
+	{
+	}
+
+	~VarHolderImpl()
+	{
+	}
+
+	const std::type_info& type() const
+	{
+		return typeid(JSON::Object);
+	}
+
+	void convert(Int8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(Int64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt8&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt16&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt32&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(UInt64&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(bool& value) const
+	{
+		value = _val.size() > 0;
+	}
+
+	void convert(float&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(double&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(char&) const
+	{
+		throw BadCastException();
+	}
+
+	void convert(std::string& s) const
+	{
+		std::ostringstream oss;
+		_val.stringify(oss, 2);
+		s = oss.str();
+	}
+
+	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");
+	}
+
+	VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
+	{
+		return cloneHolder(pVarHolder, _val);
+	}
+
+	const JSON::Object& value() const
+	{
+		return _val;
+	}
+
+	bool isArray() const
+	{
+		return false;
+	}
+
+	bool isInteger() const
+	{
+		return false;
+	}
+
+	bool isSigned() const
+	{
+		return false;
+	}
+
+	bool isNumeric() const
+	{
+		return false;
+	}
+
+	bool isString() const
+	{
+		return false;
+	}
+
+private:
+	JSON::Object _val;
+};
+
+
+} } // namespace Poco::Dynamic
+
+
+#endif // JSON_Object_INCLUDED
diff --git a/Poco/JSON/ParseHandler.h b/Poco/JSON/ParseHandler.h
new file mode 100644
index 0000000..98cd69e
--- /dev/null
+++ b/Poco/JSON/ParseHandler.h
@@ -0,0 +1,169 @@
+//
+// ParseHandler.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  ParseHandler
+//
+// Definition of the ParseHandler class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_ParseHandler_INCLUDED
+#define JSON_ParseHandler_INCLUDED
+
+
+#include "Poco/JSON/Handler.h"
+#include <stack>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API ParseHandler: public Handler
+	/// ParseHandler is the default handler for the JSON Parser.
+	///
+	/// This handler will construct an Object or Array based
+	/// on the handlers called by the Parser.
+{
+public:
+	ParseHandler(bool preserveObjectOrder = false);
+		/// Creates the ParseHandler.
+		///
+		/// If preserveObjectOrder is true, the order of properties
+		/// inside objects is preserved. Otherwise, items
+		/// will be sorted by keys.
+
+	virtual ~ParseHandler();
+		/// Destroys the ParseHandler.
+
+	virtual void reset();
+		/// Resets the handler state.
+		
+	void startObject();
+		/// Handles a '{'; a new object is started.
+
+	void endObject();
+		/// Handles a '}'; the object is closed.
+
+	void startArray();
+		/// Handles a '['; a new array is started.
+
+	void endArray();
+		/// Handles a ']'; the array is closed.
+
+	void key(const std::string& k);
+		/// A key is read
+
+	Dynamic::Var asVar() const;
+		/// Returns the result of the parser (an object or an array).
+
+	virtual void value(int v);
+		/// An integer value is read
+
+	virtual void value(unsigned v);
+		/// An unsigned value is read. This will only be triggered if the
+		/// value cannot fit into a signed int.
+
+#if defined(POCO_HAVE_INT64)
+	virtual void value(Int64 v);
+		/// A 64-bit integer value is read
+
+	virtual void value(UInt64 v);
+		/// An unsigned 64-bit integer value is read. This will only be
+		/// triggered if the value cannot fit into a signed 64-bit integer.
+#endif
+
+	virtual void value(const std::string& s);
+		/// A string value is read.
+
+	virtual void value(double d);
+		/// A double value is read.
+
+	virtual void value(bool b);
+		/// A boolean value is read.
+
+	virtual void null();
+		/// A null value is read.
+
+private:
+	void setValue(const Poco::Dynamic::Var& value);
+	typedef std::stack<Dynamic::Var> Stack;
+
+	Stack        _stack;
+	std::string  _key;
+	Dynamic::Var _result;
+	bool         _preserveObjectOrder;
+};
+
+
+//
+// inlines
+//
+inline Dynamic::Var ParseHandler::asVar() const
+{
+	return _result;
+}
+
+
+inline void ParseHandler::value(int v)
+{
+	setValue(v);
+}
+
+
+inline void ParseHandler::value(unsigned v)
+{
+	setValue(v);
+}
+
+
+#if defined(POCO_HAVE_INT64)
+inline void ParseHandler::value(Int64 v)
+{
+	setValue(v);
+}
+
+
+inline void ParseHandler::value(UInt64 v)
+{
+	setValue(v);
+}
+#endif
+
+
+inline void ParseHandler::value(const std::string& s)
+{
+	setValue(s);
+}
+
+
+inline void ParseHandler::value(double d)
+{
+	setValue(d);
+}
+
+
+inline void ParseHandler::value(bool b)
+{
+	setValue(b);
+}
+
+
+inline void ParseHandler::null()
+{
+	Poco::Dynamic::Var empty;
+	setValue(empty);
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_ParseHandler_INCLUDED
diff --git a/Poco/JSON/Parser.h b/Poco/JSON/Parser.h
new file mode 100644
index 0000000..592ddab
--- /dev/null
+++ b/Poco/JSON/Parser.h
@@ -0,0 +1,203 @@
+//
+// Parser.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Parser
+//
+// Definition of the Parser class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONParser_INCLUDED
+#define JSON_JSONParser_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/ParserImpl.h"
+#include "Poco/JSON/Object.h"
+#include "Poco/JSON/Array.h"
+#include "Poco/JSON/ParseHandler.h"
+#include "Poco/JSON/JSONException.h"
+#include "Poco/UTF8Encoding.h"
+#include "Poco/Dynamic/Var.h"
+#include <string>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API Parser: private ParserImpl
+	/// A parser for reading RFC 4627 compliant JSON from strings or streams.
+	/// 
+	/// Simple usage example:
+	/// 
+	///    std::string json = "{ \"name\" : \"Franky\", \"children\" : [ \"Jonas\", \"Ellen\" ] }";
+	///    Parser parser;
+	///    Var result = parser.parse(json);
+	///    // ... use result (see next example)
+	///    parser.reset();
+	///    std::ostringstream ostr;
+	///    PrintHandler::Ptr pHandler = new PrintHandler(ostr);
+	///    parser.setHandler(pHandler);
+	///    parser.parse(json); // ostr.str() == json
+	/// ----
+	///
+	/// The result of parsing a valid JSON document will be either an Object
+	/// or an Array. Therefore the result of parse() is a Poco::Dynamic::Var
+	/// containing a Poco::SharedPtr to an Object or Array instance.
+	///
+	/// Example:
+	/// 
+	///    std::string json = "{ \"name\" : \"Franky\", \"children\" : [ \"Jonas\", \"Ellen\" ] }";
+	///    Parser parser;
+	///    Var result = parser.parse(json);
+	///    Object::Ptr object = result.extract<Object::Ptr>();
+	///    std::string name = object.getValue<std::string>("name");
+	///    Array::Ptr children = object.getArray("children");
+	/// ----
+{
+public:
+
+	Parser(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE);
+		/// Creates JSON Parser, using the given Handler and buffer size.
+
+	virtual ~Parser();
+		/// Destroys JSON Parser.
+
+	void reset();
+		/// Resets the parser.
+
+	void setAllowComments(bool comments);
+		/// Allow or disallow comments. By default, comments are not allowed.
+
+	bool getAllowComments() const;
+		/// Returns true if comments are allowed, false otherwise.
+		///
+		/// By default, comments are not allowed.
+		
+	void setAllowNullByte(bool nullByte);
+		/// Allow or disallow null byte in strings. 
+		///
+		/// By default, null byte is allowed.
+
+	bool getAllowNullByte() const;
+		/// Returns true if null byte is allowed, false otherwise.
+		///
+		/// By default, null bytes are allowed.
+
+	void setDepth(std::size_t depth);
+		/// Sets the allowed JSON depth.
+
+	std::size_t getDepth() const;
+		/// Returns the allowed JSON depth.
+
+	Dynamic::Var parse(const std::string& json);
+		/// Parses JSON from a string.
+
+	Dynamic::Var parse(std::istream& in);
+		/// Parses JSON from an input stream.
+
+	void setHandler(const Handler::Ptr& pHandler);
+		/// Set the Handler.
+
+	const Handler::Ptr& getHandler();
+		/// Returns the Handler.
+
+	Dynamic::Var asVar() const;
+		/// Returns the result of parsing;
+
+	Dynamic::Var result() const;
+		/// Returns the result of parsing as Dynamic::Var;
+
+private:
+	Parser(const Parser&);
+	Parser& operator = (const Parser&);
+};
+
+
+//
+// inlines
+//
+inline void Parser::setAllowComments(bool comments)
+{
+	setAllowCommentsImpl(comments);
+}
+
+
+inline bool Parser::getAllowComments() const
+{
+	return getAllowCommentsImpl();
+}
+
+
+inline void Parser::setAllowNullByte(bool nullByte)
+{
+	setAllowNullByteImpl(nullByte);
+}
+
+
+inline bool Parser::getAllowNullByte() const
+{
+	return getAllowNullByteImpl();
+}
+
+
+inline void Parser::setDepth(std::size_t depth)
+{
+	setDepthImpl(depth);
+}
+
+
+inline std::size_t Parser::getDepth() const
+{
+	return getDepthImpl();
+}
+
+
+inline const Handler::Ptr& Parser::getHandler()
+{
+	return getHandlerImpl();
+}
+
+
+inline Dynamic::Var Parser::result() const
+{
+	return resultImpl();
+}
+
+
+inline Dynamic::Var Parser::asVar() const
+{
+	return asVarImpl();
+}
+
+
+inline void Parser::reset()
+{
+	resetImpl();
+}
+
+
+inline Dynamic::Var Parser::parse(const std::string& json)
+{
+	return parseImpl(json);
+}
+
+
+inline Dynamic::Var Parser::parse(std::istream& in)
+{
+	return parseImpl(in);
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONParser_INCLUDED
diff --git a/Poco/JSON/ParserImpl.h b/Poco/JSON/ParserImpl.h
new file mode 100644
index 0000000..dd92fe8
--- /dev/null
+++ b/Poco/JSON/ParserImpl.h
@@ -0,0 +1,194 @@
+//
+// Parser.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  ParserImpl
+//
+// Definition of the ParserImpl class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONParserImpl_INCLUDED
+#define JSON_JSONParserImpl_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Object.h"
+#include "Poco/JSON/Array.h"
+#include "Poco/JSON/ParseHandler.h"
+#include "Poco/JSON/JSONException.h"
+#include "Poco/UTF8Encoding.h"
+#include "Poco/Dynamic/Var.h"
+#include <string>
+
+
+struct json_stream;
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API ParserImpl
+{
+protected:
+	static const std::size_t JSON_PARSE_BUFFER_SIZE = 4096;
+	static const std::size_t JSON_PARSER_STACK_SIZE = 128;
+	static const int         JSON_UNLIMITED_DEPTH = -1;
+
+	ParserImpl(const Handler::Ptr& pHandler = new ParseHandler, std::size_t bufSize = JSON_PARSE_BUFFER_SIZE);
+		/// Creates JSON ParserImpl, using the given Handler and buffer size.
+
+	virtual ~ParserImpl();
+		/// Destroys JSON ParserImpl.
+
+	void resetImpl();
+		/// Resets the parser.
+
+	void setAllowCommentsImpl(bool comments);
+		/// Allow or disallow comments. By default, comments are not allowed.
+
+	bool getAllowCommentsImpl() const;
+		/// Returns true if comments are allowed, false otherwise.
+		///
+		/// By default, comments are not allowed.
+
+	void setAllowNullByteImpl(bool nullByte);
+		/// Allow or disallow null byte in strings.
+		///
+		/// By default, null byte is allowed.
+
+	bool getAllowNullByteImpl() const;
+		/// Returns true if null byte is allowed, false otherwise.
+		///
+		/// By default, null bytes are allowed.
+
+	void setDepthImpl(std::size_t depth);
+		/// Sets the allowed JSON depth.
+
+	std::size_t getDepthImpl() const;
+		/// Returns the allowed JSON depth.
+
+	Dynamic::Var parseImpl(const std::string& json);
+		/// Parses JSON from a string.
+
+	Dynamic::Var parseImpl(std::istream& in);
+		/// Parses JSON from an input stream.
+
+	void setHandlerImpl(const Handler::Ptr& pHandler);
+		/// Set the Handler.
+
+	const Handler::Ptr& getHandlerImpl();
+		/// Returns the Handler.
+
+	Dynamic::Var asVarImpl() const;
+		/// Returns the result of parsing;
+
+	Dynamic::Var resultImpl() const;
+		/// Returns the result of parsing as Dynamic::Var;
+
+private:
+	ParserImpl(const ParserImpl&);
+	ParserImpl& operator =(const ParserImpl&);
+
+	void handleArray();
+	void handleObject();
+	void handle();
+	void handle(const std::string& json);
+	void stripComments(std::string& json);
+	bool checkError();
+
+	struct json_stream* _pJSON;
+	Handler::Ptr _pHandler;
+	int          _depth;
+	char         _decimalPoint;
+	bool         _allowNullByte;
+	bool         _allowComments;
+};
+
+
+//
+// inlines
+//
+
+inline void ParserImpl::resetImpl()
+{
+	// currently, json stream is opened and closed on every parse request
+	// (perhaps there is some optimization room?)
+	//json_reset(&_json);
+	if (_pHandler) _pHandler->reset();
+}
+
+
+inline void ParserImpl::setAllowCommentsImpl(bool comments)
+{
+	_allowComments = comments;
+}
+
+
+inline bool ParserImpl::getAllowCommentsImpl() const
+{
+	return _allowComments;
+}
+
+
+inline void ParserImpl::setAllowNullByteImpl(bool nullByte)
+{
+	_allowNullByte = nullByte;
+}
+
+
+inline bool ParserImpl::getAllowNullByteImpl() const
+{
+	return _allowNullByte;
+}
+
+
+inline void ParserImpl::setDepthImpl(std::size_t depth)
+{
+	_depth = static_cast<int>(depth);
+}
+
+
+inline std::size_t ParserImpl::getDepthImpl() const
+{
+	return static_cast<int>(_depth);
+}
+
+
+inline void ParserImpl::setHandlerImpl(const Handler::Ptr& pHandler)
+{
+	_pHandler = pHandler;
+}
+
+
+inline const Handler::Ptr& ParserImpl::getHandlerImpl()
+{
+	return _pHandler;
+}
+
+
+inline Dynamic::Var ParserImpl::resultImpl() const
+{
+	return asVarImpl();
+}
+
+
+inline Dynamic::Var ParserImpl::asVarImpl() const
+{
+	if (_pHandler) return _pHandler->asVar();
+
+	return Dynamic::Var();
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONParserImpl_INCLUDED
diff --git a/Poco/JSON/PrintHandler.h b/Poco/JSON/PrintHandler.h
new file mode 100644
index 0000000..620dc52
--- /dev/null
+++ b/Poco/JSON/PrintHandler.h
@@ -0,0 +1,139 @@
+//
+// PrintHandler.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  PrintHandler
+//
+// Definition of the PrintHandler class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_PrintHandler_INCLUDED
+#define JSON_PrintHandler_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Handler.h"
+#include "Poco/JSONString.h"
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API PrintHandler: public Handler
+	/// PrintHandler formats and prints the JSON object
+	/// to either user-provided std::ostream or standard output.
+	/// If indent is zero, the output is a condensed JSON string,
+	/// otherwise, the proper indentation is applied to elements.
+{
+public:
+	typedef SharedPtr<PrintHandler> Ptr;
+
+	static const unsigned JSON_PRINT_FLAT = 0;
+
+	PrintHandler(unsigned indent = 0, int options = Poco::JSON_WRAP_STRINGS);
+		/// Creates the PrintHandler.
+
+	PrintHandler(std::ostream& out, unsigned indent = 0, int options = Poco::JSON_WRAP_STRINGS);
+		/// Creates the PrintHandler.
+
+	~PrintHandler();
+		/// Destroys the PrintHandler.
+
+	void reset();
+		/// Resets the handler state.
+
+	void startObject();
+		/// The parser has read a '{'; a new object is started.
+		/// If indent is greater than zero, a newline will be appended.
+
+	void endObject();
+		/// The parser has read a '}'; the object is closed.
+
+	void startArray();
+		/// The parser has read a [; a new array will be started.
+		/// If indent is greater than zero, a newline will be appended.
+
+	void endArray();
+		/// The parser has read a ]; the array is closed.
+
+	void key(const std::string& k);
+		/// A key of an object is read; it will be written to the output,
+		/// followed by a ':'. If indent is greater than zero, the colon
+		/// is padded by a space before and after.
+
+	void null();
+		/// A null value is read; "null" will be written to the output.
+
+	void value(int v);
+		/// An integer value is read.
+
+	void value(unsigned v);
+		/// An unsigned value is read. This will only be triggered if the
+		/// value cannot fit into a signed int.
+		
+#if defined(POCO_HAVE_INT64)
+	void value(Int64 v);
+		/// A 64-bit integer value is read; it will be written to the output.
+
+	void value(UInt64 v);
+		/// An unsigned 64-bit integer value is read; it will be written to the output.
+#endif
+
+	void value(const std::string& value);
+		/// A string value is read; it will be formatted and written to the output.
+
+	void value(double d);
+		/// A double value is read; it will be written to the output.
+
+	void value(bool b);
+		/// A boolean value is read; it will be written to the output.
+
+	void comma();
+		/// A comma is read; it will be written to the output as "true" or "false".
+
+	void setIndent(unsigned indent);
+		/// Sets indentation.
+
+private:
+	const char* endLine() const;
+	unsigned indent();
+	bool printFlat() const;
+	void arrayValue();
+	bool array() const;
+
+	std::ostream& _out;
+	unsigned      _indent;
+	std::string   _tab;
+	int           _array;
+	bool          _objStart;
+	int           _options;
+};
+
+
+//
+// inlines
+//
+inline void PrintHandler::setIndent(unsigned indent)
+{
+	_indent = indent;
+}
+
+
+inline bool PrintHandler::array() const
+{
+	return _array > 0;
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_PrintHandler_INCLUDED
diff --git a/Poco/JSON/Query.h b/Poco/JSON/Query.h
new file mode 100644
index 0000000..c639a3d
--- /dev/null
+++ b/Poco/JSON/Query.h
@@ -0,0 +1,125 @@
+//
+// Query.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Query
+//
+// Definition of the Query class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONQuery_INCLUDED
+#define JSON_JSONQuery_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Object.h"
+#include "Poco/JSON/Array.h"
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API Query
+	/// Class that can be used to search for a value in a JSON object or array.
+{
+public:
+	Query(const Dynamic::Var& source);
+		/// Creates a Query/
+		///
+		/// Source must be JSON Object, Array, Object::Ptr,
+		/// Array::Ptr or empty Var. Any other type will trigger throwing of 
+		/// InvalidArgumentException.
+		///
+		/// Creating Query holding Ptr will typically result in faster
+		/// performance.
+
+	virtual ~Query();
+		/// Destroys the Query.
+
+	Object::Ptr findObject(const std::string& path) const;
+		/// Search for an object. 
+		///
+		/// When the object can't be found, a zero Ptr is returned; 
+		/// otherwise, a shared pointer to internally held object
+		/// is returned.
+		/// If object (as opposed to a pointer to object) is held
+		/// internally, a shared pointer to new (heap-allocated) Object is
+		/// returned; this may be expensive operation.
+
+	Object& findObject(const std::string& path, Object& obj) const;
+		/// Search for an object. 
+		///
+		/// If object is found, it is assigned to the
+		/// Object through the reference passed in. When the object can't be 
+		/// found, the provided Object is emptied and returned.
+
+	Array::Ptr findArray(const std::string& path) const;
+		/// Search for an array. 
+		///
+		/// When the array can't be found, a zero Ptr is returned; 
+		/// otherwise, a shared pointer to internally held array
+		/// is returned.
+		/// If array (as opposed to a pointer to array) is held
+		/// internally, a shared pointer to new (heap-allocated) Object is
+		/// returned; this may be expensive operation.
+
+	Array& findArray(const std::string& path, Array& obj) const;
+		/// Search for an array. 
+		///
+		/// If array is found, it is assigned to the
+		/// Object through the reference passed in. When the array can't be 
+		/// found, the provided Object is emptied and returned.
+
+	Dynamic::Var find(const std::string& path) const;
+		/// Searches a value.
+		///
+		/// Example: "person.children[0].name" will return the
+		/// the name of the first child. When the value can't be found
+		/// an empty value is returned.
+
+	template<typename T>
+	T findValue(const std::string& path, const T& def) const
+		/// Searches for a value will convert it to the given type.
+		/// When the value can't be found or has an invalid type
+		/// the default value will be returned.
+	{
+		T result = def;
+		Dynamic::Var value = find(path);
+		if (!value.isEmpty())
+		{
+			try
+			{
+				result = value.convert<T>();
+			}
+			catch (...) 
+			{ 
+			}
+		}
+		return result;
+	}
+
+	std::string findValue(const char* path, const char* def) const
+		/// Searches for a value will convert it to the given type.
+		/// When the value can't be found or has an invalid type
+		/// the default value will be returned.
+	{
+		return findValue<std::string>(path, def);
+	}
+
+private:
+	Dynamic::Var _source;
+};
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONQuery_INCLUDED
diff --git a/Poco/JSON/Stringifier.h b/Poco/JSON/Stringifier.h
new file mode 100644
index 0000000..8e3303b
--- /dev/null
+++ b/Poco/JSON/Stringifier.h
@@ -0,0 +1,73 @@
+//
+// Stringifier.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Stringifier
+//
+// Definition of the Stringifier class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONStringifier_INCLUDED
+#define JSON_JSONStringifier_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSONString.h"
+#include "Poco/Dynamic/Var.h"
+#include <ostream>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API Stringifier
+	/// Helper class for creating a string from a JSON object or array.
+{
+public:
+	static void condense(const Dynamic::Var& any, std::ostream& out, int options = Poco::JSON_WRAP_STRINGS);
+		/// Writes a condensed string representation of the value to the output stream while preserving
+		/// the insertion order.
+		///
+		/// If JSON_ESCAPE_UNICODE is in options, all unicode characters will be escaped, otherwise
+		/// only the compulsory ones.
+		///
+		/// This is just a "shortcut" to stringify(any, out) with name indicating the function effect.
+
+	static void stringify(const Dynamic::Var& any, std::ostream& out,
+			unsigned int indent = 0, int step = -1, int options = Poco::JSON_WRAP_STRINGS);
+		/// Writes a string representation of the value to the output stream.
+		///
+		/// When indent is 0, the string will be created as small as possible.
+		/// Indentation is increased/decreased using number of spaces defined in step.
+		/// The default value -1 for step indicates that step will be equal to the
+		/// indent size.
+		///
+		/// If JSON_ESCAPE_UNICODE is in options, all unicode characters will be escaped, otherwise
+		/// only the compulsory ones.
+
+	static void formatString(const std::string& value, std::ostream& out, int options = Poco::JSON_WRAP_STRINGS);
+		/// Formats the JSON string and streams it into ostream.
+		///
+		/// If JSON_ESCAPE_UNICODE is in options, all unicode characters will be escaped, otherwise
+		/// only the compulsory ones.
+};
+
+
+inline void Stringifier::condense(const Dynamic::Var& any, std::ostream& out, int options)
+{
+	stringify(any, out, 0, -1, options);
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONStringifier_INCLUDED
diff --git a/Poco/JSON/Template.h b/Poco/JSON/Template.h
new file mode 100644
index 0000000..7e8ac51
--- /dev/null
+++ b/Poco/JSON/Template.h
@@ -0,0 +1,151 @@
+//
+// Template.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  Template
+//
+// Definition of the Template class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONTemplate_INCLUDED
+#define JSON_JSONTemplate_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Path.h"
+#include "Poco/Timestamp.h"
+#include <sstream>
+#include <stack>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class MultiPart;
+
+
+POCO_DECLARE_EXCEPTION(JSON_API, JSONTemplateException, Poco::Exception)
+
+
+class JSON_API Template
+	/// Template is a template engine which uses JSON as input
+	/// for generating output. There are commands for
+	/// looping over JSON arrays, include other templates,
+	/// conditional output, etc.
+	///
+	/// All text is send to the outputstream. A command is placed
+	/// between 
+	///     <?
+	/// and 
+	///     ?>
+	/// ----
+	///
+	/// These are the available commands:
+	/// 
+	///     <? echo query ?>
+	/// ----
+	/// The result of the query is send to the output stream
+	/// This command can also be written as <?= query ?>
+	/// 
+	///     <? if query ?> <? else ?> <? endif ?>
+	/// ----
+	/// When the result of query is true, all the text between
+	/// if and else (or endif when there is no else) is send to the
+	/// output stream. When the result of query is false, all the text
+	/// between else and endif is send to the output stream. An empty
+	/// object, an empty array or a null value is considered as a false value.
+	/// For numbers a zero is false. An empty String is also false.
+	///
+	///     <? ifexist query ?> <? else ?> <? endif ?>
+	/// ----
+	/// This can be used to check the existence of the value.
+	/// Use this for example when a zero value is ok (which returns false for <? if ?>.
+	/// 
+	///     <? for variable query ?> <? endfor ?>
+	/// ----
+	/// The result of the query must be an array. For each element
+	/// in the array the text between for and endfor is send to the
+	/// output stream. The active element is stored in the variable.
+	///
+	///     <? include "filename" ?>
+	/// ----
+	/// Includes a template. When the filename is relative it will try
+	/// to resolve the filename against the active template. When this
+	/// file doesn't exist, it can still be found when the JSONTemplateCache
+	/// is used.
+	///
+	///  A query is passed to Poco::JSON::Query to get the value.
+{
+public:
+	typedef SharedPtr<Template> Ptr;
+
+	Template();
+		/// Creates a Template.
+
+	Template(const Path& templatePath);
+		/// Creates a Template from the file with the given templatePath.
+
+	virtual ~Template();
+		/// Destroys the Template.
+
+	void parse();
+		/// Parse a template from a file.
+
+	void parse(const std::string& source);
+		/// Parse a template from a string.
+
+	void parse(std::istream& in);
+		/// Parse a template from an input stream.
+
+	Timestamp parseTime() const;
+		/// Returns the time when the template was parsed.
+
+	void render(const Dynamic::Var& data, std::ostream& out) const;
+		/// Renders the template and send the output to the stream.
+
+private:
+	std::string readText(std::istream& in);
+	std::string readWord(std::istream& in);
+	std::string readQuery(std::istream& in);
+	std::string readTemplateCommand(std::istream& in);
+	std::string readString(std::istream& in);
+	void readWhiteSpace(std::istream& in);
+
+	MultiPart* _parts;
+	std::stack<MultiPart*> _partStack;
+	MultiPart* _currentPart;
+	Path _templatePath;
+	Timestamp _parseTime;
+};
+
+
+//
+// inlines
+//
+inline void Template::parse(const std::string& source)
+{
+	std::istringstream is(source);
+	parse(is);
+}
+
+
+inline Timestamp Template::parseTime() const
+{
+	return _parseTime;
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONTemplate_INCLUDED
diff --git a/Poco/JSON/TemplateCache.h b/Poco/JSON/TemplateCache.h
new file mode 100644
index 0000000..0f5fcf0
--- /dev/null
+++ b/Poco/JSON/TemplateCache.h
@@ -0,0 +1,105 @@
+//
+// TemplateCache.h
+//
+// Library: JSON
+// Package: JSON
+// Module:  TemplateCache
+//
+// Definition of the TemplateCache class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef JSON_JSONTemplateCache_INCLUDED
+#define JSON_JSONTemplateCache_INCLUDED
+
+
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Template.h"
+#include "Poco/Path.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Logger.h"
+#include <vector>
+#include <map>
+
+
+namespace Poco {
+namespace JSON {
+
+
+class JSON_API TemplateCache
+	/// Use to cache parsed templates. Templates are
+	/// stored in a map with the full path as key.
+	/// When a template file has changed, the cache
+	/// will remove the old template from the cache
+	/// and load a new one.
+{
+public:
+	TemplateCache();
+		/// Creates an empty TemplateCache.
+		///
+		/// The cache must be created and not destroyed 
+		/// as long as it is used.
+
+	virtual ~TemplateCache();
+		/// Destroys the TemplateCache.
+
+	void addPath(const Path& path);
+		/// Add a path for resolving template paths.
+		/// The order of check is FIFO.
+
+	Template::Ptr getTemplate(const Path& path);
+		/// Returns a template from the cache.
+		/// When the template file is not yet loaded
+		/// or when the file has changed, the template
+		/// will be (re)loaded and parsed. A shared pointer
+		/// is returned, so it is safe to use this template
+		/// even when the template isn't stored anymore in
+		/// the cache.
+
+	static TemplateCache* instance();
+		/// Returns the only instance of this cache.
+
+	void setLogger(Logger& logger);
+		/// Sets the logger for the cache.
+
+private:
+	void setup();
+	Path resolvePath(const Path& path) const;
+
+	static TemplateCache*                _pInstance;
+	std::vector<Path>                    _includePaths;
+	std::map<std::string, Template::Ptr> _cache;
+	Logger*                              _pLogger;
+};
+
+
+//
+// inlines
+//
+inline void TemplateCache::addPath(const Path& path)
+{
+	_includePaths.push_back(path);
+}
+
+
+inline TemplateCache* TemplateCache::instance()
+{
+	return _pInstance;
+}
+
+
+inline void TemplateCache::setLogger(Logger& logger)
+{
+	_pLogger = &logger;
+}
+
+
+} } // namespace Poco::JSON
+
+
+#endif // JSON_JSONTemplateCache_INCLUDED
diff --git a/Poco/JSONString.h b/Poco/JSONString.h
new file mode 100644
index 0000000..b4446ef
--- /dev/null
+++ b/Poco/JSONString.h
@@ -0,0 +1,93 @@
+//
+// JSONString.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  String
+//
+// JSONString utility functions.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_JSONString_INCLUDED
+#define Foundation_JSONString_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+enum JSONOptions
+{
+	JSON_PRESERVE_KEY_ORDER = 1,
+		/// Applies to JSON::Object. If specified, the Object will
+		/// preserve the items insertion order. Otherwise, items
+		/// will be sorted by keys.
+		///
+		/// Has no effect on toJSON() function.
+
+	JSON_ESCAPE_UNICODE = 2,
+		/// If specified, when the object is stringified, all
+		/// unicode characters will be escaped in the resulting
+		/// string.
+
+	JSON_WRAP_STRINGS = 4
+		/// If specified, the object will preserve the items
+		/// insertion order. Otherwise, items will be sorted
+		/// by keys.
+	};
+
+
+//@ deprecated
+void Foundation_API toJSON(const std::string& value, std::ostream& out, bool wrap = true);
+	/// Formats string value into the supplied output stream by
+	/// escaping control and ALL Unicode characters.
+	/// If wrap is true, the resulting string is enclosed in double quotes.
+	///
+	/// This function is deprecated, please use
+	///
+	/// void Poco::toJSON(const std::string&, std::ostream&, int)
+
+
+//@ deprecated
+std::string Foundation_API toJSON(const std::string& value, bool wrap = true);
+	/// Formats string value by escaping control and ALL Unicode characters.
+	/// If wrap is true, the resulting string is enclosed in double quotes
+	///
+	/// Returns formatted string.
+	///
+	/// This function is deprecated, please use
+	///
+	/// std::string Poco::toJSON(const std::string&, int)
+
+
+void Foundation_API toJSON(const std::string& value, std::ostream& out, int options);
+	/// Formats string value into the supplied output stream by
+	/// escaping control characters.
+	/// If JSON_WRAP_STRINGS is in options, the resulting strings is enclosed in double quotes
+	/// If JSON_ESCAPE_UNICODE is in options, all unicode characters will be escaped, otherwise
+	/// only the compulsory ones.
+
+
+std::string Foundation_API toJSON(const std::string& value, int options);
+	/// Formats string value by escaping control characters.
+	/// If JSON_WRAP_STRINGS is in options, the resulting string is enclosed in double quotes
+	/// If JSON_ESCAPE_UNICODE is in options, all unicode characters will be escaped, otherwise
+	/// only the compulsory ones.
+	///
+	/// Returns formatted string.
+	/// If escapeAllUnicode is true, all unicode characters will be escaped, otherwise only the compulsory ones.
+
+
+
+} // namespace Poco
+
+
+#endif // Foundation_JSONString_INCLUDED
diff --git a/Poco/KeyValueArgs.h b/Poco/KeyValueArgs.h
new file mode 100644
index 0000000..cdcc4e1
--- /dev/null
+++ b/Poco/KeyValueArgs.h
@@ -0,0 +1,73 @@
+//
+// KeyValueArgs.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  KeyValueArgs
+//
+// Definition of the KeyValueArgs class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_KeyValueArgs_INCLUDED
+#define Foundation_KeyValueArgs_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class TKey, class TValue> 
+class KeyValueArgs
+	/// Simply event arguments class to transfer a key and a value via an event call.
+	/// Note that key and value are *NOT* copied, only references to them are stored.
+{
+public:
+	KeyValueArgs(const TKey& aKey, const TValue& aVal): 
+		_key(aKey), 
+		_value(aVal)
+	{
+	}
+
+	KeyValueArgs(const KeyValueArgs& args):
+		_key(args._key), 
+		_value(args._value)
+	{
+	}
+
+	~KeyValueArgs()
+	{
+	}
+
+	const TKey& key() const
+		/// Returns a reference to the key,
+	{
+		return _key;
+	}
+
+	const TValue& value() const
+		/// Returns a Reference to the value.
+	{
+		return _value;
+	}
+
+protected:
+	const TKey&   _key;
+	const TValue& _value;
+
+private:
+	KeyValueArgs& operator = (const KeyValueArgs& args);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_KeyValueArgs_INCLUDED
diff --git a/Poco/LRUCache.h b/Poco/LRUCache.h
new file mode 100644
index 0000000..7f8f0de
--- /dev/null
+++ b/Poco/LRUCache.h
@@ -0,0 +1,56 @@
+//
+// LRUCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  LRUCache
+//
+// Definition of the LRUCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LRUCache_INCLUDED
+#define Foundation_LRUCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/LRUStrategy.h"
+
+
+namespace Poco {
+
+
+template <
+	class TKey, 
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+> 
+class LRUCache: public AbstractCache<TKey, TValue, LRUStrategy<TKey, TValue>, TMutex, TEventMutex>
+	/// An LRUCache implements Least Recently Used caching. The default size for a cache is 1024 entries.
+{
+public:
+	LRUCache(long size = 1024):
+		AbstractCache<TKey, TValue, LRUStrategy<TKey, TValue>, TMutex, TEventMutex>(LRUStrategy<TKey, TValue>(size))
+	{
+	}
+
+	~LRUCache()
+	{
+	}
+
+private:
+	LRUCache(const LRUCache& aCache);
+	LRUCache& operator = (const LRUCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LRUCache_INCLUDED
diff --git a/Poco/LRUStrategy.h b/Poco/LRUStrategy.h
new file mode 100644
index 0000000..c7180bd
--- /dev/null
+++ b/Poco/LRUStrategy.h
@@ -0,0 +1,140 @@
+//
+// LRUStrategy.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  LRUStrategy
+//
+// Definition of the LRUStrategy class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LRUStrategy_INCLUDED
+#define Foundation_LRUStrategy_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/AbstractStrategy.h"
+#include "Poco/EventArgs.h"
+#include "Poco/Exception.h"
+#include <list>
+#include <map>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+template <class TKey, class TValue>
+class LRUStrategy: public AbstractStrategy<TKey, TValue>
+	/// An LRUStrategy implements least recently used cache replacement.
+{
+public:
+	typedef std::list<TKey>                   Keys;
+	typedef typename Keys::iterator           Iterator;
+	typedef typename Keys::const_iterator     ConstIterator;
+	typedef std::map<TKey, Iterator>          KeyIndex;
+	typedef typename KeyIndex::iterator       IndexIterator;
+	typedef typename KeyIndex::const_iterator ConstIndexIterator;
+
+public:
+	LRUStrategy(std::size_t size): 
+		_size(size)
+	{
+		if (_size < 1) throw InvalidArgumentException("size must be > 0");
+	}
+
+	~LRUStrategy()
+	{
+	}
+
+	void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
+	{
+		_keys.push_front(args.key());
+		std::pair<IndexIterator, bool> stat = _keyIndex.insert(std::make_pair(args.key(), _keys.begin()));
+		if (!stat.second)
+		{
+			stat.first->second = _keys.begin();
+		}
+	}
+
+	void onRemove(const void*, const TKey& key)
+	{
+		IndexIterator it = _keyIndex.find(key);
+
+		if (it != _keyIndex.end())
+		{
+			_keys.erase(it->second);
+			_keyIndex.erase(it);
+		}
+	}
+
+	void onGet(const void*, const TKey& key)
+	{
+		// LRU: in case of an hit, move to begin
+		IndexIterator it = _keyIndex.find(key);
+
+		if (it != _keyIndex.end())
+		{
+			_keys.splice(_keys.begin(), _keys, it->second); //_keys.erase(it->second)+_keys.push_front(key);
+			it->second = _keys.begin();
+		}
+	}
+
+	void onClear(const void*, const EventArgs& args)
+	{
+		_keys.clear();
+		_keyIndex.clear();
+	}
+
+	void onIsValid(const void*, ValidArgs<TKey>& args)
+	{
+		if (_keyIndex.find(args.key()) == _keyIndex.end())
+		{
+			args.invalidate();
+		}
+	}
+
+	void onReplace(const void*, std::set<TKey>& elemsToRemove)
+	{
+		// Note: replace only informs the cache which elements
+		// it would like to remove!
+		// it does not remove them on its own!
+		std::size_t curSize = _keyIndex.size();
+
+		if (curSize < _size)
+		{
+			return;
+		}
+
+		std::size_t diff = curSize - _size;
+		Iterator it = --_keys.end(); //--keys can never be invoked on an empty list due to the minSize==1 requirement of LRU
+		std::size_t i = 0;
+
+		while (i++ < diff) 
+		{
+			elemsToRemove.insert(*it);
+			if (it != _keys.begin())
+			{
+				--it;
+			}
+		}
+	}
+
+protected:
+	std::size_t _size;     /// Number of keys the cache can store.
+	Keys        _keys;
+	KeyIndex    _keyIndex; /// For faster access to _keys
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LRUStrategy_INCLUDED
diff --git a/Poco/Latin1Encoding.h b/Poco/Latin1Encoding.h
new file mode 100644
index 0000000..b1b987e
--- /dev/null
+++ b/Poco/Latin1Encoding.h
@@ -0,0 +1,51 @@
+//
+// Latin1Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Latin1Encoding
+//
+// Definition of the Latin1Encoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Latin1Encoding_INCLUDED
+#define Foundation_Latin1Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Latin1Encoding: public TextEncoding
+	/// ISO Latin-1 (8859-1) text encoding.
+{
+public:
+	Latin1Encoding();
+	~Latin1Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Latin1Encoding_INCLUDED
diff --git a/Poco/Latin2Encoding.h b/Poco/Latin2Encoding.h
new file mode 100644
index 0000000..ac1cfec
--- /dev/null
+++ b/Poco/Latin2Encoding.h
@@ -0,0 +1,54 @@
+//
+// Latin2Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Latin2Encoding
+//
+// Definition of the Latin2Encoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Latin2Encoding_INCLUDED
+#define Foundation_Latin2Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Latin2Encoding: public TextEncoding
+	/// ISO Latin-2 (8859-2) text encoding.
+	///
+	/// Latin-2 is basically Latin-1 with the EURO sign plus
+	/// some other minor changes.
+{
+public:
+	Latin2Encoding();
+	virtual ~Latin2Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Latin2Encoding_INCLUDED
diff --git a/Poco/Latin9Encoding.h b/Poco/Latin9Encoding.h
new file mode 100644
index 0000000..d2b7a1c
--- /dev/null
+++ b/Poco/Latin9Encoding.h
@@ -0,0 +1,54 @@
+//
+// Latin9Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Latin9Encoding
+//
+// Definition of the Latin9Encoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Latin9Encoding_INCLUDED
+#define Foundation_Latin9Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Latin9Encoding: public TextEncoding
+	/// ISO Latin-9 (8859-15) text encoding.
+	///
+	/// Latin-9 is basically Latin-1 with the EURO sign plus
+	/// some other minor changes.
+{
+public:
+	Latin9Encoding();
+	~Latin9Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Latin9Encoding_INCLUDED
diff --git a/Poco/LineEndingConverter.h b/Poco/LineEndingConverter.h
new file mode 100644
index 0000000..d23414c
--- /dev/null
+++ b/Poco/LineEndingConverter.h
@@ -0,0 +1,181 @@
+//
+// LineEndingConverter.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  LineEndingConverter
+//
+// Definition of the LineEndingConverter class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LineEndingConverter_INCLUDED
+#define Foundation_LineEndingConverter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API LineEnding
+	/// This class defines valid line ending sequences
+	/// for InputLineEndingConverter and OutputLineEndingConverter.
+{
+public:
+	static const std::string NEWLINE_DEFAULT;
+	static const std::string NEWLINE_CR;
+	static const std::string NEWLINE_CRLF;
+	static const std::string NEWLINE_LF;
+};
+
+
+class Foundation_API LineEndingConverterStreamBuf: public UnbufferedStreamBuf
+	/// This stream buffer performs line ending conversion
+	/// on text streams. The converter can convert from and to 
+	/// the Unix (LF), Mac (CR) and DOS/Windows/Network (CF-LF) endings.
+	///
+	/// Any newline sequence in the source will be replaced by the
+	/// target newline sequence.
+{
+public:
+	LineEndingConverterStreamBuf(std::istream& istr);
+		/// Creates the LineEndingConverterStreamBuf and connects it
+		/// to the given input stream.
+
+	LineEndingConverterStreamBuf(std::ostream& ostr);
+		/// Creates the LineEndingConverterStreamBuf and connects it
+		/// to the given output stream.
+
+	~LineEndingConverterStreamBuf();
+		/// Destroys the LineEndingConverterStream.
+		
+	void setNewLine(const std::string& newLineCharacters);
+		/// Sets the target line ending for the converter.
+		///
+		/// Possible values are:
+		///   * NEWLINE_DEFAULT (whatever is appropriate for the current platform)
+		///   * NEWLINE_CRLF    (Windows),
+		///   * NEWLINE_LF      (Unix),
+		///   * NEWLINE_CR      (Macintosh)
+		///
+		/// In theory, any character sequence can be used as newline sequence.
+		/// In practice, however, only the above three make sense.
+
+	const std::string& getNewLine() const;
+		/// Returns the line ending currently in use.
+
+protected:
+	int readFromDevice();
+	int writeToDevice(char c);
+
+private:
+	std::istream*               _pIstr;
+	std::ostream*               _pOstr;
+	std::string                 _newLine;
+	std::string::const_iterator _it;
+	char                        _lastChar;
+};
+
+
+class Foundation_API LineEndingConverterIOS: public virtual std::ios
+	/// The base class for InputLineEndingConverter and OutputLineEndingConverter.
+	///
+	/// This class provides common methods and is also needed to ensure 
+	/// the correct initialization order of the stream buffer and base classes.
+{
+public:
+	LineEndingConverterIOS(std::istream& istr);
+		/// Creates the LineEndingConverterIOS and connects it
+		/// to the given input stream.
+
+	LineEndingConverterIOS(std::ostream& ostr);
+		/// Creates the LineEndingConverterIOS and connects it
+		/// to the given output stream.
+
+	~LineEndingConverterIOS();
+		/// Destroys the stream.
+
+	void setNewLine(const std::string& newLineCharacters);
+		/// Sets the target line ending for the converter.
+		///
+		/// Possible values are:
+		///   * NEWLINE_DEFAULT (whatever is appropriate for the current platform)
+		///   * NEWLINE_CRLF    (Windows),
+		///   * NEWLINE_LF      (Unix),
+		///   * NEWLINE_CR      (Macintosh)
+		///
+		/// In theory, any character sequence can be used as newline sequence.
+		/// In practice, however, only the above three make sense.
+		///
+		/// If an empty string is given, all newline characters are removed from
+		/// the stream.
+
+	const std::string& getNewLine() const;
+		/// Returns the line ending currently in use.
+
+	LineEndingConverterStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	LineEndingConverterStreamBuf _buf;
+};
+
+
+class Foundation_API InputLineEndingConverter: public LineEndingConverterIOS, public std::istream
+	/// InputLineEndingConverter performs line ending conversion
+	/// on text input streams. The converter can convert from and to 
+	/// the Unix (LF), Mac (CR) and DOS/Windows/Network (CF-LF) endings.
+	///
+	/// Any newline sequence in the source will be replaced by the
+	/// target newline sequence.
+{
+public:
+	InputLineEndingConverter(std::istream& istr);
+		/// Creates the LineEndingConverterInputStream and connects it
+		/// to the given input stream.
+
+	InputLineEndingConverter(std::istream& istr, const std::string& newLineCharacters);
+		/// Creates the LineEndingConverterInputStream and connects it
+		/// to the given input stream.
+
+	~InputLineEndingConverter();
+		/// Destroys the stream.
+};
+
+
+class Foundation_API OutputLineEndingConverter: public LineEndingConverterIOS, public std::ostream
+	/// OutputLineEndingConverter performs line ending conversion
+	/// on text output streams. The converter can convert from and to 
+	/// the Unix (LF), Mac (CR) and DOS/Windows/Network (CF-LF) endings.
+	///
+	/// Any newline sequence in the source will be replaced by the
+	/// target newline sequence.
+{
+public:
+	OutputLineEndingConverter(std::ostream& ostr);
+		/// Creates the LineEndingConverterOutputStream and connects it
+		/// to the given input stream.
+
+	OutputLineEndingConverter(std::ostream& ostr, const std::string& newLineCharacters);
+		/// Creates the LineEndingConverterOutputStream and connects it
+		/// to the given input stream.
+
+	~OutputLineEndingConverter();
+		/// Destroys the LineEndingConverterOutputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LineEndingConverter_INCLUDED
diff --git a/Poco/LinearHashTable.h b/Poco/LinearHashTable.h
new file mode 100644
index 0000000..ac18b4b
--- /dev/null
+++ b/Poco/LinearHashTable.h
@@ -0,0 +1,503 @@
+//
+// LinearHashTable.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  LinearHashTable
+//
+// Definition of the LinearHashTable class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LinearHashTable_INCLUDED
+#define Foundation_LinearHashTable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Hash.h"
+#include <functional>
+#include <algorithm>
+#include <vector>
+#include <utility>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+template <class Value, class HashFunc = Hash<Value> >
+class LinearHashTable
+	/// This class implements a linear hash table.
+	///
+	/// In a linear hash table, the available address space
+	/// grows or shrinks dynamically. A linar hash table thus
+	/// supports any number of insertions or deletions without
+	/// lookup or insertion performance deterioration.
+	///
+	/// Linear hashing was discovered by Witold Litwin in 1980
+	/// and described in the paper LINEAR HASHING: A NEW TOOL FOR FILE AND TABLE ADDRESSING.
+	///
+	/// For more information on linear hashing, see <http://en.wikipedia.org/wiki/Linear_hash>.
+	///
+	/// The LinearHashTable is not thread safe.
+	///
+	/// Value must support comparison for equality.
+	///
+	/// Find, insert and delete operations are basically O(1) with regard
+	/// to the total number of elements in the table, and O(N) with regard
+	/// to the number of elements in the bucket where the element is stored.
+	/// On average, every bucket stores one element; the exact number depends
+	/// on the quality of the hash function. In most cases, the maximum number of
+	/// elements in a bucket should not exceed 3.
+{
+public:
+	typedef Value               ValueType;
+	typedef Value&              Reference;
+	typedef const Value&        ConstReference;
+	typedef Value*              Pointer;
+	typedef const Value*        ConstPointer;
+	typedef HashFunc            Hash;
+	typedef std::vector<Value>  Bucket;
+	typedef std::vector<Bucket> BucketVec;
+	typedef typename Bucket::iterator    BucketIterator;
+	typedef typename BucketVec::iterator BucketVecIterator;
+
+	class ConstIterator: public std::iterator<std::forward_iterator_tag, Value>
+	{
+	public:
+		ConstIterator(): _initialized(false)
+		{
+		}
+		
+		ConstIterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt):
+			_vecIt(vecIt),
+			_endIt(endIt),
+			_buckIt(buckIt),
+			_initialized(true)
+		{
+		}
+
+		ConstIterator(const ConstIterator& it):
+			_vecIt(it._vecIt),
+			_endIt(it._endIt),
+			_buckIt(it._buckIt),
+			_initialized(it._initialized)
+
+		{
+		}
+		
+		ConstIterator& operator = (const ConstIterator& it)
+		{
+			ConstIterator tmp(it);
+			swap(tmp);
+			return *this;
+		}
+		
+		void swap(ConstIterator& it)
+		{
+			using std::swap;
+			// uninitialized iterators crash when swapped
+			if (_initialized)
+			{
+				swap(_vecIt, it._vecIt);
+				swap(_endIt, it._endIt);
+				swap(_buckIt, it._buckIt);
+				swap(_initialized, it._initialized);
+			}
+			else 
+			{
+				_vecIt = it._vecIt;
+				_endIt = it._endIt;
+				_buckIt = it._buckIt;
+				_initialized = it._initialized;
+			}
+		}
+		
+		bool operator == (const ConstIterator& it) const
+		{
+			return _vecIt == it._vecIt && (_vecIt == _endIt || _buckIt == it._buckIt);
+		}
+
+		bool operator != (const ConstIterator& it) const
+		{
+			return _vecIt != it._vecIt || (_vecIt != _endIt && _buckIt != it._buckIt);
+		}
+		
+		const typename Bucket::value_type& operator * () const
+		{
+			return *_buckIt;
+		}
+
+		const typename Bucket::value_type* operator -> () const
+		{
+			return &*_buckIt;
+		}
+		
+		ConstIterator& operator ++ () // prefix
+		{
+			if (_vecIt != _endIt)
+			{
+				++_buckIt;
+				while (_vecIt != _endIt && _buckIt == _vecIt->end())
+				{
+					++_vecIt;
+					if (_vecIt != _endIt) _buckIt = _vecIt->begin();
+				}
+			}
+			return *this;
+		}
+		
+		ConstIterator operator ++ (int) // postfix
+		{
+			ConstIterator tmp(*this);
+			++*this;
+			return tmp;
+		}
+		
+	protected:
+		BucketVecIterator _vecIt;
+		BucketVecIterator _endIt;
+		BucketIterator    _buckIt;
+		bool              _initialized;
+		
+		friend class LinearHashTable;
+	};
+	
+	class Iterator: public ConstIterator
+	{
+	public:
+		Iterator()
+		{
+		}
+		
+		Iterator(const BucketVecIterator& vecIt, const BucketVecIterator& endIt, const BucketIterator& buckIt):
+			ConstIterator(vecIt, endIt, buckIt)
+		{
+		}
+
+		Iterator(const Iterator& it):
+			ConstIterator(it)
+		{
+		}
+		
+		Iterator& operator = (const Iterator& it)
+		{
+			Iterator tmp(it);
+			ConstIterator::swap(tmp);
+			return *this;
+		}
+		
+		void swap(Iterator& it)
+		{
+			ConstIterator::swap(it);
+		}
+				
+		typename Bucket::value_type& operator * ()
+		{
+			return *this->_buckIt;
+		}
+
+		const typename Bucket::value_type& operator * () const
+		{
+			return *this->_buckIt;
+		}
+
+		typename Bucket::value_type* operator -> ()
+		{
+			return &*this->_buckIt;
+		}
+
+		const typename Bucket::value_type* operator -> () const
+		{
+			return &*this->_buckIt;
+		}
+		
+		Iterator& operator ++ () // prefix
+		{
+			ConstIterator::operator ++ ();
+			return *this;
+		}
+		
+		Iterator operator ++ (int) // postfix
+		{
+			Iterator tmp(*this);
+			++*this;
+			return tmp;
+		}
+
+		friend class LinearHashTable;
+	};
+	
+	LinearHashTable(std::size_t initialReserve = 64): 
+		_split(0),
+		_front(1),
+		_size(0)
+		/// Creates the LinearHashTable, using the given initialReserve.
+	{
+		_buckets.reserve(calcSize(initialReserve));
+		_buckets.push_back(Bucket());
+	}
+	
+	LinearHashTable(const LinearHashTable& table):
+		_buckets(table._buckets),
+		_split(table._split),
+		_front(table._front),
+		_size(table._size)
+		/// Creates the LinearHashTable by copying another one.
+	{
+	}
+	
+	~LinearHashTable()
+		/// Destroys the LinearHashTable.
+	{
+	}
+	
+	LinearHashTable& operator = (const LinearHashTable& table)
+		/// Assigns another LinearHashTable.
+	{
+		LinearHashTable tmp(table);
+		swap(tmp);
+		return *this;
+	}
+	
+	void swap(LinearHashTable& table)
+		/// Swaps the LinearHashTable with another one.
+	{
+		using std::swap;
+		swap(_buckets, table._buckets);
+		swap(_split, table._split);
+		swap(_front, table._front);
+		swap(_size, table._size);
+	}
+	
+	ConstIterator begin() const
+		/// Returns an iterator pointing to the first entry, if one exists.
+	{
+		BucketVecIterator it(_buckets.begin());
+		BucketVecIterator end(_buckets.end());
+		while (it != end && it->empty())
+		{
+			++it;
+		}
+		if (it == end)
+			return this->end();
+		else
+			return ConstIterator(it, end, it->begin());
+	}
+	
+	ConstIterator end() const
+		/// Returns an iterator pointing to the end of the table.
+	{
+		return ConstIterator(_buckets.end(), _buckets.end(), _buckets.front().end());
+	}
+	
+	Iterator begin()
+		/// Returns an iterator pointing to the first entry, if one exists.
+	{
+		BucketVecIterator it(_buckets.begin());
+		BucketVecIterator end(_buckets.end());
+		while (it != end && it->empty())
+		{
+			++it;
+		}
+		if (it == end)
+			return this->end();
+		else
+			return Iterator(it, end, it->begin());
+	}
+	
+	Iterator end()
+		/// Returns an iterator pointing to the end of the table.
+	{
+		return Iterator(_buckets.end(), _buckets.end(), _buckets.front().end());
+	}
+		
+	ConstIterator find(const Value& value) const
+		/// Finds an entry in the table.
+	{
+		std::size_t addr = bucketAddress(value);
+		BucketVecIterator it(_buckets.begin() + addr);
+		BucketIterator buckIt(std::find(it->begin(), it->end(), value));
+		if (buckIt != it->end())
+			return ConstIterator(it, _buckets.end(), buckIt);
+		else
+			return end();
+	}
+
+	Iterator find(const Value& value)
+		/// Finds an entry in the table.
+	{
+		std::size_t addr = bucketAddress(value);
+		BucketVecIterator it(_buckets.begin() + addr);
+		BucketIterator buckIt(std::find(it->begin(), it->end(), value));
+		if (buckIt != it->end())
+			return Iterator(it, _buckets.end(), buckIt);
+		else
+			return end();
+	}
+	
+	std::size_t count(const Value& value) const
+		/// Returns the number of elements with the given
+		/// value, with is either 1 or 0.
+	{
+		return find(value) != end() ? 1 : 0;
+	}
+	
+	std::pair<Iterator, bool> insert(const Value& value)
+		/// Inserts an element into the table.
+		///
+		/// If the element already exists in the table,
+		/// a pair(iterator, false) with iterator pointing to the 
+		/// existing element is returned.
+		/// Otherwise, the element is inserted an a 
+		/// pair(iterator, true) with iterator
+		/// pointing to the new element is returned.
+	{
+		std::size_t hash = _hash(value);
+		std::size_t addr = bucketAddressForHash(hash);
+		BucketVecIterator it(_buckets.begin() + addr);
+		BucketIterator buckIt(std::find(it->begin(), it->end(), value));
+		if (buckIt == it->end())
+		{
+			split();
+			addr = bucketAddressForHash(hash);
+			it = _buckets.begin() + addr;
+			buckIt = it->insert(it->end(), value);
+			++_size;
+			return std::make_pair(Iterator(it, _buckets.end(), buckIt), true);
+		}
+		else
+		{
+			return std::make_pair(Iterator(it, _buckets.end(), buckIt), false);
+		}
+	}
+	
+	void erase(Iterator it)
+		/// Erases the element pointed to by it.
+	{
+		if (it != end())
+		{
+			it._vecIt->erase(it._buckIt);
+			--_size;
+			merge();
+		}
+	}
+	
+	void erase(const Value& value)
+		/// Erases the element with the given value, if it exists.
+	{
+		Iterator it = find(value);
+		erase(it);
+	}
+	
+	void clear()
+		/// Erases all elements.
+	{
+		LinearHashTable empty;
+		swap(empty);
+	}
+	
+	std::size_t size() const
+		/// Returns the number of elements in the table.
+	{
+		return _size;
+	}
+	
+	bool empty() const
+		/// Returns true iff the table is empty.
+	{
+		return _size == 0;
+	}
+	
+	std::size_t buckets() const
+		/// Returns the number of allocated buckets.
+	{
+		return _buckets.size();
+	}
+	
+protected:
+	std::size_t bucketAddress(const Value& value) const
+	{
+		std::size_t n = _hash(value);
+		if (n % _front >= _split)
+			return n % _front;
+		else
+			return n % (2*_front);
+	}
+	
+	std::size_t bucketAddressForHash(std::size_t hash)
+	{
+		if (hash % _front >= _split)
+			return hash % _front;
+		else
+			return hash % (2*_front);
+	}
+	
+	void split()
+	{
+		if (_split == _front)
+		{
+			_split = 0;
+			_front *= 2;
+			_buckets.reserve(_front*2);
+		}
+		Bucket tmp;
+		_buckets.push_back(tmp);
+		_buckets[_split].swap(tmp);
+		++_split;
+		for (BucketIterator it = tmp.begin(); it != tmp.end(); ++it)
+		{
+			using std::swap;
+			std::size_t addr = bucketAddress(*it);
+			_buckets[addr].push_back(Value());
+			swap(*it, _buckets[addr].back());
+		}
+	}
+	
+	void merge()
+	{
+		if (_split == 0)
+		{
+			_front /= 2;
+			_split = _front;
+		}
+		--_split;
+		Bucket tmp;
+		tmp.swap(_buckets.back());
+		_buckets.pop_back();
+		for (BucketIterator it = tmp.begin(); it != tmp.end(); ++it)
+		{
+			using std::swap;
+			std::size_t addr = bucketAddress(*it);
+			_buckets[addr].push_back(Value());
+			swap(*it, _buckets[addr].back());
+		}
+	}
+	
+	static std::size_t calcSize(std::size_t initialSize)
+	{
+		std::size_t size = 32;
+		while (size < initialSize) size *= 2;
+		return size;
+	}
+	
+private:
+	// Evil hack: _buckets must be mutable because both ConstIterator and Iterator hold 
+	// ordinary iterator's (not const_iterator's).
+	mutable BucketVec _buckets;
+	std::size_t _split;
+	std::size_t _front;
+	std::size_t _size;
+	HashFunc    _hash;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LinearHashTable_INCLUDED
diff --git a/Poco/ListMap.h b/Poco/ListMap.h
new file mode 100644
index 0000000..03c056d
--- /dev/null
+++ b/Poco/ListMap.h
@@ -0,0 +1,246 @@
+//
+// ListMap.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  ListMap
+//
+// Definition of the ListMap class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ListMap_INCLUDED
+#define Foundation_ListMap_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/String.h"
+#include "Poco/Exception.h"
+#include <list>
+#include <utility>
+
+
+namespace Poco {
+
+
+template <class Key, class Mapped, class Container = std::list<std::pair<Key, Mapped> >, bool CaseSensitive = false >
+class ListMap
+	/// This class implements a multimap in terms of a sequential container.
+	/// The use for this type of associative container is wherever automatic
+	/// ordering of elements is not desirable. Naturally, this container will
+	/// have inferior data retrieval performance and it is not recommended for
+	/// use with large datasets. The main purpose within POCO is for Internet
+	/// messages (email message, http headers etc), to prevent automatic 
+	/// header entry reordering.
+{
+public:
+	typedef Key                 KeyType;
+	typedef Mapped              MappedType;
+	typedef Mapped&             Reference;
+	typedef const Mapped&       ConstReference;
+	typedef Mapped*             Pointer;
+	typedef const Mapped*       ConstPointer;
+	
+	typedef typename Container::value_type     ValueType;
+	typedef typename Container::size_type      SizeType;
+	typedef typename Container::iterator       Iterator;
+	typedef typename Container::const_iterator ConstIterator;
+	
+	ListMap()
+		/// Creates an empty ListMap.
+	{
+	}
+	
+	ListMap(std::size_t initialReserve):
+		_list(initialReserve)
+		/// Creates the ListMap with room for initialReserve entries.
+	{
+	}
+	
+	ListMap& operator = (const ListMap& map)
+		/// Assigns another ListMap.
+	{
+		ListMap tmp(map);
+		swap(tmp);
+		return *this;
+	}
+	
+	void swap(ListMap& map)
+		/// Swaps the ListMap with another one.
+	{
+		_list.swap(map._list);
+	}
+	
+	ConstIterator begin() const
+		/// Returns the beginning of the map.
+	{
+		return _list.begin();
+	}
+	
+	ConstIterator end() const
+		/// Returns the end of the map.
+	{
+		return _list.end();
+	}
+	
+	Iterator begin()
+		/// Returns the beginning of the map.
+	{
+		return _list.begin();
+	}
+	
+	Iterator end()
+		/// Returns the end of the map.
+	{
+		return _list.end();
+	}
+	
+	ConstIterator find(const KeyType& key) const
+		/// Finds the first occurrence of the key and
+		/// returns iterator pointing to the found entry
+		/// or iterator pointing to the end if entry is
+		/// not found.
+	{
+		typename Container::const_iterator it = _list.begin();
+		typename Container::const_iterator itEnd = _list.end();
+		for(; it != itEnd; ++it)
+		{
+			if (isEqual(it->first, key)) return it;
+		}
+		return itEnd;
+	}
+
+	Iterator find(const KeyType& key)
+		/// Finds the first occurrence of the key and
+		/// returns iterator pointing to the found entry
+		/// or iterator pointing to the end if entry is
+		/// not found.
+	{
+		typename Container::iterator it = _list.begin();
+		typename Container::iterator itEnd = _list.end();
+		for(; it != itEnd; ++it)
+		{
+			if (isEqual(it->first, key)) return it;
+		}
+		return itEnd;
+	}
+
+	Iterator insert(const ValueType& val)
+		/// Inserts the value into the map. If one or more values 
+		/// already exist, new value is inserted at the end of the 
+		/// block. Thus, all the equal value entries are located
+		/// sequentially at all times.
+		/// Returns iterator pointing to the newly inserted value 
+	{
+		Iterator it = find(val.first);
+		while (it != _list.end() && isEqual(it->first, val.first)) ++it;
+		return _list.insert(it, val);
+	}
+	
+	void erase(Iterator it)
+	{
+		_list.erase(it);
+	}
+	
+	SizeType erase(const KeyType& key)
+	{
+		SizeType count = 0;
+		Iterator it = find(key);
+		bool removed = false;
+		while (it != _list.end())
+		{
+			if (isEqual(it->first, key))
+			{
+				++count;
+				it = _list.erase(it);
+				removed = true;
+			}
+			else
+			{
+				if (removed) return count;
+				++it;
+			}
+		}
+		return count;
+	}
+	
+	void clear()
+	{
+		_list.clear();
+	}
+
+	std::size_t size() const
+	{
+		return _list.size();
+	}
+
+	bool empty() const
+	{
+		return _list.empty();
+	}
+
+	ConstReference operator [] (const KeyType& key) const
+	{
+		ConstIterator it = find(key);
+		if (it != _list.end())
+			return it->second;
+		else
+			throw NotFoundException();
+	}
+
+	Reference operator [] (const KeyType& key)
+	{
+		Iterator it = find(key);
+		if (it != _list.end())
+			return it->second;
+		else
+		{
+			ValueType value(key, Mapped());
+			Iterator itInsert = insert(value);
+			return itInsert->second;
+		}
+	}
+
+private:
+	template <typename T1, typename T2>
+	bool isEqual(T1 val1, T2 val2) const
+	{
+		return val1 == val2;
+	}
+
+	bool isEqual(const std::string& s1, const std::string& s2) const
+	{
+		if (!CaseSensitive)
+			return Poco::icompare(s1, s2) == 0;
+		else
+			return s1 == s2;
+	}
+
+	bool isEqual(const std::string& s1, const char* s2) const
+	{
+		return isEqual(s1, std::string(s2));
+	}
+
+	bool isEqual(const char* s1, const std::string& s2) const
+	{
+		return isEqual(std::string(s1), s2);
+	}
+
+	bool isEqual(const char* s1, const char* s2) const
+	{
+		return isEqual(std::string(s1), std::string(s2));
+	}
+
+	Container _list;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ListMap_INCLUDED
diff --git a/Poco/LocalDateTime.h b/Poco/LocalDateTime.h
new file mode 100644
index 0000000..08c90b6
--- /dev/null
+++ b/Poco/LocalDateTime.h
@@ -0,0 +1,388 @@
+//
+// LocalDateTime.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  LocalDateTime
+//
+// Definition of the LocalDateTime class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LocalDateTime_INCLUDED
+#define Foundation_LocalDateTime_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DateTime.h"
+
+
+namespace Poco {
+
+
+class Foundation_API LocalDateTime
+	/// This class represents an instant in local time
+	/// (as opposed to UTC), expressed in years, months, days, 
+	/// hours, minutes, seconds and milliseconds based on the 
+	/// Gregorian calendar.
+	///
+	/// In addition to the date and time, the class also 
+	/// maintains a time zone differential, which denotes
+	/// the difference in seconds from UTC to local time,
+	/// i.e. UTC = local time - time zone differential.
+	///
+	/// Although LocalDateTime supports relational and arithmetic
+	/// operators, all date/time comparisons and date/time arithmetics
+	/// should be done in UTC, using the DateTime or Timestamp
+	/// class for better performance. The relational operators
+	/// normalize the dates/times involved to UTC before carrying out
+	/// the comparison.
+	///
+	/// The time zone differential is based on the input date and
+	/// time and current time zone. A number of constructors accept
+	/// an explicit time zone differential parameter. These should
+	/// not be used since daylight savings time processing is impossible
+	/// since the time zone is unknown. Each of the constructors
+	/// accepting a tzd parameter have been marked as deprecated and
+	/// may be removed in a future revision.
+{
+public:
+	LocalDateTime();
+		/// Creates a LocalDateTime with the current date/time 
+		/// for the current time zone.
+
+	LocalDateTime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0);
+		/// Creates a LocalDateTime for the given Gregorian local date and time.
+		///   * year is from 0 to 9999.
+		///   * month is from 1 to 12.
+		///   * day is from 1 to 31.
+		///   * hour is from 0 to 23.
+		///   * minute is from 0 to 59.
+		///   * second is from 0 to 60 (allowing leap seconds).
+		///   * millisecond is from 0 to 999.
+		///   * microsecond is from 0 to 999.
+
+	//@ deprecated
+	LocalDateTime(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond);
+		/// Creates a LocalDateTime for the given Gregorian date and time in the
+		/// time zone denoted by the time zone differential in tzd.
+		///   * tzd is in seconds.
+		///   * year is from 0 to 9999.
+		///   * month is from 1 to 12.
+		///   * day is from 1 to 31.
+		///   * hour is from 0 to 23.
+		///   * minute is from 0 to 59.
+		///   * second is from 0 to 60 (allowing leap seconds).
+		///   * millisecond is from 0 to 999.
+		///   * microsecond is from 0 to 999.
+
+	LocalDateTime(const DateTime& dateTime);
+		/// Creates a LocalDateTime from the UTC time given in dateTime,
+		/// using the time zone differential of the current time zone.
+
+	//@ deprecated
+	LocalDateTime(int tzd, const DateTime& dateTime);
+		/// Creates a LocalDateTime from the UTC time given in dateTime,
+		/// using the given time zone differential. Adjusts dateTime
+		/// for the given time zone differential.
+
+	//@ deprecated
+	LocalDateTime(int tzd, const DateTime& dateTime, bool adjust);
+		/// Creates a LocalDateTime from the UTC time given in dateTime,
+		/// using the given time zone differential. If adjust is true, 
+		/// adjusts dateTime for the given time zone differential.
+
+	LocalDateTime(double julianDay);
+		/// Creates a LocalDateTime for the given Julian day in the local time zone.
+
+	//@ deprecated
+	LocalDateTime(int tzd, double julianDay);
+		/// Creates a LocalDateTime for the given Julian day in the time zone
+		/// denoted by the time zone differential in tzd.
+
+	LocalDateTime(const LocalDateTime& dateTime);
+		/// Copy constructor. Creates the LocalDateTime from another one.
+		
+	~LocalDateTime();
+		/// Destroys the LocalDateTime.
+		
+	LocalDateTime& operator = (const LocalDateTime& dateTime);
+		/// Assigns another LocalDateTime.
+	
+	LocalDateTime& operator = (const Timestamp& timestamp);
+		/// Assigns a timestamp
+
+	LocalDateTime& operator = (double julianDay);
+		/// Assigns a Julian day in the local time zone.
+	
+	LocalDateTime& assign(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microseconds = 0);
+		/// Assigns a Gregorian local date and time.
+		///   * year is from 0 to 9999.
+		///   * month is from 1 to 12.
+		///   * day is from 1 to 31.
+		///   * hour is from 0 to 23.
+		///   * minute is from 0 to 59.
+		///   * second is from 0 to 60 (allowing leap seconds).
+		///   * millisecond is from 0 to 999.
+		///   * microsecond is from 0 to 999.
+
+	//@ deprecated
+	LocalDateTime& assign(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds);
+		/// Assigns a Gregorian local date and time in the time zone denoted by
+		/// the time zone differential in tzd.
+		///   * tzd is in seconds.
+		///   * year is from 0 to 9999.
+		///   * month is from 1 to 12.
+		///   * day is from 1 to 31.
+		///   * hour is from 0 to 23.
+		///   * minute is from 0 to 59.
+		///   * second is from 0 to 60 (allowing leap seconds).
+		///   * millisecond is from 0 to 999.
+		///   * microsecond is from 0 to 999.
+
+	//@ deprecated
+	LocalDateTime& assign(int tzd, double julianDay);
+		/// Assigns a Julian day in the time zone denoted by the
+		/// time zone differential in tzd.
+
+	void swap(LocalDateTime& dateTime);
+		/// Swaps the LocalDateTime with another one.
+
+	int year() const;
+		/// Returns the year.
+		
+	int month() const;
+		/// Returns the month (1 to 12).
+	
+	int week(int firstDayOfWeek = DateTime::MONDAY) const;
+		/// Returns the week number within the year.
+		/// FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1).
+		/// The returned week number will be from 0 to 53. Week number 1 is the week 
+		/// containing January 4. This is in accordance to ISO 8601.
+		/// 
+		/// The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started
+		/// on a Saturday, week 1 will be the week starting on Monday, January 3.
+		/// January 1 and 2 will fall within week 0 (or the last week of the previous year).
+		///
+		/// For 2007, which starts on a Monday, week 1 will be the week startung on Monday, January 1.
+		/// There will be no week 0 in 2007.
+	
+	int day() const;
+		/// Returns the day witin the month (1 to 31).
+		
+	int dayOfWeek() const;
+		/// Returns the weekday (0 to 6, where
+		/// 0 = Sunday, 1 = Monday, ..., 6 = Saturday).
+	
+	int dayOfYear() const;
+		/// Returns the number of the day in the year.
+		/// January 1 is 1, February 1 is 32, etc.
+	
+	int hour() const;
+		/// Returns the hour (0 to 23).
+		
+	int hourAMPM() const;
+		/// Returns the hour (0 to 12).
+	
+	bool isAM() const;
+		/// Returns true if hour < 12;
+
+	bool isPM() const;
+		/// Returns true if hour >= 12.
+		
+	int minute() const;
+		/// Returns the minute (0 to 59).
+		
+	int second() const;
+		/// Returns the second (0 to 59).
+		
+	int millisecond() const;
+		/// Returns the millisecond (0 to 999)
+	
+	int microsecond() const;
+		/// Returns the microsecond (0 to 999)
+	
+	double julianDay() const;
+		/// Returns the julian day for the date.
+
+	int tzd() const;
+		/// Returns the time zone differential.
+		
+	DateTime utc() const;
+		/// Returns the UTC equivalent for the local date and time.
+
+	Timestamp timestamp() const;
+		/// Returns the date and time expressed as a Timestamp.
+
+	Timestamp::UtcTimeVal utcTime() const;
+		/// Returns the UTC equivalent for the local date and time.
+
+	bool operator == (const LocalDateTime& dateTime) const;	
+	bool operator != (const LocalDateTime& dateTime) const;	
+	bool operator <  (const LocalDateTime& dateTime) const;	
+	bool operator <= (const LocalDateTime& dateTime) const;	
+	bool operator >  (const LocalDateTime& dateTime) const;	
+	bool operator >= (const LocalDateTime& dateTime) const;	
+
+	LocalDateTime  operator +  (const Timespan& span) const;
+	LocalDateTime  operator -  (const Timespan& span) const;
+	Timespan       operator -  (const LocalDateTime& dateTime) const;
+	LocalDateTime& operator += (const Timespan& span);
+	LocalDateTime& operator -= (const Timespan& span);
+
+protected:
+	LocalDateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff, int tzd);
+		
+	void determineTzd(bool adjust = false);
+		/// Recalculate the tzd based on the _dateTime member based
+		/// on the current timezone using the Standard C runtime functions.
+		/// If adjust is true, then adjustForTzd() is called after the
+		/// differential is calculated.
+		
+	void adjustForTzd();
+		/// Adjust the _dateTime member based on the _tzd member.
+		
+	std::time_t dstOffset(int& dstOffset) const;
+		/// Determine the DST offset for the current date/time.
+	
+private:
+	DateTime _dateTime;
+	int      _tzd;
+	
+	friend class DateTimeFormatter;
+	friend class DateTimeParser;
+};
+
+
+//
+// inlines
+//
+inline int LocalDateTime::year() const
+{
+	return _dateTime.year();
+}
+
+
+inline int LocalDateTime::month() const
+{
+	return _dateTime.month();
+}
+
+
+inline int LocalDateTime::week(int firstDayOfWeek) const
+{
+	return _dateTime.week(firstDayOfWeek);
+}
+
+
+inline int LocalDateTime::day() const
+{
+	return _dateTime.day();
+}
+
+	
+inline int LocalDateTime::dayOfWeek() const
+{
+	return _dateTime.dayOfWeek();
+}
+
+
+inline int LocalDateTime::dayOfYear() const
+{
+	return _dateTime.dayOfYear();
+}
+
+
+inline int LocalDateTime::hour() const
+{
+	return _dateTime.hour();
+}
+
+	
+inline int LocalDateTime::hourAMPM() const
+{
+	return _dateTime.hourAMPM();
+}
+
+
+inline bool LocalDateTime::isAM() const
+{
+	return _dateTime.isAM();
+}
+
+
+inline bool LocalDateTime::isPM() const
+{
+	return _dateTime.isPM();
+}
+
+	
+inline int LocalDateTime::minute() const
+{
+	return _dateTime.minute();
+}
+
+	
+inline int LocalDateTime::second() const
+{
+	return _dateTime.second();
+}
+
+	
+inline int LocalDateTime::millisecond() const
+{
+	return _dateTime.millisecond();
+}
+
+
+inline int LocalDateTime::microsecond() const
+{
+	return _dateTime.microsecond();
+}
+
+
+inline double LocalDateTime::julianDay() const
+{
+	return _dateTime.julianDay();
+}
+
+
+inline int LocalDateTime::tzd() const
+{
+	return _tzd;
+}
+
+
+inline Timestamp LocalDateTime::timestamp() const
+{
+	return Timestamp::fromUtcTime(_dateTime.utcTime());
+}
+
+
+inline Timestamp::UtcTimeVal LocalDateTime::utcTime() const
+{
+	return _dateTime.utcTime() - ((Timestamp::TimeDiff) _tzd)*10000000;
+}
+
+
+inline void LocalDateTime::adjustForTzd()
+{
+	_dateTime += Timespan(((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS);
+}
+
+
+inline void swap(LocalDateTime& d1, LocalDateTime& d2)
+{
+	d1.swap(d2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LocalDateTime_INCLUDED
diff --git a/Poco/LogFile.h b/Poco/LogFile.h
new file mode 100644
index 0000000..37872b5
--- /dev/null
+++ b/Poco/LogFile.h
@@ -0,0 +1,93 @@
+//
+// LogFile.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LogFile
+//
+// Definition of the LogFile class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LogFile_INCLUDED
+#define Foundation_LogFile_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+#include "Poco/LogFile_WIN32U.h"
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/LogFile_WIN32.h"
+#else
+#include "Poco/LogFile_STD.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API LogFile: public LogFileImpl
+	/// This class is used by FileChannel to work
+	/// with a log file.
+{
+public:
+	LogFile(const std::string& path);
+		/// Creates the LogFile.
+
+	~LogFile();
+		/// Destroys the LogFile.
+
+	void write(const std::string& text, bool flush = true);
+		/// Writes the given text to the log file.
+		/// If flush is true, the text will be immediately
+		/// flushed to the file.
+
+	UInt64 size() const;
+		/// Returns the current size in bytes of the log file.
+
+	Timestamp creationDate() const;
+		/// Returns the date and time the log file was created.
+
+	const std::string& path() const;
+		/// Returns the path given in the constructor.
+};
+
+
+//
+// inlines
+//
+inline void LogFile::write(const std::string& text, bool flush)
+{
+	writeImpl(text, flush);
+}
+
+
+inline UInt64 LogFile::size() const
+{
+	return sizeImpl();
+}
+
+
+inline Timestamp LogFile::creationDate() const
+{
+	return creationDateImpl();
+}
+
+
+inline const std::string& LogFile::path() const
+{
+	return pathImpl();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LogFile_INCLUDED
diff --git a/Poco/LogFile_STD.h b/Poco/LogFile_STD.h
new file mode 100644
index 0000000..0e8feda
--- /dev/null
+++ b/Poco/LogFile_STD.h
@@ -0,0 +1,52 @@
+//
+// LogFile_STD.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LogFile
+//
+// Definition of the LogFileImpl class using iostreams.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LogFile_STD_INCLUDED
+#define Foundation_LogFile_STD_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include "Poco/FileStream.h"
+
+
+namespace Poco {
+
+
+class Foundation_API LogFileImpl
+	/// The implementation of LogFile for non-Windows platforms.
+	/// The native filesystem APIs are used for
+	/// total control over locking behavior.
+{
+public:
+	LogFileImpl(const std::string& path);
+	~LogFileImpl();
+	void writeImpl(const std::string& text, bool flush);
+	UInt64 sizeImpl() const;
+	Timestamp creationDateImpl() const;
+	const std::string& pathImpl() const;
+
+private:
+	std::string _path;
+	mutable Poco::FileOutputStream _str;
+	Timestamp _creationDate;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LogFile_STD_INCLUDED
diff --git a/Poco/LogFile_WIN32.h b/Poco/LogFile_WIN32.h
new file mode 100644
index 0000000..ce2ff6c
--- /dev/null
+++ b/Poco/LogFile_WIN32.h
@@ -0,0 +1,54 @@
+//
+// LogFile_WIN32.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LogFile
+//
+// Definition of the LogFileImpl class using the Windows file APIs.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LogFile_WIN32_INCLUDED
+#define Foundation_LogFile_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API LogFileImpl
+	/// The implementation of LogFile for Windows.
+	/// The native filesystem APIs are used for
+	/// total control over locking behavior.
+{
+public:
+	LogFileImpl(const std::string& path);
+	~LogFileImpl();
+	void writeImpl(const std::string& text, bool flush);
+	UInt64 sizeImpl() const;
+	Timestamp creationDateImpl() const;
+	const std::string& pathImpl() const;
+
+private:
+	void createFile();
+
+	std::string _path;
+	HANDLE      _hFile;
+	Timestamp   _creationDate;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LogFile_WIN32_INCLUDED
diff --git a/Poco/LogFile_WIN32U.h b/Poco/LogFile_WIN32U.h
new file mode 100644
index 0000000..ed558a7
--- /dev/null
+++ b/Poco/LogFile_WIN32U.h
@@ -0,0 +1,54 @@
+//
+// LogFile_WIN32U.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LogFile
+//
+// Definition of the LogFileImpl class using the Windows file APIs.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LogFile_WIN32U_INCLUDED
+#define Foundation_LogFile_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API LogFileImpl
+	/// The implementation of LogFile for Windows.
+	/// The native filesystem APIs are used for
+	/// total control over locking behavior.
+{
+public:
+	LogFileImpl(const std::string& path);
+	~LogFileImpl();
+	void writeImpl(const std::string& text, bool flush);
+	UInt64 sizeImpl() const;
+	Timestamp creationDateImpl() const;
+	const std::string& pathImpl() const;
+
+private:
+	void createFile();
+
+	std::string _path;
+	HANDLE      _hFile;
+	Timestamp   _creationDate;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LogFile_WIN32U_INCLUDED
diff --git a/Poco/LogStream.h b/Poco/LogStream.h
new file mode 100644
index 0000000..3da5582
--- /dev/null
+++ b/Poco/LogStream.h
@@ -0,0 +1,185 @@
+//
+// LogStream.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LogStream
+//
+// Definition of the LogStream class.
+//
+// Copyright (c) 2006-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LogStream_INCLUDED
+#define Foundation_LogStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Logger.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class Foundation_API LogStreamBuf: public UnbufferedStreamBuf
+	/// This class implements a streambuf interface
+	/// to a Logger.
+	///
+	/// The streambuf appends all characters written to it
+	/// to a string. As soon as a CR or LF (std::endl) is written,
+	/// the string is sent to the Logger, with the set
+	/// priority.
+{
+public:
+	LogStreamBuf(Logger& logger, Message::Priority priority);
+		/// Creates the LogStream.
+
+	~LogStreamBuf();
+		/// Destroys the LogStream.
+		
+	void setPriority(Message::Priority priority);
+		/// Sets the priority for log messages.
+		
+	Message::Priority getPriority() const;
+		/// Returns the priority for log messages.
+
+	Logger& logger() const;
+		/// Returns a reference to the Logger.
+
+private:
+	int writeToDevice(char c);
+
+private:
+	Logger&           _logger;
+	Message::Priority _priority;
+	std::string       _message;
+};
+
+
+class Foundation_API LogIOS: public virtual std::ios
+	/// The base class for LogStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	LogIOS(Logger& logger, Message::Priority priority);
+	~LogIOS();
+	LogStreamBuf* rdbuf();
+
+protected:
+	LogStreamBuf _buf;
+};
+
+
+class Foundation_API LogStream: public LogIOS, public std::ostream
+	/// This class implements an ostream interface
+	/// to a Logger.
+	///
+	/// The stream's buffer appends all characters written to it
+	/// to a string. As soon as a CR or LF (std::endl) is written,
+	/// the string is sent to the Logger, with the current
+	/// priority.
+	///
+	/// Usage example:
+	///     LogStream ls(someLogger);
+	///     ls << "Some informational message" << std::endl;
+	///     ls.error() << "Some error message" << std::endl;
+{
+public:
+	LogStream(Logger& logger, Message::Priority priority = Message::PRIO_INFORMATION);
+		/// Creates the LogStream, using the given logger and priority.
+
+	LogStream(const std::string& loggerName, Message::Priority priority = Message::PRIO_INFORMATION);
+		/// Creates the LogStream, using the logger identified
+		/// by loggerName, and sets the priority.
+		
+	~LogStream();
+		/// Destroys the LogStream.
+		
+	LogStream& fatal();
+		/// Sets the priority for log messages to Message::PRIO_FATAL.
+		
+	LogStream& fatal(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_FATAL
+		/// and writes the given message.
+		
+	LogStream& critical();
+		/// Sets the priority for log messages to Message::PRIO_CRITICAL.
+
+	LogStream& critical(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_CRITICAL
+		/// and writes the given message.
+
+	LogStream& error();
+		/// Sets the priority for log messages to Message::PRIO_ERROR.
+
+	LogStream& error(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_ERROR
+		/// and writes the given message.
+
+	LogStream& warning();
+		/// Sets the priority for log messages to Message::PRIO_WARNING.
+
+	LogStream& warning(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_WARNING
+		/// and writes the given message.
+
+	LogStream& notice();
+		/// Sets the priority for log messages to Message::PRIO_NOTICE.
+
+	LogStream& notice(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_NOTICE
+		/// and writes the given message.
+
+	LogStream& information();
+		/// Sets the priority for log messages to Message::PRIO_INFORMATION.
+
+	LogStream& information(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_INFORMATION
+		/// and writes the given message.
+
+	LogStream& debug();
+		/// Sets the priority for log messages to Message::PRIO_DEBUG.
+
+	LogStream& debug(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_DEBUG
+		/// and writes the given message.
+
+	LogStream& trace();
+		/// Sets the priority for log messages to Message::PRIO_TRACE.
+
+	LogStream& trace(const std::string& message);
+		/// Sets the priority for log messages to Message::PRIO_TRACE
+		/// and writes the given message.
+
+	LogStream& priority(Message::Priority priority);
+		/// Sets the priority for log messages.
+};
+
+
+//
+// inlines
+//
+inline Message::Priority LogStreamBuf::getPriority() const
+{
+	return _priority;
+}
+
+
+inline Logger& LogStreamBuf::logger() const
+{
+	return _logger;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LogStream_INCLUDED
diff --git a/Poco/Logger.h b/Poco/Logger.h
new file mode 100644
index 0000000..956b1d8
--- /dev/null
+++ b/Poco/Logger.h
@@ -0,0 +1,1318 @@
+//
+// Logger.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  Logger
+//
+// Definition of the Logger class.
+//
+// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Logger_INCLUDED
+#define Foundation_Logger_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Message.h"
+#include "Poco/Format.h"
+#include <map>
+#include <vector>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class Exception;
+
+
+class Foundation_API Logger: public Channel
+	/// Logger is a special Channel that acts as the main
+	/// entry point into the logging framework.
+	///
+	/// An application uses instances of the Logger class to generate its log messages
+	/// and send them on their way to their final destination. Logger instances
+	/// are organized in a hierarchical, tree-like manner and are maintained by
+	/// the framework. Every Logger object has exactly one direct ancestor, with
+	/// the exception of the root logger. A newly created logger inherits its properties -
+	/// channel and level - from its direct ancestor. Every logger is connected
+	/// to a channel, to which it passes on its messages. Furthermore, every logger
+	/// has a log level, which is used for filtering messages based on their priority.
+	/// Only messages with a priority equal to or higher than the specified level
+	/// are passed on. For example, if the level of a logger is set to three (PRIO_ERROR),
+	/// only messages with priority PRIO_ERROR, PRIO_CRITICAL and PRIO_FATAL will
+	/// propagate. If the level is set to zero, the logger is effectively disabled.
+	///
+	/// The name of a logger determines the logger's place within the logger hierarchy.
+	/// The name of the root logger is always "", the empty string. For all other
+	/// loggers, the name is made up of one or more components, separated by a period.
+	/// For example, the loggers with the name HTTPServer.RequestHandler and HTTPServer.Listener
+	/// are descendants of the logger HTTPServer, which itself is a descendant of
+	/// the root logger. There is not limit as to how deep
+	/// the logger hierarchy can become. Once a logger has been created and it has
+	/// inherited the channel and level from its ancestor, it loses the connection
+	/// to it. So changes to the level or channel of a logger do not affect its
+	/// descendants. This greatly simplifies the implementation of the framework
+	/// and is no real restriction, because almost always levels and channels are
+	/// set up at application startup and never changed afterwards. Nevertheless,
+	/// there are methods to simultaneously change the level and channel of all
+	/// loggers in a certain hierarchy.
+	///
+	/// There are also convenience macros available that wrap the actual
+	/// logging statement into a check whether the Logger's log level
+	/// is sufficient to actually log the message. This allows to increase
+	/// the application performance if many complex log statements
+	/// are used. The macros also add the source file path and line
+	/// number into the log message so that it is available to formatters.
+	/// Variants of these macros that allow message formatting with Poco::format()
+	/// are also available. Up to four arguments are supported.
+	///
+	/// Examples:
+	///     poco_warning(logger, "This is a warning");
+	///     poco_information_f2(logger, "An informational message with args: %d, %d", 1, 2);
+{
+public:
+	const std::string& name() const;
+		/// Returns the name of the logger, which is set as the
+		/// message source on all messages created by the logger.
+
+	void setChannel(Channel* pChannel);
+		/// Attaches the given Channel to the Logger.
+		
+	Channel* getChannel() const;
+		/// Returns the Channel attached to the logger.
+		
+	void setLevel(int level);
+		/// Sets the Logger's log level.
+		///
+		/// See Message::Priority for valid log levels.
+		/// Setting the log level to zero turns off
+		/// logging for that Logger.
+		
+	int getLevel() const;
+		/// Returns the Logger's log level.
+		
+	void setLevel(const std::string& level);
+		/// Sets the Logger's log level using a symbolic value.
+		///
+		/// Valid values are:
+		///   - none (turns off logging)
+		///   - fatal
+		///   - critical
+		///   - error
+		///   - warning
+		///   - notice
+		///   - information
+		///   - debug
+		///   - trace
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets or changes a configuration property.
+		///
+		/// Only the "channel" and "level" properties are supported, which allow
+		/// setting the target channel and log level, respectively, via the LoggingRegistry.
+		/// The "channel" and "level" properties are set-only.
+
+	void log(const Message& msg);
+		/// Logs the given message if its priority is
+		/// greater than or equal to the Logger's log level.
+		
+	void log(const Exception& exc);
+		/// Logs the given exception with priority PRIO_ERROR.	
+
+	void log(const Exception& exc, const char* file, int line);
+		/// Logs the given exception with priority PRIO_ERROR.	
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+		
+	void fatal(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_FATAL,
+		/// creates a Message with priority PRIO_FATAL
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void fatal(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_FATAL,
+		/// creates a Message with priority PRIO_FATAL
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void fatal(const std::string& fmt, const Any& value1);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void critical(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_CRITICAL,
+		/// creates a Message with priority PRIO_CRITICAL
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void critical(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_CRITICAL,
+		/// creates a Message with priority PRIO_CRITICAL
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void critical(const std::string& fmt, const Any& value1);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void error(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_ERROR,
+		/// creates a Message with priority PRIO_ERROR
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void error(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_ERROR,
+		/// creates a Message with priority PRIO_ERROR
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void error(const std::string& fmt, const Any& value1);
+	void error(const std::string& fmt, const Any& value1, const Any& value2);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void warning(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_WARNING,
+		/// creates a Message with priority PRIO_WARNING
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void warning(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_WARNING,
+		/// creates a Message with priority PRIO_WARNING
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void warning(const std::string& fmt, const Any& value1);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void notice(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_NOTICE,
+		/// creates a Message with priority PRIO_NOTICE
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void notice(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_NOTICE,
+		/// creates a Message with priority PRIO_NOTICE
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void notice(const std::string& fmt, const Any& value1);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void information(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_INFORMATION,
+		/// creates a Message with priority PRIO_INFORMATION
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void information(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_INFORMATION,
+		/// creates a Message with priority PRIO_INFORMATION
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void information(const std::string& fmt, const Any& value1);
+	void information(const std::string& fmt, const Any& value1, const Any& value2);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void debug(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_DEBUG,
+		/// creates a Message with priority PRIO_DEBUG
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void debug(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_DEBUG,
+		/// creates a Message with priority PRIO_DEBUG
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void debug(const std::string& fmt, const Any& value1);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void trace(const std::string& msg);
+		/// If the Logger's log level is at least PRIO_TRACE,
+		/// creates a Message with priority PRIO_TRACE
+		/// and the given message text and sends it
+		/// to the attached channel.
+
+	void trace(const std::string& msg, const char* file, int line);
+		/// If the Logger's log level is at least PRIO_TRACE,
+		/// creates a Message with priority PRIO_TRACE
+		/// and the given message text and sends it
+		/// to the attached channel.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+
+	void trace(const std::string& fmt, const Any& value1);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9);
+	void trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10);
+
+	void dump(const std::string& msg, const void* buffer, std::size_t length, Message::Priority prio = Message::PRIO_DEBUG);
+		/// Logs the given message, followed by the data in buffer.
+		///
+		/// The data in buffer is written in canonical hex+ASCII form:
+		/// Offset (4 bytes) in hexadecimal, followed by sixteen 
+		/// space-separated, two column, hexadecimal bytes,
+		/// followed by the same sixteen bytes as ASCII characters.
+		/// For bytes outside the range 32 .. 127, a dot is printed.
+
+	bool is(int level) const;
+		/// Returns true if at least the given log level is set.
+		
+	bool fatal() const;
+		/// Returns true if the log level is at least PRIO_FATAL.
+		
+	bool critical() const;
+		/// Returns true if the log level is at least PRIO_CRITICAL.
+
+	bool error() const;
+		/// Returns true if the log level is at least PRIO_ERROR.
+
+	bool warning() const;
+		/// Returns true if the log level is at least PRIO_WARNING.
+
+	bool notice() const;
+		/// Returns true if the log level is at least PRIO_NOTICE.
+
+	bool information() const;
+		/// Returns true if the log level is at least PRIO_INFORMATION.
+
+	bool debug() const;
+		/// Returns true if the log level is at least PRIO_DEBUG.
+
+	bool trace() const;
+		/// Returns true if the log level is at least PRIO_TRACE.
+
+	static std::string format(const std::string& fmt, const std::string& arg);
+		/// Replaces all occurences of $0 in fmt with the string given in arg and
+		/// returns the result. To include a dollar sign in the result string,
+		/// specify two dollar signs ($$) in the format string.
+		
+	static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1);
+		/// Replaces all occurences of $<n> in fmt with the string given in arg<n> and
+		/// returns the result. To include a dollar sign in the result string,
+		/// specify two dollar signs ($$) in the format string.
+
+	static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2);	
+		/// Replaces all occurences of $<n> in fmt with the string given in arg<n> and
+		/// returns the result. To include a dollar sign in the result string,
+		/// specify two dollar signs ($$) in the format string.
+
+	static std::string format(const std::string& fmt, const std::string& arg0, const std::string& arg1, const std::string& arg2, const std::string& arg3);	
+		/// Replaces all occurences of $<n> in fmt with the string given in arg<n> and
+		/// returns the result. To include a dollar sign in the result string,
+		/// specify two dollar signs ($$) in the format string.
+
+	static void formatDump(std::string& message, const void* buffer, std::size_t length);
+		/// Creates a hex-dump of the given buffer and appends it to the
+		/// given message string.
+		
+	static void setLevel(const std::string& name, int level);
+		/// Sets the given log level on all loggers that are
+		/// descendants of the Logger with the given name.
+		
+	static void setChannel(const std::string& name, Channel* pChannel);
+		/// Attaches the given Channel to all loggers that are
+		/// descendants of the Logger with the given name.
+
+	static void setProperty(const std::string& loggerName, const std::string& propertyName, const std::string& value);
+		/// Sets or changes a configuration property for all loggers
+		/// that are descendants of the Logger with the given name.
+
+	static Logger& get(const std::string& name);
+		/// Returns a reference to the Logger with the given name.
+		/// If the Logger does not yet exist, it is created, based
+		/// on its parent logger.
+
+	static Logger& unsafeGet(const std::string& name);
+		/// Returns a reference to the Logger with the given name.
+		/// If the Logger does not yet exist, it is created, based
+		/// on its parent logger.
+		///
+		/// WARNING: This method is not thread safe. You should
+		/// probably use get() instead.
+		/// The only time this method should be used is during
+		/// program initialization, when only one thread is running.
+		
+	static Logger& create(const std::string& name, Channel* pChannel, int level = Message::PRIO_INFORMATION);
+		/// Creates and returns a reference to a Logger with the
+		/// given name. The Logger's Channel and log level as set as
+		/// specified.
+		
+	static Logger& root();
+		/// Returns a reference to the root logger, which is the ultimate
+		/// ancestor of all Loggers.
+		
+	static Logger* has(const std::string& name);
+		/// Returns a pointer to the Logger with the given name if it
+		/// exists, or a null pointer otherwse.
+		
+	static void destroy(const std::string& name);
+		/// Destroys the logger with the specified name. Does nothing
+		/// if the logger is not found.
+		///
+		/// After a logger has been destroyed, all references to it
+		/// become invalid.	
+		
+	static void shutdown();
+		/// Shuts down the logging framework and releases all
+		/// Loggers.
+		
+	static void names(std::vector<std::string>& names);
+		/// Fills the given vector with the names
+		/// of all currently defined loggers.
+		
+	static int parseLevel(const std::string& level);
+		/// Parses a symbolic log level from a string and
+		/// returns the resulting numeric level.
+		///
+		/// Valid symbolic levels are:
+		///   - none (turns off logging)
+		///   - fatal
+		///   - critical
+		///   - error
+		///   - warning
+		///   - notice
+		///   - information
+		///   - debug
+		///   - trace
+		///
+		/// The level is not case sensitive.
+		
+	static const std::string ROOT; /// The name of the root logger ("").	
+		
+protected:
+	typedef std::map<std::string, Logger*> LoggerMap;
+
+	Logger(const std::string& name, Channel* pChannel, int level);
+	~Logger();
+	
+	void log(const std::string& text, Message::Priority prio);
+	void log(const std::string& text, Message::Priority prio, const char* file, int line);
+
+	static std::string format(const std::string& fmt, int argc, std::string argv[]);
+	static Logger& parent(const std::string& name);
+	static void add(Logger* pLogger);
+	static Logger* find(const std::string& name);
+
+private:
+	Logger();
+	Logger(const Logger&);
+	Logger& operator = (const Logger&);
+	
+	std::string _name;
+	Channel*    _pChannel;
+	int         _level;
+
+	static LoggerMap* _pLoggerMap;
+	static Mutex      _mapMtx;
+};
+
+
+//
+// convenience macros
+//
+#define poco_fatal(logger, msg) \
+	if ((logger).fatal()) (logger).fatal(msg, __FILE__, __LINE__); else (void) 0
+
+#define poco_fatal_f1(logger, fmt, arg1) \
+	if ((logger).fatal()) (logger).fatal(Poco::format((fmt), arg1), __FILE__, __LINE__); else (void) 0
+
+#define poco_fatal_f2(logger, fmt, arg1, arg2) \
+	if ((logger).fatal()) (logger).fatal(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+#define poco_fatal_f3(logger, fmt, arg1, arg2, arg3) \
+	if ((logger).fatal()) (logger).fatal(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+#define poco_fatal_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+	if ((logger).fatal()) (logger).fatal(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+
+#define poco_critical(logger, msg) \
+	if ((logger).critical()) (logger).critical(msg, __FILE__, __LINE__); else (void) 0
+
+#define poco_critical_f1(logger, fmt, arg1) \
+	if ((logger).critical()) (logger).critical(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+#define poco_critical_f2(logger, fmt, arg1, arg2) \
+	if ((logger).critical()) (logger).critical(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+#define poco_critical_f3(logger, fmt, arg1, arg2, arg3) \
+	if ((logger).critical()) (logger).critical(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+#define poco_critical_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+	if ((logger).critical()) (logger).critical(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+
+#define poco_error(logger, msg) \
+	if ((logger).error()) (logger).error(msg, __FILE__, __LINE__); else (void) 0
+
+#define poco_error_f1(logger, fmt, arg1) \
+	if ((logger).error()) (logger).error(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+#define poco_error_f2(logger, fmt, arg1, arg2) \
+	if ((logger).error()) (logger).error(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+#define poco_error_f3(logger, fmt, arg1, arg2, arg3) \
+	if ((logger).error()) (logger).error(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+#define poco_error_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+	if ((logger).error()) (logger).error(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+
+#define poco_warning(logger, msg) \
+	if ((logger).warning()) (logger).warning(msg, __FILE__, __LINE__); else (void) 0
+
+#define poco_warning_f1(logger, fmt, arg1) \
+	if ((logger).warning()) (logger).warning(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+#define poco_warning_f2(logger, fmt, arg1, arg2) \
+	if ((logger).warning()) (logger).warning(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+#define poco_warning_f3(logger, fmt, arg1, arg2, arg3) \
+	if ((logger).warning()) (logger).warning(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+#define poco_warning_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+	if ((logger).warning()) (logger).warning(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+	
+#define poco_notice(logger, msg) \
+	if ((logger).notice()) (logger).notice(msg, __FILE__, __LINE__); else (void) 0
+
+#define poco_notice_f1(logger, fmt, arg1) \
+	if ((logger).notice()) (logger).notice(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+#define poco_notice_f2(logger, fmt, arg1, arg2) \
+	if ((logger).notice()) (logger).notice(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+#define poco_notice_f3(logger, fmt, arg1, arg2, arg3) \
+	if ((logger).notice()) (logger).notice(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+#define poco_notice_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+	if ((logger).notice()) (logger).notice(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+
+#define poco_information(logger, msg) \
+	if ((logger).information()) (logger).information(msg, __FILE__, __LINE__); else (void) 0
+
+#define poco_information_f1(logger, fmt, arg1) \
+	if ((logger).information()) (logger).information(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+#define poco_information_f2(logger, fmt, arg1, arg2) \
+	if ((logger).information()) (logger).information(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+#define poco_information_f3(logger, fmt, arg1, arg2, arg3) \
+	if ((logger).information()) (logger).information(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+#define poco_information_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+	if ((logger).information()) (logger).information(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+
+#if defined(_DEBUG) || defined(POCO_LOG_DEBUG)
+	#define poco_debug(logger, msg) \
+		if ((logger).debug()) (logger).debug(msg, __FILE__, __LINE__); else (void) 0
+
+	#define poco_debug_f1(logger, fmt, arg1) \
+		if ((logger).debug()) (logger).debug(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_debug_f2(logger, fmt, arg1, arg2) \
+		if ((logger).debug()) (logger).debug(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_debug_f3(logger, fmt, arg1, arg2, arg3) \
+		if ((logger).debug()) (logger).debug(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_debug_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+		if ((logger).debug()) (logger).debug(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_trace(logger, msg) \
+		if ((logger).trace()) (logger).trace(msg, __FILE__, __LINE__); else (void) 0
+
+	#define poco_trace_f1(logger, fmt, arg1) \
+		if ((logger).trace()) (logger).trace(Poco::format((fmt), (arg1)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_trace_f2(logger, fmt, arg1, arg2) \
+		if ((logger).trace()) (logger).trace(Poco::format((fmt), (arg1), (arg2)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_trace_f3(logger, fmt, arg1, arg2, arg3) \
+		if ((logger).trace()) (logger).trace(Poco::format((fmt), (arg1), (arg2), (arg3)), __FILE__, __LINE__); else (void) 0
+
+	#define poco_trace_f4(logger, fmt, arg1, arg2, arg3, arg4) \
+		if ((logger).trace()) (logger).trace(Poco::format((fmt), (arg1), (arg2), (arg3), (arg4)), __FILE__, __LINE__); else (void) 0
+#else
+	#define poco_debug(logger, msg)
+	#define poco_debug_f1(logger, fmt, arg1)
+	#define poco_debug_f2(logger, fmt, arg1, arg2)
+	#define poco_debug_f3(logger, fmt, arg1, arg2, arg3)
+	#define poco_debug_f4(logger, fmt, arg1, arg2, arg3, arg4)
+	#define poco_trace(logger, msg)
+	#define poco_trace_f1(logger, fmt, arg1)
+	#define poco_trace_f2(logger, fmt, arg1, arg2)
+	#define poco_trace_f3(logger, fmt, arg1, arg2, arg3)
+	#define poco_trace_f4(logger, fmt, arg1, arg2, arg3, arg4)
+#endif
+
+
+//
+// inlines
+//
+inline const std::string& Logger::name() const
+{
+	return _name;
+}
+
+
+inline int Logger::getLevel() const
+{
+	return _level;
+}
+
+
+inline void Logger::log(const std::string& text, Message::Priority prio)
+{
+	if (_level >= prio && _pChannel)
+	{
+		_pChannel->log(Message(_name, text, prio));
+	}
+}
+
+
+inline void Logger::log(const std::string& text, Message::Priority prio, const char* file, int line)
+{
+	if (_level >= prio && _pChannel)
+	{
+		_pChannel->log(Message(_name, text, prio, file, line));
+	}
+}
+
+
+inline void Logger::fatal(const std::string& msg)
+{
+	log(msg, Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_FATAL, file, line);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::fatal(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_FATAL);
+}
+
+
+inline void Logger::critical(const std::string& msg)
+{
+	log(msg, Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_CRITICAL, file, line);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::critical(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_CRITICAL);
+}
+
+
+inline void Logger::error(const std::string& msg)
+{
+	log(msg, Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_ERROR, file, line);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::error(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_ERROR);
+}
+
+
+inline void Logger::warning(const std::string& msg)
+{
+	log(msg, Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_WARNING, file, line);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::warning(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_WARNING);
+}
+
+
+inline void Logger::notice(const std::string& msg)
+{
+	log(msg, Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_NOTICE, file, line);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::notice(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_NOTICE);
+}
+
+
+inline void Logger::information(const std::string& msg)
+{
+	log(msg, Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_INFORMATION, file, line);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::information(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_INFORMATION);
+}
+
+
+inline void Logger::debug(const std::string& msg)
+{
+	log(msg, Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_DEBUG, file, line);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::debug(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_DEBUG);
+}
+
+
+inline void Logger::trace(const std::string& msg)
+{
+	log(msg, Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& msg, const char* file, int line)
+{
+	log(msg, Message::PRIO_TRACE, file, line);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1)
+{
+	log(Poco::format(fmt, value1), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2)
+{
+	log(Poco::format(fmt, value1, value2), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
+{
+	log(Poco::format(fmt, value1, value2, value3), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9), Message::PRIO_TRACE);
+}
+
+
+inline void Logger::trace(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6, const Any& value7, const Any& value8, const Any& value9, const Any& value10)
+{
+	log(Poco::format(fmt, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10), Message::PRIO_TRACE);
+}
+
+
+inline bool Logger::is(int level) const
+{
+	return _level >= level;
+}
+
+
+inline bool Logger::fatal() const
+{
+	return _level >= Message::PRIO_FATAL;
+}
+
+
+inline bool Logger::critical() const
+{
+	return _level >= Message::PRIO_CRITICAL;
+}
+
+
+inline bool Logger::error() const
+{
+	return _level >= Message::PRIO_ERROR;
+}
+
+
+inline bool Logger::warning() const
+{
+	return _level >= Message::PRIO_WARNING;
+}
+
+
+inline bool Logger::notice() const
+{
+	return _level >= Message::PRIO_NOTICE;
+}
+
+
+inline bool Logger::information() const
+{
+	return _level >= Message::PRIO_INFORMATION;
+}
+
+
+inline bool Logger::debug() const
+{
+	return _level >= Message::PRIO_DEBUG;
+}
+
+
+inline bool Logger::trace() const
+{
+	return _level >= Message::PRIO_TRACE;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Logger_INCLUDED
diff --git a/Poco/LoggingFactory.h b/Poco/LoggingFactory.h
new file mode 100644
index 0000000..c851c3f
--- /dev/null
+++ b/Poco/LoggingFactory.h
@@ -0,0 +1,92 @@
+//
+// LoggingFactory.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LoggingFactory
+//
+// Definition of the LoggingFactory class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LoggingFactory_INCLUDED
+#define Foundation_LoggingFactory_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DynamicFactory.h"
+#include "Poco/Channel.h"
+#include "Poco/Formatter.h"
+
+
+namespace Poco {
+
+
+class Foundation_API LoggingFactory
+	/// An extensible factory for channels and formatters.
+	///
+	/// The following channel classes are pre-registered:
+	///   - AsyncChannel
+	///   - ConsoleChannel
+	///   - EventLogChannel (Windows platforms only)
+	///   - FileChannel
+	///   - FormattingChannel
+	///   - NullChannel
+	///   - SplitterChannel
+	///   - SyslogChannel (Unix platforms only)
+	///
+	/// The following formatter classes are pre-registered:
+	///   - PatternFormatter
+{
+public:
+	typedef AbstractInstantiator<Channel>   ChannelInstantiator;
+	typedef AbstractInstantiator<Formatter> FormatterFactory;
+
+	LoggingFactory();
+		/// Creates the LoggingFactory.
+		///
+		/// Automatically registers class factories for the
+		/// built-in channel and formatter classes.
+
+	~LoggingFactory();
+		/// Destroys the LoggingFactory.
+
+	void registerChannelClass(const std::string& className, ChannelInstantiator* pFactory);
+		/// Registers a channel class with the LoggingFactory.
+
+	void registerFormatterClass(const std::string& className, FormatterFactory* pFactory);
+		/// Registers a formatter class with the LoggingFactory.
+
+	Channel* createChannel(const std::string& className) const;
+		/// Creates a new Channel instance from specified class.
+		///
+		/// Throws a NotFoundException if the specified channel class
+		/// has not been registered.
+
+	Formatter* createFormatter(const std::string& className) const;
+		/// Creates a new Formatter instance from specified class.
+		///
+		/// Throws a NotFoundException if the specified formatter class
+		/// has not been registered.
+
+	static LoggingFactory& defaultFactory();
+		/// Returns a reference to the default
+		/// LoggingFactory.
+
+private:
+	void registerBuiltins();
+
+	DynamicFactory<Channel>   _channelFactory;
+	DynamicFactory<Formatter> _formatterFactory;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LoggingFactory_INCLUDED
diff --git a/Poco/LoggingRegistry.h b/Poco/LoggingRegistry.h
new file mode 100644
index 0000000..82bb2c8
--- /dev/null
+++ b/Poco/LoggingRegistry.h
@@ -0,0 +1,99 @@
+//
+// LoggingRegistry.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  LoggingRegistry
+//
+// Definition of the LoggingRegistry class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_LoggingRegistry_INCLUDED
+#define Foundation_LoggingRegistry_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Channel.h"
+#include "Poco/Formatter.h"
+#include "Poco/Mutex.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Foundation_API LoggingRegistry
+	/// A registry for channels and formatters.
+	///
+	/// The LoggingRegistry class is used for configuring
+	/// the logging framework.
+{
+public:
+	LoggingRegistry();
+		/// Creates the LoggingRegistry.
+
+	~LoggingRegistry();
+		/// Destroys the LoggingRegistry.
+
+	Channel* channelForName(const std::string& name) const;
+		/// Returns the Channel object which has been registered
+		/// under the given name.
+		///
+		/// Throws a NotFoundException if the name is unknown.
+
+	Formatter* formatterForName(const std::string& name) const;
+		/// Returns the Formatter object which has been registered
+		/// under the given name.
+		///
+		/// Throws a NotFoundException if the name is unknown.
+
+	void registerChannel(const std::string& name, Channel* pChannel);
+		/// Registers a channel under a given name.
+		/// It is okay to re-register a different channel under an
+		/// already existing name.
+		
+	void registerFormatter(const std::string& name, Formatter* pFormatter);
+		/// Registers a formatter under a given name.
+		/// It is okay to re-register a different formatter under an
+		/// already existing name.
+
+	void unregisterChannel(const std::string& name);
+		/// Unregisters the given channel.
+		///
+		/// Throws a NotFoundException if the name is unknown.
+
+	void unregisterFormatter(const std::string& name);
+		/// Unregisters the given formatter.
+		///
+		/// Throws a NotFoundException if the name is unknown.
+
+	void clear();
+		/// Unregisters all registered channels and formatters.
+
+	static LoggingRegistry& defaultRegistry();
+		/// Returns a reference to the default
+		/// LoggingRegistry.
+
+private:
+	typedef AutoPtr<Channel>   ChannelPtr;
+	typedef AutoPtr<Formatter> FormatterPtr;
+	typedef std::map<std::string, ChannelPtr> ChannelMap;
+	typedef std::map<std::string, FormatterPtr> FormatterMap;
+	
+	ChannelMap   _channelMap;
+	FormatterMap _formatterMap;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_LoggingRegistry_INCLUDED
diff --git a/Poco/MD4Engine.h b/Poco/MD4Engine.h
new file mode 100644
index 0000000..644575e
--- /dev/null
+++ b/Poco/MD4Engine.h
@@ -0,0 +1,95 @@
+//
+// MD4Engine.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  MD4Engine
+//
+// Definition of class MD4Engine.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+//
+// MD4 (RFC 1320) algorithm:
+// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD4 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+//
+
+
+#ifndef Foundation_MD4Engine_INCLUDED
+#define Foundation_MD4Engine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DigestEngine.h"
+
+
+namespace Poco {
+
+
+class Foundation_API MD4Engine: public DigestEngine
+	/// This class implementes the MD4 message digest algorithm,
+	/// described in RFC 1320.
+{
+public:
+	enum
+	{
+		BLOCK_SIZE  = 64,
+		DIGEST_SIZE = 16
+	};
+
+	MD4Engine();
+	~MD4Engine();
+		
+	std::size_t digestLength() const;
+	void reset();
+	const DigestEngine::Digest& digest();
+
+protected:
+	void updateImpl(const void* data, std::size_t length);
+
+private:
+	static void transform(UInt32 state[4], const unsigned char block[64]);
+	static void encode(unsigned char* output, const UInt32* input, std::size_t len);
+	static void decode(UInt32* output, const unsigned char* input, std::size_t len);
+
+	struct Context
+	{
+		UInt32 state[4];          // state (ABCD)
+		UInt32 count[2];          // number of bits, modulo 2^64 (lsb first)
+		unsigned char buffer[64]; // input buffer
+	};
+
+	Context _context;
+	DigestEngine::Digest _digest;
+
+	MD4Engine(const MD4Engine&);
+	MD4Engine& operator = (const MD4Engine&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_MD5Engine_INCLUDED
diff --git a/Poco/MD5Engine.h b/Poco/MD5Engine.h
new file mode 100644
index 0000000..7835ff6
--- /dev/null
+++ b/Poco/MD5Engine.h
@@ -0,0 +1,95 @@
+//
+// MD5Engine.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  MD5Engine
+//
+// Definition of class MD5Engine.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+//
+// MD5 (RFC 1321) algorithm:
+// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+// 
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD5 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+//
+
+
+#ifndef Foundation_MD5Engine_INCLUDED
+#define Foundation_MD5Engine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DigestEngine.h"
+
+
+namespace Poco {
+
+
+class Foundation_API MD5Engine: public DigestEngine
+	/// This class implementes the MD5 message digest algorithm,
+	/// described in RFC 1321.
+{
+public:
+	enum
+	{
+		BLOCK_SIZE  = 64,
+		DIGEST_SIZE = 16
+	};
+
+	MD5Engine();
+	~MD5Engine();
+		
+	std::size_t digestLength() const;
+	void reset();
+	const DigestEngine::Digest& digest();
+
+protected:
+	void updateImpl(const void* data, std::size_t length);
+
+private:
+	static void transform(UInt32 state[4], const unsigned char block[64]);
+	static void encode(unsigned char* output, const UInt32* input, std::size_t len);
+	static void decode(UInt32* output, const unsigned char* input, std::size_t len);
+
+	struct Context
+	{
+		UInt32 state[4];          // state (ABCD)
+		UInt32 count[2];          // number of bits, modulo 2^64 (lsb first)
+		unsigned char buffer[64]; // input buffer
+	};
+
+	Context _context;
+	DigestEngine::Digest _digest;
+
+	MD5Engine(const MD5Engine&);
+	MD5Engine& operator = (const MD5Engine&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_MD5Engine_INCLUDED
diff --git a/Poco/Manifest.h b/Poco/Manifest.h
new file mode 100644
index 0000000..f2d36e7
--- /dev/null
+++ b/Poco/Manifest.h
@@ -0,0 +1,180 @@
+//
+// Manifest.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  ClassLoader
+//
+// Definition of the Manifest class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Manifest_INCLUDED
+#define Foundation_Manifest_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/MetaObject.h"
+#include <map>
+#include <typeinfo>
+
+
+namespace Poco {
+
+
+class Foundation_API ManifestBase
+	/// ManifestBase is a common base class for
+	/// all instantiations of Manifest.
+{
+public:
+	ManifestBase();
+	virtual ~ManifestBase();
+
+	virtual const char* className() const = 0;
+		/// Returns the type name of the manifest's class.
+};
+
+
+template <class B>
+class Manifest: public ManifestBase
+	/// A Manifest maintains a list of all classes
+	/// contained in a dynamically loadable class
+	/// library.
+	/// Internally, the information is held
+	/// in a map. An iterator is provided to
+	/// iterate over all the classes in a Manifest.
+{
+public:
+	typedef AbstractMetaObject<B> Meta;
+	typedef std::map<std::string, const Meta*> MetaMap;
+
+	class Iterator
+		/// The Manifest's very own iterator class.
+	{
+	public:
+		Iterator(const typename MetaMap::const_iterator& it)
+		{
+			_it = it;
+		}
+		Iterator(const Iterator& it)
+		{
+			_it = it._it;
+		}
+		~Iterator()
+		{
+		}
+		Iterator& operator = (const Iterator& it)
+		{
+			_it = it._it;
+			return *this;
+		}
+		inline bool operator == (const Iterator& it) const
+		{
+			return _it == it._it;
+		}
+		inline bool operator != (const Iterator& it) const
+		{
+			return _it != it._it;
+		}
+		Iterator& operator ++ () // prefix
+		{
+			++_it;
+			return *this;
+		}
+		Iterator operator ++ (int) // postfix
+		{
+			Iterator result(_it);
+			++_it;
+			return result;
+		}
+		inline const Meta* operator * () const
+		{
+			return _it->second;
+		}
+		inline const Meta* operator -> () const
+		{
+			return _it->second;
+		}
+		
+	private:
+		typename MetaMap::const_iterator _it;
+	};
+
+	Manifest()
+		/// Creates an empty Manifest.
+	{
+	}
+
+	virtual ~Manifest()
+		/// Destroys the Manifest.
+	{
+		clear();
+	}
+
+	Iterator find(const std::string& className) const
+		/// Returns an iterator pointing to the MetaObject
+		/// for the given class. If the MetaObject cannot
+		/// be found, the iterator points to end().
+	{
+		return Iterator(_metaMap.find(className));
+	}
+
+	Iterator begin() const
+	{
+		return Iterator(_metaMap.begin());
+	}
+
+	Iterator end() const
+	{
+		return Iterator(_metaMap.end());
+	}
+
+	bool insert(const Meta* pMeta)
+		/// Inserts a MetaObject. Returns true if insertion
+		/// was successful, false if a class with the same
+		/// name already exists.
+	{
+		return _metaMap.insert(typename MetaMap::value_type(pMeta->name(), pMeta)).second;
+	}
+
+	void clear()
+		/// Removes all MetaObjects from the manifest.
+	{
+		for (typename MetaMap::iterator it = _metaMap.begin(); it != _metaMap.end(); ++it)
+		{
+			delete it->second;
+		}
+		_metaMap.clear();
+	}
+
+	int size() const
+		/// Returns the number of MetaObjects in the Manifest.
+	{
+		return int(_metaMap.size());
+	}
+
+	bool empty() const
+		/// Returns true iff the Manifest does not contain any MetaObjects.
+	{
+		return _metaMap.empty();
+	}
+
+	const char* className() const
+	{
+		return typeid(*this).name();
+	}
+
+private:
+	MetaMap _metaMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Manifest_INCLUDED
diff --git a/Poco/MemoryPool.h b/Poco/MemoryPool.h
new file mode 100644
index 0000000..55f238d
--- /dev/null
+++ b/Poco/MemoryPool.h
@@ -0,0 +1,115 @@
+//
+// MemoryPool.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  MemoryPool
+//
+// Definition of the MemoryPool class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_MemoryPool_INCLUDED
+#define Foundation_MemoryPool_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include <vector>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class Foundation_API MemoryPool
+	/// A simple pool for fixed-size memory blocks.
+	///
+	/// The main purpose of this class is to speed-up
+	/// memory allocations, as well as to reduce memory
+	/// fragmentation in situations where the same blocks
+	/// are allocated all over again, such as in server
+	/// applications.
+	///
+	/// All allocated blocks are retained for future use.
+	/// A limit on the number of blocks can be specified.
+	/// Blocks can be preallocated.
+{
+public:
+	MemoryPool(std::size_t blockSize, int preAlloc = 0, int maxAlloc = 0);
+		/// Creates a MemoryPool for blocks with the given blockSize.
+		/// The number of blocks given in preAlloc are preallocated.
+		
+	~MemoryPool();
+
+	void* get();
+		/// Returns a memory block. If there are no more blocks
+		/// in the pool, a new block will be allocated.
+		///
+		/// If maxAlloc blocks are already allocated, an
+		/// OutOfMemoryException is thrown.
+		
+	void release(void* ptr);
+		/// Releases a memory block and returns it to the pool.
+	
+	std::size_t blockSize() const;
+		/// Returns the block size.
+		
+	int allocated() const;
+		/// Returns the number of allocated blocks.
+		
+	int available() const;
+		/// Returns the number of available blocks in the pool.
+
+private:
+	MemoryPool();
+	MemoryPool(const MemoryPool&);
+	MemoryPool& operator = (const MemoryPool&);
+	
+	void clear();
+	
+	enum
+	{
+		BLOCK_RESERVE = 128
+	};
+	
+	typedef std::vector<char*> BlockVec;
+	
+	std::size_t _blockSize;
+	int         _maxAlloc;
+	int         _allocated;
+	BlockVec    _blocks;
+	FastMutex   _mutex;
+};
+
+
+//
+// inlines
+//
+inline std::size_t MemoryPool::blockSize() const
+{
+	return _blockSize;
+}
+
+
+inline int MemoryPool::allocated() const
+{
+	return _allocated;
+}
+
+
+inline int MemoryPool::available() const
+{
+	return (int) _blocks.size();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_MemoryPool_INCLUDED
diff --git a/Poco/MemoryStream.h b/Poco/MemoryStream.h
new file mode 100644
index 0000000..819f160
--- /dev/null
+++ b/Poco/MemoryStream.h
@@ -0,0 +1,246 @@
+//
+// MemoryStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  MemoryStream
+//
+// Definition of MemoryStreamBuf, MemoryInputStream, MemoryOutputStream
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_MemoryStream_INCLUDED
+#define Foundation_MemoryStream_INCLUDED
+
+
+#include "Poco/Bugcheck.h"
+#include "Poco/Foundation.h"
+#include "Poco/StreamUtil.h"
+#include <streambuf>
+#include <iosfwd>
+#include <ios>
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+template <typename ch, typename tr> 
+class BasicMemoryStreamBuf: public std::basic_streambuf<ch, tr>
+	/// BasicMemoryStreamBuf is a simple implementation of a 
+	/// stream buffer for reading and writing from a memory area.
+	///
+	/// This streambuf only supports unidirectional streams.
+	/// In other words, the BasicMemoryStreamBuf can be
+	/// used for the implementation of an istream or an
+	/// ostream, but not for an iostream.
+{
+protected:
+	typedef std::basic_streambuf<ch, tr> Base;
+	typedef std::basic_ios<ch, tr> IOS;
+	typedef ch char_type;
+	typedef tr char_traits;
+	typedef typename Base::int_type int_type;
+	typedef typename Base::pos_type pos_type;
+	typedef typename Base::off_type off_type;
+
+public:
+	BasicMemoryStreamBuf(char_type* pBuffer, std::streamsize bufferSize):
+		_pBuffer(pBuffer),
+		_bufferSize(bufferSize)
+	{
+		this->setg(_pBuffer, _pBuffer, _pBuffer + _bufferSize);
+		this->setp(_pBuffer, _pBuffer + _bufferSize);
+	}
+
+	~BasicMemoryStreamBuf()
+	{
+	}
+
+	virtual int_type overflow(int_type /*c*/)
+	{
+		return char_traits::eof();
+	}
+
+	virtual int_type underflow()
+	{
+		return char_traits::eof();
+	}
+
+	virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
+	{
+		const pos_type fail = off_type(-1);
+		off_type newoff = off_type(-1);
+
+		if ((which & std::ios_base::in) != 0)
+		{
+			if (this->gptr() == 0)
+				return fail;
+
+			if (way == std::ios_base::beg)
+			{
+				newoff = 0;
+			}
+			else if (way == std::ios_base::cur)
+			{
+				// cur is not valid if both in and out are specified (Condition 3)
+				if ((which & std::ios_base::out) != 0)
+					return fail;
+				newoff = this->gptr() - this->eback();
+			}
+			else if (way == std::ios_base::end)
+			{
+				newoff = this->egptr() - this->eback();
+			}
+			else
+			{
+				poco_bugcheck();
+			}
+
+			if ((newoff + off) < 0 || (this->egptr() - this->eback()) < (newoff + off))
+				return fail;
+			this->setg(this->eback(), this->eback() + newoff + off, this->egptr());
+		}
+
+		if ((which & std::ios_base::out) != 0)
+		{
+			if (this->pptr() == 0)
+				return fail;
+
+			if (way == std::ios_base::beg)
+			{
+				newoff = 0;
+			}
+			else if (way == std::ios_base::cur)
+			{
+				// cur is not valid if both in and out are specified (Condition 3)
+				if ((which & std::ios_base::in) != 0)
+					return fail;
+				newoff = this->pptr() - this->pbase();
+			}
+			else if (way == std::ios_base::end)
+			{
+				newoff = this->epptr() - this->pbase();
+			}
+			else
+			{
+				poco_bugcheck();
+			}
+
+			if (newoff + off < 0 || (this->epptr() - this->pbase()) < newoff + off)
+				return fail;
+			this->pbump((int)(newoff + off - (this->pptr() - this->pbase())));
+		}
+
+		return newoff;
+	}
+
+	virtual int sync()
+	{
+		return 0;
+	}
+	
+	std::streamsize charsWritten() const
+	{
+		return static_cast<std::streamsize>(this->pptr() - this->pbase());
+	}
+
+	void reset()
+		/// Resets the buffer so that current read and write positions
+		/// will be set to the beginning of the buffer.
+	{
+		this->setg(_pBuffer, _pBuffer, _pBuffer + _bufferSize);
+		this->setp(_pBuffer, _pBuffer + _bufferSize);
+	}
+		
+private:
+	char_type*      _pBuffer;
+	std::streamsize _bufferSize;
+
+	BasicMemoryStreamBuf();
+	BasicMemoryStreamBuf(const BasicMemoryStreamBuf&);
+	BasicMemoryStreamBuf& operator = (const BasicMemoryStreamBuf&);
+};
+
+
+//
+// We provide an instantiation for char
+//
+typedef BasicMemoryStreamBuf<char, std::char_traits<char> > MemoryStreamBuf;
+
+
+class Foundation_API MemoryIOS: public virtual std::ios
+	/// The base class for MemoryInputStream and MemoryOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	MemoryIOS(char* pBuffer, std::streamsize bufferSize);
+		/// Creates the basic stream.
+		
+	~MemoryIOS();
+		/// Destroys the stream.
+
+	MemoryStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+		
+protected:
+	MemoryStreamBuf _buf;
+};
+
+
+class Foundation_API MemoryInputStream: public MemoryIOS, public std::istream
+	/// An input stream for reading from a memory area.
+{
+public:
+	MemoryInputStream(const char* pBuffer, std::streamsize bufferSize);
+		/// Creates a MemoryInputStream for the given memory area,
+		/// ready for reading.
+	
+	~MemoryInputStream();
+		/// Destroys the MemoryInputStream.
+};
+
+
+class Foundation_API MemoryOutputStream: public MemoryIOS, public std::ostream
+	/// An input stream for reading from a memory area.
+{
+public:
+	MemoryOutputStream(char* pBuffer, std::streamsize bufferSize);
+		/// Creates a MemoryOutputStream for the given memory area,
+		/// ready for writing.
+	
+	~MemoryOutputStream();
+		/// Destroys the MemoryInputStream.
+
+	std::streamsize charsWritten() const;
+		/// Returns the number of chars written to the buffer.
+};
+
+
+//
+// inlines
+//
+inline MemoryStreamBuf* MemoryIOS::rdbuf()
+{
+	return &_buf;
+}
+
+
+inline std::streamsize MemoryOutputStream::charsWritten() const
+{
+	return _buf.charsWritten();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_MemoryStream_INCLUDED
diff --git a/Poco/Message.h b/Poco/Message.h
new file mode 100644
index 0000000..0086f2b
--- /dev/null
+++ b/Poco/Message.h
@@ -0,0 +1,271 @@
+//
+// Message.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  Message
+//
+// Definition of the Message class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Message_INCLUDED
+#define Foundation_Message_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Foundation_API Message
+	/// This class represents a log message that is sent through a
+	/// chain of log channels.
+	///
+	/// A Message contains a priority denoting the severity of the
+	/// message, a source describing its origin, a text describing
+	/// its meaning, the time of its creation, and an identifier of
+	/// the process and thread that created the message.
+	///
+	/// Optionally a Message can also contain the source file path
+	/// and line number of the statement generating the message.
+	///
+	/// A Message can also contain any number of named parameters
+	/// that contain additional information about the event that
+	/// caused the message.
+{
+public:
+	enum Priority
+	{
+		PRIO_FATAL = 1,   /// A fatal error. The application will most likely terminate. This is the highest priority.
+		PRIO_CRITICAL,    /// A critical error. The application might not be able to continue running successfully.
+		PRIO_ERROR,       /// An error. An operation did not complete successfully, but the application as a whole is not affected.
+		PRIO_WARNING,     /// A warning. An operation completed with an unexpected result.
+		PRIO_NOTICE,      /// A notice, which is an information with just a higher priority.
+		PRIO_INFORMATION, /// An informational message, usually denoting the successful completion of an operation.
+		PRIO_DEBUG,       /// A debugging message.
+		PRIO_TRACE        /// A tracing message. This is the lowest priority.
+	};
+	
+	Message();
+		/// Creates an empty Message.
+		/// The thread and process ids are set.
+		
+	Message(const std::string& source, const std::string& text, Priority prio);
+		/// Creates a Message with the given source, text and priority.
+		/// The thread and process ids are set.
+
+	Message(const std::string& source, const std::string& text, Priority prio, const char* file, int line);
+		/// Creates a Message with the given source, text, priority,
+		/// source file path and line. 
+		///
+		/// The source file path must be a 
+		/// static string with a lifetime that's at least the lifetime
+		/// of the message object (the string is not copied internally).
+		/// Usually, this will be the path string obtained from the 
+		/// __FILE__ macro.
+		///
+		/// The thread and process ids are set.
+		
+	Message(const Message& msg);
+		/// Creates a Message by copying another one.
+		
+	Message(const Message& msg, const std::string& text);
+		/// Creates a Message by copying all but the text from another message.
+		
+	~Message();
+		/// Destroys the Message.
+	
+	Message& operator = (const Message& msg);
+		/// Assignment operator.
+		
+	void swap(Message& msg);
+		/// Swaps the message with another one.	
+		
+	void setSource(const std::string& src);
+		/// Sets the source of the message.
+		
+	const std::string& getSource() const;
+		/// Returns the source of the message.
+		
+	void setText(const std::string& text);
+		/// Sets the text of the message.
+		
+	const std::string& getText() const;
+		/// Returns the text of the message.
+		
+	void setPriority(Priority prio);
+		/// Sets the priority of the message.
+		
+	Priority getPriority() const;
+		/// Returns the priority of the message.
+	
+	void setTime(const Timestamp& time);
+		/// Sets the time of the message.
+		
+	const Timestamp& getTime() const;
+		/// Returns the time of the message.
+		
+	void setThread(const std::string& thread);
+		/// Sets the thread identifier for the message.
+		
+	const std::string& getThread() const;
+		/// Returns the thread identifier for the message.
+
+	void setTid(long pid);
+		/// Sets the numeric thread identifier for the message.
+		
+	long getTid() const;
+		/// Returns the numeric thread identifier for the message.
+	
+	void setPid(long pid);
+		/// Sets the process identifier for the message.
+		
+	long getPid() const;
+		/// Returns the process identifier for the message.
+		
+	void setSourceFile(const char* file);
+		/// Sets the source file path of the statement
+		/// generating the log message.
+		///
+		/// File must be a static string, such as the value of
+		/// the __FILE__ macro. The string is not copied
+		/// internally for performance reasons.	
+		
+	const char* getSourceFile() const;
+		/// Returns the source file path of the code creating
+		/// the message. May be 0 if not set.
+		
+	void setSourceLine(int line);
+		/// Sets the source file line of the statement
+		/// generating the log message.
+		///
+		/// This is usually the result of the __LINE__
+		/// macro.
+		
+	int getSourceLine() const;
+		/// Returns the source file line of the statement
+		/// generating the log message. May be 0
+		/// if not set.
+
+	bool has(const std::string& param) const;
+		/// Returns true if a parameter with the given name exists.
+
+	const std::string& get(const std::string& param) const;
+		/// Returns a const reference to the value of the parameter
+		/// with the given name. Throws a NotFoundException if the
+		/// parameter does not exist.
+
+	const std::string& get(const std::string& param, const std::string& defaultValue) const;
+		/// Returns a const reference to the value of the parameter
+		/// with the given name. If the parameter with the given name
+		/// does not exist, then defaultValue is returned.
+
+	void set(const std::string& param, const std::string& value);
+		/// Sets the value for a parameter. If the parameter does
+		/// not exist, then it is created.
+
+	const std::string& operator [] (const std::string& param) const;
+		/// Returns a const reference to the value of the parameter
+		/// with the given name. Throws a NotFoundException if the
+		/// parameter does not exist.
+		
+	std::string& operator [] (const std::string& param);
+		/// Returns a reference to the value of the parameter with the
+		/// given name. This can be used to set the parameter's value.
+		/// If the parameter does not exist, it is created with an
+		/// empty string value.
+
+protected:
+	void init();
+	typedef std::map<std::string, std::string> StringMap;
+
+private:	
+	std::string _source;
+	std::string _text;
+	Priority    _prio;
+	Timestamp   _time;
+	long        _tid;
+	std::string _thread;
+	long        _pid;
+	const char* _file;
+	int         _line;
+	StringMap*  _pMap;
+};
+
+
+//
+// inlines
+//
+inline const std::string& Message::getSource() const
+{
+	return _source;
+}
+
+
+inline const std::string& Message::getText() const
+{
+	return _text;
+}
+
+
+inline Message::Priority Message::getPriority() const
+{
+	return _prio;
+}
+
+
+inline const Timestamp& Message::getTime() const
+{
+	return _time;
+}
+
+
+inline const std::string& Message::getThread() const
+{
+	return _thread;
+}
+
+
+inline long Message::getTid() const
+{
+	return _tid;
+}
+
+
+inline long Message::getPid() const
+{
+	return _pid;
+}
+
+
+inline const char* Message::getSourceFile() const
+{
+	return _file;
+}
+
+
+inline int Message::getSourceLine() const
+{
+	return _line;
+}
+
+
+inline void swap(Message& m1, Message& m2)
+{
+	m1.swap(m2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Message_INCLUDED
diff --git a/Poco/MetaObject.h b/Poco/MetaObject.h
new file mode 100644
index 0000000..b3b0d24
--- /dev/null
+++ b/Poco/MetaObject.h
@@ -0,0 +1,201 @@
+//
+// MetaObject.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  ClassLoader
+//
+// Definition of the MetaObject class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_MetaObject_INCLUDED
+#define Foundation_MetaObject_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/SingletonHolder.h"
+#include <set>
+
+
+namespace Poco {
+
+
+template <class B>
+class AbstractMetaObject
+	/// A MetaObject stores some information
+	/// about a C++ class. The MetaObject class
+	/// is used by the Manifest class.
+	/// AbstractMetaObject is a common base class
+	/// for all MetaObject in a rooted class hierarchy.
+	/// A MetaObject can also be used as an object
+	/// factory for its class.
+{
+public:
+	AbstractMetaObject(const char* name): _name(name)
+	{
+	}
+
+	virtual ~AbstractMetaObject()
+	{
+		for (typename ObjectSet::iterator it = _deleteSet.begin(); it != _deleteSet.end(); ++it)
+		{
+			delete *it;
+		}
+	}
+
+	const char* name() const
+	{
+		return _name;
+	}
+
+	virtual B* create() const = 0;
+		/// Create a new instance of a class.
+		/// Cannot be used for singletons.
+		
+	virtual B& instance() const = 0;
+		/// Returns a reference to the only instance
+		/// of the class. Used for singletons only.
+
+	virtual bool canCreate() const = 0;
+		/// Returns true iff the create method can be used
+		/// to create instances of the class.
+		/// Returns false if the class is a singleton.
+
+	virtual void destroy(B* pObject) const
+		/// If pObject was owned by meta object, the
+		/// ownership of the deleted object is removed
+		/// and the object is deleted.
+	{
+		typename ObjectSet::iterator it = _deleteSet.find(pObject);
+		
+		if (it != _deleteSet.end())
+		{
+			_deleteSet.erase(pObject);
+			delete pObject;
+		}
+	}
+
+	B* autoDelete(B* pObject) const
+		/// Give ownership of pObject to the meta object.
+		/// The meta object will delete all objects it owns
+		/// when it is destroyed.
+		///
+		/// Returns pObject.
+	{
+		if (this->canCreate()) // guard against singleton
+		{
+			poco_check_ptr (pObject);
+			_deleteSet.insert(pObject);
+		}
+		else throw InvalidAccessException("Cannot take ownership of", this->name());
+
+		return pObject;
+	}
+
+	virtual bool isAutoDelete(B* pObject) const
+		/// Returns true if the object is owned
+		/// by meta object.
+		///
+		/// Overloaded in MetaSingleton - returns true
+		/// if the class is a singleton.
+	{
+		return _deleteSet.find(pObject) != _deleteSet.end();
+	}
+
+private:
+	AbstractMetaObject();
+	AbstractMetaObject(const AbstractMetaObject&);
+	AbstractMetaObject& operator = (const AbstractMetaObject&);
+
+	typedef std::set<B*> ObjectSet;
+	
+	const char* _name;
+	mutable ObjectSet _deleteSet;
+};
+
+
+template <class C, class B>
+class MetaObject: public AbstractMetaObject<B>
+	/// A MetaObject stores some information
+	/// about a C++ class. The MetaObject class
+	/// is used by the Manifest class.
+	/// A MetaObject can also be used as an object
+	/// factory for its class.
+{
+public:
+	MetaObject(const char* name): AbstractMetaObject<B>(name)
+	{
+	}
+
+	~MetaObject()
+	{
+	}
+
+	B* create() const
+	{
+		return new C;
+	}
+	
+	B& instance() const
+	{
+		throw InvalidAccessException("Not a singleton. Use create() to create instances of", this->name());
+	}
+	
+	bool canCreate() const
+	{
+		return true;
+	}
+};
+
+
+template <class C, class B> 
+class MetaSingleton: public AbstractMetaObject<B> 
+	/// A SingletonMetaObject disables the create() method
+	/// and instead offers an instance() method to access
+	/// the single instance of its class. 
+{ 
+public: 
+	MetaSingleton(const char* name): AbstractMetaObject<B>(name) 
+	{
+	}
+	
+	~MetaSingleton() 
+	{
+	}
+	
+	B* create() const
+	{
+		throw InvalidAccessException("Cannot create instances of a singleton class. Use instance() to obtain a", this->name());
+	}
+	
+	bool canCreate() const
+	{
+		return false;
+	}
+
+	B& instance() const
+	{
+		return *_object.get();
+	}
+
+	bool isAutoDelete(B* /*pObject*/) const
+	{
+		return true;
+	}
+
+private: 
+	mutable SingletonHolder<C> _object; 
+}; 
+
+
+} // namespace Poco
+
+
+#endif // Foundation_MetaObject_INCLUDED
diff --git a/Poco/MetaProgramming.h b/Poco/MetaProgramming.h
new file mode 100644
index 0000000..ba68fe0
--- /dev/null
+++ b/Poco/MetaProgramming.h
@@ -0,0 +1,144 @@
+//
+// MetaProgramming.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  MetaProgramming
+//
+// Common definitions useful for Meta Template Programming
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_MetaProgramming_INCLUDED
+#define Foundation_MetaProgramming_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <typename T>
+struct IsReference
+	/// Use this struct to determine if a template type is a reference.
+{
+	enum
+	{
+		VALUE = 0
+	};
+};
+
+
+template <typename T>
+struct IsReference<T&>
+{
+	enum 
+	{
+		VALUE = 1
+	};
+};
+
+
+template <typename T>
+struct IsReference<const T&>
+{
+	enum 
+	{
+		VALUE = 1
+	};
+};
+
+
+template <typename T>
+struct IsConst
+	/// Use this struct to determine if a template type is a const type.
+{
+	enum
+	{
+		VALUE = 0
+	};
+};
+
+
+template <typename T>
+struct IsConst<const T&>
+{
+	enum 
+	{
+		VALUE = 1
+	};
+};
+
+
+template <typename T>
+struct IsConst<const T>
+{
+	enum 
+	{
+		VALUE = 1
+	};
+};
+
+
+template <typename T, int i>
+struct IsConst<const T[i]>
+	/// Specialization for const char arrays
+{
+	enum
+	{
+		VALUE = 1
+	};
+};
+
+
+template <typename T>
+struct TypeWrapper
+	/// Use the type wrapper if you want to decouple constness and references from template types.
+{
+	typedef T TYPE;
+	typedef const T CONSTTYPE;
+	typedef T& REFTYPE;
+	typedef const T& CONSTREFTYPE;
+};
+
+
+template <typename T>
+struct TypeWrapper<const T>
+{
+	typedef T TYPE;
+	typedef const T CONSTTYPE;
+	typedef T& REFTYPE;
+	typedef const T& CONSTREFTYPE;
+};
+
+
+template <typename T>
+struct TypeWrapper<const T&>
+{
+	typedef T TYPE;
+	typedef const T CONSTTYPE;
+	typedef T& REFTYPE;
+	typedef const T& CONSTREFTYPE;
+};
+
+
+template <typename T>
+struct TypeWrapper<T&>
+{
+	typedef T TYPE;
+	typedef const T CONSTTYPE;
+	typedef T& REFTYPE;
+	typedef const T& CONSTREFTYPE;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_MetaProgramming_INCLUDED
diff --git a/Poco/MongoDB/Array.h b/Poco/MongoDB/Array.h
new file mode 100644
index 0000000..ee306bb
--- /dev/null
+++ b/Poco/MongoDB/Array.h
@@ -0,0 +1,110 @@
+//
+// Array.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Array
+//
+// Definition of the Array class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Array_INCLUDED
+#define MongoDB_Array_INCLUDED
+
+
+#include "Poco/NumberFormatter.h"
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Document.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Array: public Document
+	/// This class represents a BSON Array.
+{
+public:
+	typedef SharedPtr<Array> Ptr;
+
+	Array();
+		/// Creates an empty Array.
+
+	virtual ~Array();
+		/// Destroys the Array.
+
+	template<typename T>
+	T get(int pos) const
+		/// Returns the element at the given index and tries to convert
+		/// it to the template type. If the element is not found, a
+		/// Poco::NotFoundException will be thrown. If the element cannot be
+		/// converted a BadCastException will be thrown.
+	{
+		return Document::get<T>(Poco::NumberFormatter::format(pos));
+	}
+
+	template<typename T>
+	T get(int pos, const T& deflt) const
+		/// Returns the element at the given index and tries to convert
+		/// it to the template type. If the element is not found, or
+		/// has the wrong type, the deflt argument will be returned.
+	{
+		return Document::get<T>(Poco::NumberFormatter::format(pos), deflt);
+	}
+
+	Element::Ptr get(int pos) const;
+		/// Returns the element at the given index.
+		/// An empty element will be returned if the element is not found.
+
+	template<typename T>
+	bool isType(int pos) const
+		/// Returns true if the type of the element equals the TypeId of ElementTrait,
+		/// otherwise false.
+	{
+		return Document::isType<T>(Poco::NumberFormatter::format(pos));
+	}
+
+	std::string toString(int indent = 0) const;
+		/// Returns a string representation of the Array.
+};
+
+
+// BSON Embedded Array
+// spec: document
+template<>
+struct ElementTraits<Array::Ptr>
+{
+	enum { TypeId = 0x04 };
+
+	static std::string toString(const Array::Ptr& value, int indent = 0)
+	{
+		//TODO:
+		return value.isNull() ? "null" : value->toString(indent);
+	}
+};
+
+
+template<>
+inline void BSONReader::read<Array::Ptr>(Array::Ptr& to)
+{
+	to->read(_reader);
+}
+
+
+template<>
+inline void BSONWriter::write<Array::Ptr>(Array::Ptr& from)
+{
+	from->write(_writer);
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Array_INCLUDED
diff --git a/Poco/MongoDB/BSONReader.h b/Poco/MongoDB/BSONReader.h
new file mode 100644
index 0000000..3c5d9ba
--- /dev/null
+++ b/Poco/MongoDB/BSONReader.h
@@ -0,0 +1,84 @@
+//
+// BSONReader.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  BSONReader
+//
+// Definition of the BSONReader class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_BSONReader_INCLUDED
+#define MongoDB_BSONReader_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/BinaryReader.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API BSONReader
+	/// Class for reading BSON using a Poco::BinaryReader
+{
+public:
+	BSONReader(const Poco::BinaryReader& reader):
+		_reader(reader)
+		/// Creates the BSONReader using the given BinaryWriter.
+	{
+	}
+
+	virtual ~BSONReader()
+		/// Destroys the BSONReader.
+	{
+	}
+
+	template<typename T>
+	void read(T& t)
+		/// Reads the value from the reader. The default implementation uses the >> operator to
+		/// the given argument. Special types can write their own version.
+	{
+		_reader >> t;
+	}
+
+	std::string readCString();
+		/// Reads a cstring from the reader.
+		/// A cstring is a string terminated with a 0x00.
+
+private:
+	Poco::BinaryReader _reader;
+};
+
+
+//
+// inlines
+//
+inline std::string BSONReader::readCString()
+{
+	std::string val;
+	while(_reader.good())
+	{
+		char c;
+		_reader >> c;
+		if ( _reader.good() )
+		{
+			if (c == 0x00) return val;
+			else val += c;
+		}
+	}
+	return val;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_BSONReader_INCLUDED
diff --git a/Poco/MongoDB/BSONWriter.h b/Poco/MongoDB/BSONWriter.h
new file mode 100644
index 0000000..01c9491
--- /dev/null
+++ b/Poco/MongoDB/BSONWriter.h
@@ -0,0 +1,74 @@
+//
+// BSONWriter.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  BSONWriter
+//
+// Definition of the BSONWriter class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_BSONWriter_INCLUDED
+#define MongoDB_BSONWriter_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/BinaryWriter.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API BSONWriter
+	/// Class for writing BSON using a Poco::BinaryWriter.
+{
+public:
+	BSONWriter(const Poco::BinaryWriter& writer): 
+		_writer(writer)
+		/// Creates the BSONWriter.
+	{
+	}
+
+	virtual ~BSONWriter()
+		/// Destroys the BSONWriter.
+	{
+	}
+
+	template<typename T>
+	void write(T& t)
+		/// Writes the value to the writer. The default implementation uses
+		/// the << operator. Special types can write their own version.
+	{
+		_writer << t;
+	}
+
+	void writeCString(const std::string& value);
+		/// Writes a cstring to the writer. A cstring is a string
+		/// terminated a null character.
+
+private:
+	Poco::BinaryWriter _writer;
+};
+
+
+//
+// inlines
+//
+inline void BSONWriter::writeCString(const std::string& value)
+{
+	_writer.writeRaw(value);
+	_writer << (unsigned char) 0x00;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_BSONWriter_INCLUDED
diff --git a/Poco/MongoDB/Binary.h b/Poco/MongoDB/Binary.h
new file mode 100644
index 0000000..02b6baf
--- /dev/null
+++ b/Poco/MongoDB/Binary.h
@@ -0,0 +1,155 @@
+//
+// Binary.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Binary
+//
+// Definition of the Binary class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Binary_INCLUDED
+#define MongoDB_Binary_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Element.h"
+#include "Poco/Base64Encoder.h"
+#include "Poco/Buffer.h"
+#include "Poco/StreamCopier.h"
+#include "Poco/MemoryStream.h"
+#include "Poco/UUID.h"
+#include <sstream>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Binary
+	/// Implements BSON Binary.
+	///
+	/// A Binary stores its data in a Poco::Buffer<unsigned char>.
+{
+public:
+	typedef SharedPtr<Binary> Ptr;
+
+	Binary();
+		/// Creates an empty Binary with subtype 0.
+
+	Binary(Poco::Int32 size, unsigned char subtype);
+		/// Creates a Binary with a buffer of the given size and the given subtype.
+
+	Binary(const UUID& uuid);
+		/// Creates a Binary containing an UUID.
+		
+	Binary(const std::string& data, unsigned char subtype = 0);
+		/// Creates a Binary with the contents of the given string and the given subtype.
+		
+	Binary(const void* data, Poco::Int32 size, unsigned char subtype = 0);
+		/// Creates a Binary with the contents of the given buffer and the given subtype.		
+
+	virtual ~Binary();
+		/// Destroys the Binary.
+
+	Buffer<unsigned char>& buffer();
+		/// Returns a reference to the internal buffer
+
+	unsigned char subtype() const;
+		/// Returns the subtype.
+
+	void subtype(unsigned char type);
+		/// Sets the subtype.
+
+	std::string toString(int indent = 0) const;
+		/// Returns the contents of the Binary as Base64-encoded string.
+		
+	std::string toRawString() const;
+		/// Returns the raw content of the Binary as a string.
+
+	UUID uuid() const;
+		/// Returns the UUID when the binary subtype is 0x04.
+		/// Otherwise, throws a Poco::BadCastException.
+
+private:
+	Buffer<unsigned char> _buffer;
+	unsigned char _subtype;
+};
+
+
+//
+// inlines
+//
+inline unsigned char Binary::subtype() const
+{
+	return _subtype;
+}
+
+
+inline void Binary::subtype(unsigned char type)
+{
+	_subtype = type;
+}
+
+
+inline Buffer<unsigned char>& Binary::buffer()
+{
+	return _buffer;
+}
+
+
+inline std::string Binary::toRawString() const
+{
+	return std::string(reinterpret_cast<const char*>(_buffer.begin()), _buffer.size());
+}
+
+
+// BSON Embedded Document
+// spec: binary
+template<>
+struct ElementTraits<Binary::Ptr>
+{
+	enum { TypeId = 0x05 };
+
+	static std::string toString(const Binary::Ptr& value, int indent = 0)
+	{
+		return value.isNull() ? "" : value->toString();
+	}
+};
+
+
+template<>
+inline void BSONReader::read<Binary::Ptr>(Binary::Ptr& to)
+{
+	Poco::Int32 size;
+	_reader >> size;
+
+	to->buffer().resize(size);
+
+	unsigned char subtype;
+	_reader >> subtype;
+	to->subtype(subtype);
+	
+	_reader.readRaw((char*) to->buffer().begin(), size);
+}
+
+
+template<>
+inline void BSONWriter::write<Binary::Ptr>(Binary::Ptr& from)
+{
+	_writer << (Poco::Int32) from->buffer().size();
+	_writer << from->subtype();
+	_writer.writeRaw((char*) from->buffer().begin(), from->buffer().size());
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Binary_INCLUDED
diff --git a/Poco/MongoDB/Connection.h b/Poco/MongoDB/Connection.h
new file mode 100644
index 0000000..202ae90
--- /dev/null
+++ b/Poco/MongoDB/Connection.h
@@ -0,0 +1,164 @@
+//
+// Connection.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Connection
+//
+// Definition of the Connection class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Connection_INCLUDED
+#define MongoDB_Connection_INCLUDED
+
+
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Mutex.h"
+#include "Poco/MongoDB/RequestMessage.h"
+#include "Poco/MongoDB/ResponseMessage.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Connection
+	/// Represents a connection to a MongoDB server
+	/// using the MongoDB wire protocol.
+	///
+	/// See https://docs.mongodb.com/manual/reference/mongodb-wire-protocol/
+	/// for more information on the wire protocol.
+{
+public:
+	typedef Poco::SharedPtr<Connection> Ptr;
+
+	class MongoDB_API SocketFactory
+	{
+	public:
+		SocketFactory();
+			/// Creates the SocketFactory.
+
+		virtual ~SocketFactory();
+			/// Destroys the SocketFactory.
+
+		virtual Poco::Net::StreamSocket createSocket(const std::string& host, int port, Poco::Timespan connectTimeout, bool secure);
+			/// Creates a Poco::Net::StreamSocket (if secure is false), or a
+			/// Poco::Net::SecureStreamSocket (if secure is true) connected to the
+			/// given host and port number.
+			///
+			/// The default implementation will throw a Poco::NotImplementedException
+			/// if secure is true.
+	};
+
+	Connection();
+		/// Creates an unconnected Connection.
+		///
+		/// Use this when you want to connect later on.
+
+	Connection(const std::string& hostAndPort);
+		/// Creates a Connection connected to the given MongoDB instance at host:port.
+		///
+		/// The host and port must be separated with a colon.
+
+	Connection(const std::string& uri, SocketFactory& socketFactory);
+		/// Creates a Connection connected to the given MongoDB instance at the
+		/// given URI.
+		///
+		/// See the corresponding connect() method for more information.
+
+	Connection(const std::string& host, int port);
+		/// Creates a Connection connected to the given MongoDB instance at host and port.
+
+	Connection(const Poco::Net::SocketAddress& addrs);
+		/// Creates a Connection connected to the given MongoDB instance at the given address.
+
+	Connection(const Poco::Net::StreamSocket& socket);
+		/// Creates a Connection connected to the given MongoDB instance using the given socket,
+		/// which must already be connected.
+
+	virtual ~Connection();
+		/// Destroys the Connection.
+
+	Poco::Net::SocketAddress address() const;
+		/// Returns the address of the MongoDB server.
+
+	void connect(const std::string& hostAndPort);
+		/// Connects to the given MongoDB server.
+		///
+		/// The host and port must be separated with a colon.
+
+	void connect(const std::string& uri, SocketFactory& socketFactory);
+		/// Connects to the given MongoDB instance at the given URI.
+		///
+		/// The URI must be in standard MongoDB connection string URI format:
+		///
+		///     mongodb://<user>:<password>@hostname.com:<port>/database-name?options
+		///
+		/// The following options are supported:
+		///
+		///   - ssl: If ssl=true is specified, a custom SocketFactory subclass creating
+		///     a SecureStreamSocket must be supplied.
+		///   - connectTimeoutMS: Socket connection timeout in milliseconds.
+		///   - socketTimeoutMS: Socket send/receive timeout in milliseconds.
+		///   - authMechanism: Authentication mechanism. Only "SCRAM-SHA-1" (default)
+		///     and "MONGODB-CR" are supported.
+		///
+		/// Unknown options are silently ignored.
+		///
+		/// Will also attempt to authenticate using the specified credentials,
+		/// using Database::authenticate().
+		///
+		/// Throws a Poco::NoPermissionException if authentication fails.
+
+	void connect(const std::string& host, int port);
+		/// Connects to the given MongoDB server.
+
+	void connect(const Poco::Net::SocketAddress& addrs);
+		/// Connects to the given MongoDB server.
+
+	void connect(const Poco::Net::StreamSocket& socket);
+		/// Connects using an already connected socket.
+
+	void disconnect();
+		/// Disconnects from the MongoDB server.
+
+	void sendRequest(RequestMessage& request);
+		/// Sends a request to the MongoDB server.
+		///
+		/// Used for one-way requests without a response.
+
+	void sendRequest(RequestMessage& request, ResponseMessage& response);
+		/// Sends a request to the MongoDB server and receives the response.
+		///
+		/// Use this when a response is expected: only a "query" or "getmore"
+		/// request will return a response.
+
+protected:
+	void connect();
+
+private:
+	Poco::Net::SocketAddress _address;
+	Poco::Net::StreamSocket _socket;
+};
+
+
+//
+// inlines
+//
+inline Net::SocketAddress Connection::address() const
+{
+	return _address;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Connection_INCLUDED
diff --git a/Poco/MongoDB/Cursor.h b/Poco/MongoDB/Cursor.h
new file mode 100644
index 0000000..b9816b0
--- /dev/null
+++ b/Poco/MongoDB/Cursor.h
@@ -0,0 +1,74 @@
+//
+// Cursor.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Cursor
+//
+// Definition of the Cursor class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Cursor_INCLUDED
+#define MongoDB_Cursor_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Connection.h"
+#include "Poco/MongoDB/QueryRequest.h"
+#include "Poco/MongoDB/ResponseMessage.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Cursor: public Document
+	/// Cursor is an helper class for querying multiple documents.
+{
+public:
+	Cursor(const std::string& dbname, const std::string& collectionName, QueryRequest::Flags flags = QueryRequest::QUERY_DEFAULT);
+		/// Creates a Cursor for the given database and collection, using the specified flags.
+
+	Cursor(const std::string& fullCollectionName, QueryRequest::Flags flags = QueryRequest::QUERY_DEFAULT);
+		/// Creates a Cursor for the given database and collection ("database.collection"), using the specified flags.
+
+	virtual ~Cursor();
+		/// Destroys the Cursor.
+
+	ResponseMessage& next(Connection& connection);
+		/// Tries to get the next documents. As long as ResponseMessage has a
+		/// cursor ID next can be called to retrieve the next bunch of documents.
+		///
+		/// The cursor must be killed (see kill()) when not all documents are needed.
+
+	QueryRequest& query();
+		/// Returns the associated query.
+
+	void kill(Connection& connection);
+		/// Kills the cursor and reset it so that it can be reused.
+
+private:
+	QueryRequest    _query;
+	ResponseMessage _response;
+};
+
+
+//
+// inlines
+//
+inline QueryRequest& Cursor::query()
+{
+	return _query;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Cursor_INCLUDED
diff --git a/Poco/MongoDB/Database.h b/Poco/MongoDB/Database.h
new file mode 100644
index 0000000..ab276ee
--- /dev/null
+++ b/Poco/MongoDB/Database.h
@@ -0,0 +1,162 @@
+//
+// Database.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Database
+//
+// Definition of the Database class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Database_INCLUDED
+#define MongoDB_Database_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Connection.h"
+#include "Poco/MongoDB/Document.h"
+#include "Poco/MongoDB/QueryRequest.h"
+#include "Poco/MongoDB/InsertRequest.h"
+#include "Poco/MongoDB/UpdateRequest.h"
+#include "Poco/MongoDB/DeleteRequest.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Database
+	/// Database is a helper class for creating requests. MongoDB works with
+	/// collection names and uses the part before the first dot as the name of
+	/// the database.
+{
+public:
+	explicit Database(const std::string& name);
+		/// Creates a Database for the database with the given name.
+
+	virtual ~Database();
+		/// Destroys the Database.
+		
+	bool authenticate(Connection& connection, const std::string& username, const std::string& password, const std::string& method = AUTH_SCRAM_SHA1);
+		/// Authenticates against the database using the given connection,
+		/// username and password, as well as authentication method.
+		///
+		/// "MONGODB-CR" (default prior to MongoDB 3.0) and 
+		/// "SCRAM-SHA-1" (default starting in 3.0) are the only supported 
+		/// authentication methods.
+		///
+		/// Returns true if authentication was successful, otherwise false.
+		///
+		/// May throw a Poco::ProtocolException if authentication fails for a reason other than
+		/// invalid credentials.
+
+	Int64 count(Connection& connection, const std::string& collectionName) const;
+		/// Sends a count request for the given collection to MongoDB. 
+		///
+		/// If the command fails, -1 is returned.
+
+	Poco::SharedPtr<Poco::MongoDB::QueryRequest> createCommand() const;
+		/// Creates a QueryRequest for a command.
+
+	Poco::SharedPtr<Poco::MongoDB::QueryRequest> createCountRequest(const std::string& collectionName) const;
+		/// Creates a QueryRequest to count the given collection. 
+		/// The collectionname must not contain the database name.
+
+	Poco::SharedPtr<Poco::MongoDB::DeleteRequest> createDeleteRequest(const std::string& collectionName) const;
+		/// Creates a DeleteRequest to delete documents in the given collection.
+		/// The collectionname must not contain the database name.
+
+	Poco::SharedPtr<Poco::MongoDB::InsertRequest> createInsertRequest(const std::string& collectionName) const;
+		/// Creates an InsertRequest to insert new documents in the given collection.
+		/// The collectionname must not contain the database name.
+
+	Poco::SharedPtr<Poco::MongoDB::QueryRequest> createQueryRequest(const std::string& collectionName) const;
+		/// Creates a QueryRequest. 
+		/// The collectionname must not contain the database name.
+
+	Poco::SharedPtr<Poco::MongoDB::UpdateRequest> createUpdateRequest(const std::string& collectionName) const;
+		/// Creates an UpdateRequest. 
+		/// The collectionname must not contain the database name.
+
+	Poco::MongoDB::Document::Ptr ensureIndex(Connection& connection,
+		const std::string& collection,
+		const std::string& indexName,
+		Poco::MongoDB::Document::Ptr keys,
+		bool unique = false,
+		bool background = false,
+		int version = 0,
+		int ttl = 0);
+		/// Creates an index. The document returned is the result of a getLastError call.
+		/// For more info look at the ensureIndex information on the MongoDB website.
+
+	Document::Ptr getLastErrorDoc(Connection& connection) const;
+		/// Sends the getLastError command to the database and returns the error document.
+
+	std::string getLastError(Connection& connection) const;
+		/// Sends the getLastError command to the database and returns the err element
+		/// from the error document. When err is null, an empty string is returned.
+
+	static const std::string AUTH_MONGODB_CR;
+		/// Default authentication mechanism prior to MongoDB 3.0.
+		
+	static const std::string AUTH_SCRAM_SHA1;
+		/// Default authentication mechanism for MongoDB 3.0.
+
+protected:
+	bool authCR(Connection& connection, const std::string& username, const std::string& password);
+	bool authSCRAM(Connection& connection, const std::string& username, const std::string& password);
+
+private:
+	std::string _dbname;
+};
+
+
+//
+// inlines
+//
+inline Poco::SharedPtr<Poco::MongoDB::QueryRequest> Database::createCommand() const
+{
+	Poco::SharedPtr<Poco::MongoDB::QueryRequest> cmd = createQueryRequest("$cmd");
+	cmd->setNumberToReturn(1);
+	return cmd;
+}
+
+
+inline Poco::SharedPtr<Poco::MongoDB::DeleteRequest>
+Database::createDeleteRequest(const std::string& collectionName) const
+{
+	return new Poco::MongoDB::DeleteRequest(_dbname + '.' + collectionName);
+}
+
+
+inline Poco::SharedPtr<Poco::MongoDB::InsertRequest>
+Database::createInsertRequest(const std::string& collectionName) const
+{
+	return new Poco::MongoDB::InsertRequest(_dbname + '.' + collectionName);
+}
+
+
+inline Poco::SharedPtr<Poco::MongoDB::QueryRequest>
+Database::createQueryRequest(const std::string& collectionName) const
+{
+	return new Poco::MongoDB::QueryRequest(_dbname + '.' + collectionName);
+}
+
+
+inline Poco::SharedPtr<Poco::MongoDB::UpdateRequest>
+Database::createUpdateRequest(const std::string& collectionName) const
+{
+	return new Poco::MongoDB::UpdateRequest(_dbname + '.' + collectionName);
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Database_INCLUDED
diff --git a/Poco/MongoDB/DeleteRequest.h b/Poco/MongoDB/DeleteRequest.h
new file mode 100644
index 0000000..8f3486d
--- /dev/null
+++ b/Poco/MongoDB/DeleteRequest.h
@@ -0,0 +1,113 @@
+//
+// DeleteRequest.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  DeleteRequest
+//
+// Definition of the DeleteRequest class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_DeleteRequest_INCLUDED
+#define MongoDB_DeleteRequest_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/RequestMessage.h"
+#include "Poco/MongoDB/Document.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API DeleteRequest: public RequestMessage
+	/// A DeleteRequest is used to delete one ore more documents from a database.
+	///
+	/// Specific flags for this request
+	///   - DELETE_DEFAULT: default delete operation
+	///   - DELETE_SINGLE_REMOVE: delete only the first document
+{
+public:
+	enum Flags
+	{
+		DELETE_DEFAULT = 0,
+			/// Default
+
+		DELETE_SINGLE_REMOVE = 1
+			/// Delete only the first document.
+	};
+
+	DeleteRequest(const std::string& collectionName, Flags flags = DELETE_DEFAULT);
+		/// Creates a DeleteRequest for the given collection using the given flags. 
+		///
+		/// The full collection name is the concatenation of the database 
+		/// name with the collection name, using a "." for the concatenation. For example, 
+		/// for the database "foo" and the collection "bar", the full collection name is 
+		/// "foo.bar".
+
+	DeleteRequest(const std::string& collectionName, bool justOne);
+		/// Creates a DeleteRequest for the given collection.
+		/// 
+		/// The full collection name is the concatenation of the database
+		/// name with the collection name, using a "." for the concatenation. For example,
+		/// for the database "foo" and the collection "bar", the full collection name is
+		/// "foo.bar". 
+		///
+		/// If justOne is true, only the first matching document will
+		/// be removed (the same as using flag DELETE_SINGLE_REMOVE).
+
+	virtual ~DeleteRequest();
+		/// Destructor
+
+	Flags flags() const;
+		/// Returns the flags.
+
+	void flags(Flags flag);
+		/// Sets the flags.
+
+	Document& selector();
+		/// Returns the selector document.
+
+protected:
+	void buildRequest(BinaryWriter& writer);
+		/// Writes the OP_DELETE request to the writer.
+
+private:
+	Flags       _flags;
+	std::string _fullCollectionName;
+	Document    _selector;
+};
+
+
+///
+/// inlines
+///
+inline DeleteRequest::Flags DeleteRequest::flags() const
+{
+	return _flags;
+}
+
+
+inline void DeleteRequest::flags(DeleteRequest::Flags flags)
+{
+	_flags = flags;
+}
+
+
+inline Document& DeleteRequest::selector()
+{
+	return _selector;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_DeleteRequest_INCLUDED
diff --git a/Poco/MongoDB/Document.h b/Poco/MongoDB/Document.h
new file mode 100644
index 0000000..674a1f7
--- /dev/null
+++ b/Poco/MongoDB/Document.h
@@ -0,0 +1,277 @@
+//
+// Document.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Document
+//
+// Definition of the Document class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Document_INCLUDED
+#define MongoDB_Document_INCLUDED
+
+
+#include "Poco/BinaryReader.h"
+#include "Poco/BinaryWriter.h"
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Element.h"
+#include <algorithm>
+#include <cstdlib>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class ElementFindByName
+{
+public:
+	ElementFindByName(const std::string& name): 
+		_name(name)
+	{
+	}
+
+	bool operator()(const Element::Ptr& element)
+	{
+		return !element.isNull() && element->name() == _name;
+	}
+
+private:
+	std::string _name;
+};
+
+
+class MongoDB_API Document
+	/// Represents a MongoDB (BSON) document.
+{
+public:
+	typedef SharedPtr<Document> Ptr;
+	typedef std::vector<Document::Ptr> Vector;
+
+	Document();
+		/// Creates an empty Document.
+
+	virtual ~Document();
+		/// Destroys the Document.
+
+	Document& addElement(Element::Ptr element);
+		/// Add an element to the document.
+		///
+		/// The active document is returned to allow chaining of the add methods.
+
+	template<typename T>
+	Document& add(const std::string& name, T value)
+		/// Creates an element with the given name and value and
+		/// adds it to the document.
+		///
+		/// The active document is returned to allow chaining of the add methods.
+	{
+		return addElement(new ConcreteElement<T>(name, value));
+	}
+
+	Document& add(const std::string& name, const char* value)
+		/// Creates an element with the given name and value and
+		/// adds it to the document.
+		///
+		/// The active document is returned to allow chaining of the add methods.
+	{
+		return addElement(new ConcreteElement<std::string>(name, std::string(value)));
+	}
+
+	Document& addNewDocument(const std::string& name);
+		/// Create a new document and add it to this document.
+		/// Unlike the other add methods, this method returns
+		/// a reference to the new document.
+
+	void clear();
+		/// Removes all elements from the document.
+
+	void elementNames(std::vector<std::string>& keys) const;
+		/// Puts all element names into std::vector.
+
+	bool empty() const;
+		/// Returns true if the document doesn't contain any documents.
+
+	bool exists(const std::string& name);
+		/// Returns true if the document has an element with the given name.
+
+	template<typename T>
+	T get(const std::string& name) const
+		/// Returns the element with the given name and tries to convert
+		/// it to the template type. When the element is not found, a
+		/// NotFoundException will be thrown. When the element can't be
+		/// converted a BadCastException will be thrown.
+	{
+		Element::Ptr element = get(name);
+		if (element.isNull())
+		{
+			throw NotFoundException(name);
+		}
+		else
+		{
+			if (ElementTraits<T>::TypeId == element->type())
+			{
+				ConcreteElement<T>* concrete = dynamic_cast<ConcreteElement<T>* >(element.get());
+				if (concrete != 0)
+				{
+					return concrete->value();
+				}
+			}
+			throw BadCastException("Invalid type mismatch!");
+		}
+	}
+
+	template<typename T>
+	T get(const std::string& name, const T& def) const
+		/// Returns the element with the given name and tries to convert
+		/// it to the template type. When the element is not found, or
+		/// has the wrong type, the def argument will be returned.
+	{
+		Element::Ptr element = get(name);
+		if (element.isNull())
+		{
+			return def;
+		}
+
+		if (ElementTraits<T>::TypeId == element->type())
+		{
+			ConcreteElement<T>* concrete = dynamic_cast<ConcreteElement<T>* >(element.get());
+			if (concrete != 0)
+			{
+				return concrete->value();
+			}
+		}
+
+		return def;
+	}
+
+	Element::Ptr get(const std::string& name) const;
+		/// Returns the element with the given name.
+		/// An empty element will be returned when the element is not found.
+
+	Int64 getInteger(const std::string& name) const;
+		/// Returns an integer. Useful when MongoDB returns Int32, Int64
+		/// or double for a number (count for example). This method will always
+		/// return an Int64. When the element is not found, a
+		/// Poco::NotFoundException will be thrown.
+
+	template<typename T>
+	bool isType(const std::string& name) const
+		/// Returns true when the type of the element equals the TypeId of ElementTrait.
+	{
+		Element::Ptr element = get(name);
+		if (element.isNull())
+		{
+			return false;
+		}
+
+		return ElementTraits<T>::TypeId == element->type();
+	}
+
+	void read(BinaryReader& reader);
+		/// Reads a document from the reader
+
+	std::size_t size() const;
+		/// Returns the number of elements in the document.
+
+	virtual std::string toString(int indent = 0) const;
+		/// Returns a String representation of the document.
+
+	void write(BinaryWriter& writer);
+		/// Writes a document to the reader
+
+protected:
+	ElementSet _elements;
+};
+
+
+//
+// inlines
+//
+inline Document& Document::addElement(Element::Ptr element)
+{
+	_elements.push_back(element);
+	return *this;
+}
+
+
+inline Document& Document::addNewDocument(const std::string& name)
+{
+	Document::Ptr newDoc = new Document();
+	add(name, newDoc);
+	return *newDoc;
+}
+
+
+inline void Document::clear()
+{
+	_elements.clear();
+}
+
+
+inline bool Document::empty() const
+{
+	return _elements.empty();
+}
+
+
+inline void Document::elementNames(std::vector<std::string>& keys) const
+{
+	for (ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it)
+	{
+		keys.push_back((*it)->name());
+	}
+}
+
+
+inline bool Document::exists(const std::string& name)
+{
+	return std::find_if(_elements.begin(), _elements.end(), ElementFindByName(name)) != _elements.end();
+}
+
+
+inline std::size_t Document::size() const
+{
+	return _elements.size();
+}
+
+
+// BSON Embedded Document
+// spec: document
+template<>
+struct ElementTraits<Document::Ptr>
+{
+	enum { TypeId = 0x03 };
+
+	static std::string toString(const Document::Ptr& value, int indent = 0)
+	{
+		return value.isNull() ? "null" : value->toString(indent);
+	}
+};
+
+
+template<>
+inline void BSONReader::read<Document::Ptr>(Document::Ptr& to)
+{
+	to->read(_reader);
+}
+
+
+template<>
+inline void BSONWriter::write<Document::Ptr>(Document::Ptr& from)
+{
+	from->write(_writer);
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Document_INCLUDED
diff --git a/Poco/MongoDB/Element.h b/Poco/MongoDB/Element.h
new file mode 100644
index 0000000..e6a41c4
--- /dev/null
+++ b/Poco/MongoDB/Element.h
@@ -0,0 +1,403 @@
+//
+// Element.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Element
+//
+// Definition of the Element class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Element_INCLUDED
+#define MongoDB_Element_INCLUDED
+
+
+#include "Poco/BinaryReader.h"
+#include "Poco/BinaryWriter.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Nullable.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/DateTimeFormatter.h"
+#include "Poco/UTF8String.h"
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/BSONReader.h"
+#include "Poco/MongoDB/BSONWriter.h"
+#include <string>
+#include <sstream>
+#include <iomanip>
+#include <list>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Element
+	/// Represents an Element of a Document or an Array.
+{
+public:
+	typedef Poco::SharedPtr<Element> Ptr;
+
+	explicit Element(const std::string& name);
+		/// Creates the Element with the given name.
+
+	virtual ~Element();
+		/// Destructor
+
+	const std::string& name() const;
+		/// Returns the name of the element.
+
+	virtual std::string toString(int indent = 0) const = 0;
+		/// Returns a string representation of the element.
+
+	virtual int type() const = 0;
+		/// Returns the MongoDB type of the element.
+
+private:
+	virtual void read(BinaryReader& reader) = 0;
+	virtual void write(BinaryWriter& writer) = 0;
+
+	friend class Document;
+	std::string _name;
+};
+
+
+//
+// inlines
+//
+inline const std::string& Element::name() const
+{
+	return _name;
+}
+
+
+typedef std::list<Element::Ptr> ElementSet;
+
+
+template<typename T> 
+struct ElementTraits
+{
+};
+
+
+// BSON Floating point
+// spec: double
+template<>
+struct ElementTraits<double>
+{
+	enum { TypeId = 0x01 };
+
+	static std::string toString(const double& value, int indent = 0)
+	{
+		return Poco::NumberFormatter::format(value);
+	}
+};
+
+
+// BSON UTF-8 string
+// spec: int32 (byte*) "\x00"
+// int32 is the number bytes in byte* + 1 (for trailing "\x00")
+template<>
+struct ElementTraits<std::string>
+{
+	enum { TypeId = 0x02 };
+
+	static std::string toString(const std::string& value, int indent = 0)
+	{
+		std::ostringstream oss;
+
+		oss << '"';
+
+		for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
+		{
+			switch (*it)
+			{
+			case '"':
+				oss << "\\\"";
+				break;
+			case '\\':
+				oss << "\\\\";
+				break;
+			case '\b':
+				oss << "\\b";
+				break;
+			case '\f':
+				oss << "\\f";
+				break;
+			case '\n':
+				oss << "\\n";
+				break;
+			case '\r':
+				oss << "\\r";
+				break;
+			case '\t':
+				oss << "\\t";
+				break;
+			default:
+				{
+					if ( *it > 0 && *it <= 0x1F )
+					{
+						oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*it);
+					}
+					else
+					{
+						oss << *it;
+					}
+					break;
+				}
+			}
+		}
+		oss << '"';
+		return oss.str();
+	}
+};
+
+
+template<>
+inline void BSONReader::read<std::string>(std::string& to)
+{
+	Poco::Int32 size;
+	_reader >> size;
+	_reader.readRaw(size, to);
+	to.erase(to.end() - 1); // remove terminating 0
+}
+
+
+template<>
+inline void BSONWriter::write<std::string>(std::string& from)
+{
+	_writer << (Poco::Int32) (from.length() + 1);
+	writeCString(from);
+}
+
+
+// BSON bool
+// spec: "\x00" "\x01"
+template<>
+struct ElementTraits<bool>
+{
+	enum { TypeId = 0x08 };
+
+	static std::string toString(const bool& value, int indent = 0)
+	{
+		return value ? "true" : "false";
+	}
+};
+
+
+template<>
+inline void BSONReader::read<bool>(bool& to)
+{
+	unsigned char b;
+	_reader >> b;
+	to = b != 0;
+}
+
+
+template<>
+inline void BSONWriter::write<bool>(bool& from)
+{
+	unsigned char b = from ? 0x01 : 0x00;
+	_writer << b;
+}
+
+
+// BSON 32-bit integer
+// spec: int32
+template<>
+struct ElementTraits<Int32>
+{
+	enum { TypeId = 0x10 };
+
+
+	static std::string toString(const Int32& value, int indent = 0)
+	{
+		return Poco::NumberFormatter::format(value);
+	}
+};
+
+
+// BSON UTC datetime
+// spec: int64
+template<>
+struct ElementTraits<Timestamp>
+{
+	enum { TypeId = 0x09 };
+
+	static std::string toString(const Timestamp& value, int indent = 0)
+	{
+		std::string result;
+		result.append(1, '"');
+		result.append(DateTimeFormatter::format(value, "%Y-%m-%dT%H:%M:%s%z"));
+		result.append(1, '"');
+		return result;
+	}
+};
+
+
+template<>
+inline void BSONReader::read<Timestamp>(Timestamp& to)
+{
+	Poco::Int64 value;
+	_reader >> value;
+	to = Timestamp::fromEpochTime(static_cast<std::time_t>(value / 1000));
+	to += (value % 1000 * 1000);
+}
+
+
+template<>
+inline void BSONWriter::write<Timestamp>(Timestamp& from)
+{
+	_writer << (from.epochMicroseconds() / 1000);
+}
+
+
+typedef Nullable<unsigned char> NullValue;
+
+
+// BSON Null Value
+// spec:
+template<>
+struct ElementTraits<NullValue>
+{
+	enum { TypeId = 0x0A };
+
+	static std::string toString(const NullValue& value, int indent = 0)
+	{
+		return "null";
+	}
+};
+
+
+template<>
+inline void BSONReader::read<NullValue>(NullValue& to)
+{
+}
+
+
+template<>
+inline void BSONWriter::write<NullValue>(NullValue& from)
+{
+}
+
+
+struct BSONTimestamp 
+{
+	Poco::Timestamp ts;
+	Poco::Int32 inc;
+};
+
+
+// BSON Timestamp
+// spec: int64
+template<>
+struct ElementTraits<BSONTimestamp>
+{
+	enum { TypeId = 0x11 };
+
+	static std::string toString(const BSONTimestamp& value, int indent = 0)
+	{
+		std::string result;
+		result.append(1, '"');
+		result.append(DateTimeFormatter::format(value.ts, "%Y-%m-%dT%H:%M:%s%z"));
+		result.append(1, ' ');
+		result.append(NumberFormatter::format(value.inc));
+		result.append(1, '"');
+		return result;
+	}
+};
+
+
+template<>
+inline void BSONReader::read<BSONTimestamp>(BSONTimestamp& to)
+{
+	Poco::Int64 value;
+	_reader >> value;
+	to.inc = value & 0xffffffff;
+	value >>= 32;
+	to.ts = Timestamp::fromEpochTime(static_cast<std::time_t>(value));
+}
+
+
+template<>
+inline void BSONWriter::write<BSONTimestamp>(BSONTimestamp& from)
+{
+	Poco::Int64 value = from.ts.epochMicroseconds() / 1000;
+	value <<= 32;
+	value += from.inc;
+	_writer << value;
+}
+
+
+// BSON 64-bit integer
+// spec: int64
+template<>
+struct ElementTraits<Int64>
+{
+	enum { TypeId = 0x12 };
+
+	static std::string toString(const Int64& value, int indent = 0)
+	{
+		return NumberFormatter::format(value);
+	}
+};
+
+
+template<typename T>
+class ConcreteElement: public Element
+{
+public:
+	ConcreteElement(const std::string& name, const T& init):
+		Element(name), 
+		_value(init)
+	{
+	}
+
+	virtual ~ConcreteElement()
+	{
+	}
+
+	
+	T value() const
+	{
+		return _value;
+	}
+
+
+	std::string toString(int indent = 0) const
+	{
+		return ElementTraits<T>::toString(_value, indent);
+	}
+
+	
+	int type() const
+	{
+		return ElementTraits<T>::TypeId;
+	}
+
+	void read(BinaryReader& reader)
+	{
+		BSONReader(reader).read(_value);
+	}
+
+	void write(BinaryWriter& writer)
+	{
+		BSONWriter(writer).write(_value);
+	}
+
+private:
+	T _value;
+};
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Element_INCLUDED
diff --git a/Poco/MongoDB/GetMoreRequest.h b/Poco/MongoDB/GetMoreRequest.h
new file mode 100644
index 0000000..f6c3f65
--- /dev/null
+++ b/Poco/MongoDB/GetMoreRequest.h
@@ -0,0 +1,89 @@
+//
+// GetMoreRequest.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  GetMoreRequest
+//
+// Definition of the GetMoreRequest class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_GetMoreRequest_INCLUDED
+#define MongoDB_GetMoreRequest_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/RequestMessage.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API GetMoreRequest: public RequestMessage
+	/// A GetMoreRequest is used to query the database for more documents in a collection 
+	/// after a query request is send (OP_GETMORE).
+{
+public:
+	GetMoreRequest(const std::string& collectionName, Int64 cursorID);
+		/// Creates a GetMoreRequest for the give collection and cursor. 
+		///
+		/// The full collection name is the concatenation of the database 
+		/// name with the collection name, using a "." for the concatenation. For example, 
+		/// for the database "foo" and the collection "bar", the full collection name is 
+		/// "foo.bar". The cursorID has been returned by the response on the query request.
+		/// By default the numberToReturn is set to 100.
+
+	virtual ~GetMoreRequest();
+		/// Destroys the GetMoreRequest.
+
+	Int32 getNumberToReturn() const;
+		/// Returns the limit of returned documents.
+
+	void setNumberToReturn(Int32 n);
+		/// Sets the limit of returned documents.
+
+	Int64 cursorID() const;
+		/// Returns the cursor ID.
+
+protected:
+	void buildRequest(BinaryWriter& writer);
+
+private:
+	std::string _fullCollectionName;
+	Int32 _numberToReturn;
+	Int64 _cursorID;
+};
+
+
+//
+// inlines
+//
+inline Int32 GetMoreRequest::getNumberToReturn() const
+{
+	return _numberToReturn;
+}
+
+
+inline void GetMoreRequest::setNumberToReturn(Int32 n)
+{
+	_numberToReturn = n;
+}
+
+
+inline Int64 GetMoreRequest::cursorID() const
+{
+	return _cursorID;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_GetMoreRequest_INCLUDED
diff --git a/Poco/MongoDB/InsertRequest.h b/Poco/MongoDB/InsertRequest.h
new file mode 100644
index 0000000..f9ed8a2
--- /dev/null
+++ b/Poco/MongoDB/InsertRequest.h
@@ -0,0 +1,97 @@
+//
+// InsertRequest.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  InsertRequest
+//
+// Definition of the InsertRequest class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_InsertRequest_INCLUDED
+#define MongoDB_InsertRequest_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/RequestMessage.h"
+#include "Poco/MongoDB/Document.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API InsertRequest: public RequestMessage
+	/// A request for inserting one or more documents to the database
+	/// (OP_INSERT).
+{
+public:
+	enum Flags
+	{
+		INSERT_DEFAULT = 0,
+			/// If specified, perform a normal insert operation.
+		
+		INSERT_CONTINUE_ON_ERROR = 1
+			/// If set, the database will not stop processing a bulk insert if one 
+			/// fails (e.g. due to duplicate IDs). This makes bulk insert behave similarly 
+			/// to a series of single inserts, except lastError will be set if any insert 
+			/// fails, not just the last one. If multiple errors occur, only the most 
+			/// recent will be reported.
+	};
+
+	InsertRequest(const std::string& collectionName, Flags flags = INSERT_DEFAULT);
+		/// Creates an InsertRequest.
+		///
+		/// The full collection name is the concatenation of the database 
+		/// name with the collection name, using a "." for the concatenation. For example, 
+		/// for the database "foo" and the collection "bar", the full collection name is 
+		/// "foo.bar".
+
+	virtual ~InsertRequest();
+		/// Destroys the InsertRequest.
+
+	Document& addNewDocument();
+		/// Adds a new document for insertion. A reference to the empty document is
+		/// returned. InsertRequest is the owner of the Document and will free it
+		/// on destruction.
+
+	Document::Vector& documents();
+		/// Returns the documents to insert into the database.
+
+protected:
+	void buildRequest(BinaryWriter& writer);
+
+private:
+	Int32 _flags;
+	std::string _fullCollectionName;
+	Document::Vector _documents;
+};
+
+
+//
+// inlines
+//
+inline Document& InsertRequest::addNewDocument()
+{
+	Document::Ptr doc = new Document();
+	_documents.push_back(doc);
+	return *doc;
+}
+
+
+inline Document::Vector& InsertRequest::documents()
+{
+	return _documents;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_InsertRequest_INCLUDED
diff --git a/Poco/MongoDB/JavaScriptCode.h b/Poco/MongoDB/JavaScriptCode.h
new file mode 100644
index 0000000..6401743
--- /dev/null
+++ b/Poco/MongoDB/JavaScriptCode.h
@@ -0,0 +1,105 @@
+//
+// JavaScriptCode.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  JavaScriptCode
+//
+// Definition of the JavaScriptCode class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_JavaScriptCode_INCLUDED
+#define MongoDB_JavaScriptCode_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/BSONReader.h"
+#include "Poco/MongoDB/BSONWriter.h"
+#include "Poco/MongoDB/Element.h"
+#include "Poco/SharedPtr.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API JavaScriptCode
+	/// Represents JavaScript type in BSON.
+{
+public:
+	typedef SharedPtr<JavaScriptCode> Ptr;
+
+	JavaScriptCode();
+		/// Creates an empty JavaScriptCode object.
+
+	virtual ~JavaScriptCode();
+		/// Destroys the JavaScriptCode.
+
+	void setCode(const std::string& code);
+		/// Sets the JavaScript code.
+
+	std::string getCode() const;
+		/// Returns the JavaScript code.
+
+private:
+	std::string _code;
+};
+
+
+//
+// inlines
+//
+inline void JavaScriptCode::setCode(const std::string& code)
+{
+	_code = code;
+}
+
+
+inline std::string JavaScriptCode::getCode() const
+{
+	return _code;
+}
+
+
+// BSON JavaScript code
+// spec: string
+template<>
+struct ElementTraits<JavaScriptCode::Ptr>
+{
+	enum { TypeId = 0x0D };
+
+	static std::string toString(const JavaScriptCode::Ptr& value, int indent = 0)
+	{
+		return value.isNull() ? "" : value->getCode();
+	}
+};
+
+
+template<>
+inline void BSONReader::read<JavaScriptCode::Ptr>(JavaScriptCode::Ptr& to)
+{
+	std::string code;
+	BSONReader(_reader).read(code);
+	to = new JavaScriptCode();
+	to->setCode(code);
+}
+
+
+template<>
+inline void BSONWriter::write<JavaScriptCode::Ptr>(JavaScriptCode::Ptr& from)
+{
+	std::string code = from->getCode();
+	BSONWriter(_writer).write(code);
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_JavaScriptCode_INCLUDED
diff --git a/Poco/MongoDB/KillCursorsRequest.h b/Poco/MongoDB/KillCursorsRequest.h
new file mode 100644
index 0000000..83a8085
--- /dev/null
+++ b/Poco/MongoDB/KillCursorsRequest.h
@@ -0,0 +1,62 @@
+//
+// KillCursorsRequest.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  KillCursorsRequest
+//
+// Definition of the KillCursorsRequest class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_KillCursorsRequest_INCLUDED
+#define MongoDB_KillCursorsRequest_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/RequestMessage.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API KillCursorsRequest: public RequestMessage
+	/// Class for creating an OP_KILL_CURSORS client request. This
+	/// request is used to kill cursors, which are still open, 
+	/// returned by query requests.
+{
+public:
+	KillCursorsRequest();
+		/// Creates a KillCursorsRequest.
+
+	virtual ~KillCursorsRequest();
+		/// Destroys the KillCursorsRequest.
+		
+	std::vector<Int64>& cursors();
+		/// The internal list of cursors.
+		
+protected:
+	void buildRequest(BinaryWriter& writer);
+	std::vector<Int64> _cursors;
+};
+
+
+//
+// inlines
+//
+inline std::vector<Int64>& KillCursorsRequest::cursors()
+{
+	return _cursors;
+} 
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_KillCursorsRequest_INCLUDED
diff --git a/Poco/MongoDB/Message.h b/Poco/MongoDB/Message.h
new file mode 100644
index 0000000..f3f1edb
--- /dev/null
+++ b/Poco/MongoDB/Message.h
@@ -0,0 +1,73 @@
+//
+// Message.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  Message
+//
+// Definition of the Message class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_Message_INCLUDED
+#define MongoDB_Message_INCLUDED
+
+
+#include "Poco/Net/Socket.h"
+#include "Poco/BinaryReader.h"
+#include "Poco/BinaryWriter.h"
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/MessageHeader.h"
+#include <sstream>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API Message
+	/// Base class for all messages send or retrieved from MongoDB server.
+{
+public:
+	explicit Message(MessageHeader::OpCode opcode);
+		/// Creates a Message using the given OpCode.
+	
+	virtual ~Message();
+		/// Destructor
+
+	MessageHeader& header();
+		/// Returns the message header
+
+protected:
+	MessageHeader _header;
+
+	void messageLength(Poco::Int32 length);
+		/// Sets the message length in the message header
+};
+
+
+//
+// inlines
+//
+inline MessageHeader& Message::header()
+{
+	return _header;
+}
+
+
+inline void Message::messageLength(Poco::Int32 length)
+{
+	poco_assert(length > 0);
+	_header.setMessageLength(length);
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_Message_INCLUDED
diff --git a/Poco/MongoDB/MessageHeader.h b/Poco/MongoDB/MessageHeader.h
new file mode 100644
index 0000000..1f86612
--- /dev/null
+++ b/Poco/MongoDB/MessageHeader.h
@@ -0,0 +1,130 @@
+//
+// MessageHeader.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  MessageHeader
+//
+// Definition of the MessageHeader class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_MessageHeader_INCLUDED
+#define MongoDB_MessageHeader_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/MessageHeader.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API MessageHeader
+	/// Represents the message header which is always prepended to a 
+	/// MongoDB request or response message.
+{
+public:
+	static const unsigned int MSG_HEADER_SIZE = 16;
+
+	enum OpCode
+	{
+		OP_REPLY = 1,
+		OP_MSG = 1000,
+		OP_UPDATE = 2001,
+		OP_INSERT = 2002,
+		OP_QUERY = 2004,
+		OP_GET_MORE = 2005,
+		OP_DELETE = 2006,
+		OP_KILL_CURSORS = 2007
+	};
+
+	explicit MessageHeader(OpCode);
+		/// Creates the MessageHeader using the given OpCode.
+
+	virtual ~MessageHeader();
+		/// Destroys the MessageHeader.
+
+	void read(BinaryReader& reader);
+		/// Reads the header using the given BinaryReader.
+
+	void write(BinaryWriter& writer);
+		/// Writes the header using the given BinaryWriter.
+
+	Int32 getMessageLength() const;
+		/// Returns the message length.
+
+	OpCode opCode() const;
+		/// Returns the OpCode.
+
+	Int32 getRequestID() const;
+		/// Returns the request ID of the current message.
+
+	void setRequestID(Int32 id);
+		/// Sets the request ID of the current message.
+
+	Int32 responseTo() const;
+		/// Returns the request id from the original request. 
+
+private:
+	void setMessageLength(Int32 length);
+		/// Sets the message length.
+
+	Int32 _messageLength;
+	Int32 _requestID;
+	Int32 _responseTo;
+	OpCode _opCode;
+
+	friend class Message;
+};
+
+
+//
+// inlines
+//
+inline MessageHeader::OpCode MessageHeader::opCode() const
+{
+	return _opCode;
+}
+
+
+inline Int32 MessageHeader::getMessageLength() const
+{
+	return _messageLength;
+}
+
+
+inline void MessageHeader::setMessageLength(Int32 length)
+{
+	poco_assert (_messageLength >= 0);
+	_messageLength = MSG_HEADER_SIZE + length;
+}
+
+
+inline void MessageHeader::setRequestID(Int32 id)
+{
+	_requestID = id;
+}
+
+
+inline Int32 MessageHeader::getRequestID() const
+{
+	return _requestID;
+}
+
+inline Int32 MessageHeader::responseTo() const
+{
+	return _responseTo;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_MessageHeader_INCLUDED
diff --git a/Poco/MongoDB/MongoDB.h b/Poco/MongoDB/MongoDB.h
new file mode 100644
index 0000000..8e2126f
--- /dev/null
+++ b/Poco/MongoDB/MongoDB.h
@@ -0,0 +1,64 @@
+//
+// MongoDB.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  MongoDB
+//
+// Basic definitions for the Poco MongoDB library.
+// This file must be the first file included by every other MongoDB
+// header file.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDBMongoDB_INCLUDED
+#define MongoDBMongoDB_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the MongoDB_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// MongoDB_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+
+
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(MongoDB_EXPORTS)
+		#define MongoDB_API __declspec(dllexport)
+	#else
+		#define MongoDB_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(MongoDB_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define MongoDB_API __attribute__ ((visibility ("default")))
+	#else
+		#define MongoDB_API
+	#endif
+#endif
+
+
+//
+// Automatically link MongoDB library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(MongoDB_EXPORTS)
+		#pragma comment(lib, "PocoMongoDB" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // MongoDBMongoDB_INCLUDED
diff --git a/Poco/MongoDB/ObjectId.h b/Poco/MongoDB/ObjectId.h
new file mode 100644
index 0000000..659047c
--- /dev/null
+++ b/Poco/MongoDB/ObjectId.h
@@ -0,0 +1,147 @@
+//
+// Array.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  ObjectId
+//
+// Definition of the ObjectId class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_ObjectId_INCLUDED
+#define MongoDB_ObjectId_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Element.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API ObjectId
+	/// ObjectId is a 12-byte BSON type, constructed using:
+	///
+	///   - a 4-byte timestamp,
+	///   - a 3-byte machine identifier,
+	///   - a 2-byte process id, and
+	///   - a 3-byte counter, starting with a random value.
+	///
+	/// In MongoDB, documents stored in a collection require a unique _id field that acts
+	/// as a primary key. Because ObjectIds are small, most likely unique, and fast to generate,
+	/// MongoDB uses ObjectIds as the default value for the _id field if the _id field is not
+	/// specified; i.e., the mongod adds the _id field and generates a unique ObjectId to assign
+	/// as its value.
+{
+public:
+	typedef SharedPtr<ObjectId> Ptr;
+
+	explicit ObjectId(const std::string& id);
+		/// Creates an ObjectId from a string. 
+		///
+		/// The string must contain a hexadecimal representation
+		/// of an object ID. This means a string of 24 characters.
+
+	ObjectId(const ObjectId& copy);
+		/// Creates an ObjectId by copying another one.
+
+	virtual ~ObjectId();
+		/// Destroys the ObjectId.
+
+	Timestamp timestamp() const;
+		/// Returns the timestamp which is stored in the first four bytes of the id
+
+	std::string toString(const std::string& fmt = "%02x") const;
+		/// Returns the id in string format. The fmt parameter
+		/// specifies the formatting used for individual members 
+		/// of the ID char array.
+
+private:
+	ObjectId();
+
+	static int fromHex(char c);	
+	static char fromHex(const char* c);
+	
+	unsigned char _id[12];
+
+	friend class BSONWriter;
+	friend class BSONReader;
+	friend class Document;
+};
+
+
+//
+// inlines
+//
+inline Timestamp ObjectId::timestamp() const
+{
+	int time;
+	char* T = (char *) &time;
+	T[0] = _id[3];
+	T[1] = _id[2];
+	T[2] = _id[1];
+	T[3] = _id[0];
+	return Timestamp::fromEpochTime((time_t) time);
+}
+
+
+inline int ObjectId::fromHex(char c)
+{
+	if ( '0' <= c && c <= '9' )
+		return c - '0';
+	if ( 'a' <= c && c <= 'f' )
+		return c - 'a' + 10;
+	if ( 'A' <= c && c <= 'F' )
+		return c - 'A' + 10;
+	return 0xff;
+}
+
+
+inline char ObjectId::fromHex(const char* c)
+{
+	return (char)((fromHex(c[0]) << 4 ) | fromHex(c[1]));
+}
+
+
+// BSON Embedded Document
+// spec: ObjectId
+template<>
+struct ElementTraits<ObjectId::Ptr>
+{
+	enum { TypeId = 0x07 };
+
+	static std::string toString(const ObjectId::Ptr& id,
+		int indent = 0,
+		const std::string& fmt = "%02x")
+	{
+		return id->toString(fmt);
+	}
+};
+
+
+template<>
+inline void BSONReader::read<ObjectId::Ptr>(ObjectId::Ptr& to)
+{
+	_reader.readRaw((char*) to->_id, 12);
+}
+
+
+template<>
+inline void BSONWriter::write<ObjectId::Ptr>(ObjectId::Ptr& from)
+{
+	_writer.writeRaw((char*) from->_id, 12);
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_ObjectId_INCLUDED
diff --git a/Poco/MongoDB/PoolableConnectionFactory.h b/Poco/MongoDB/PoolableConnectionFactory.h
new file mode 100644
index 0000000..a723eb1
--- /dev/null
+++ b/Poco/MongoDB/PoolableConnectionFactory.h
@@ -0,0 +1,128 @@
+//
+// PoolableConnectionFactory.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  PoolableConnectionFactory
+//
+// Definition of the PoolableConnectionFactory class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_PoolableConnectionFactory_INCLUDED
+#define MongoDB_PoolableConnectionFactory_INCLUDED
+
+
+#include "Poco/MongoDB/Connection.h"
+#include "Poco/ObjectPool.h"
+
+
+namespace Poco {
+
+
+template<>
+class PoolableObjectFactory<MongoDB::Connection, MongoDB::Connection::Ptr>
+	/// PoolableObjectFactory specialisation for Connection. New connections
+	/// are created with the given address or URI.
+	///
+	/// If a Connection::SocketFactory is given, it must live for the entire
+	/// lifetime of the PoolableObjectFactory.
+{
+public:
+	PoolableObjectFactory(Net::SocketAddress& address):
+		_address(address),
+		_pSocketFactory(0)
+	{
+	}
+
+	PoolableObjectFactory(const std::string& address):
+		_address(address),
+		_pSocketFactory(0)
+	{
+	}
+
+	PoolableObjectFactory(const std::string& uri, MongoDB::Connection::SocketFactory& socketFactory):
+		_uri(uri),
+		_pSocketFactory(&socketFactory)
+	{
+	}
+
+	MongoDB::Connection::Ptr createObject()
+	{
+		if (_pSocketFactory)
+			return new MongoDB::Connection(_uri, *_pSocketFactory);
+		else
+			return new MongoDB::Connection(_address);
+	}
+
+	bool validateObject(MongoDB::Connection::Ptr pObject)
+	{
+		return true;
+	}
+
+	void activateObject(MongoDB::Connection::Ptr pObject)
+	{
+	}
+
+	void deactivateObject(MongoDB::Connection::Ptr pObject)
+	{
+	}
+
+	void destroyObject(MongoDB::Connection::Ptr pObject)
+	{
+	}
+
+private:
+	Net::SocketAddress _address;
+	std::string _uri;
+	MongoDB::Connection::SocketFactory* _pSocketFactory;
+};
+
+
+namespace MongoDB {
+
+
+class PooledConnection
+	/// Helper class for borrowing and returning a connection automatically from a pool.
+{
+public:
+	PooledConnection(Poco::ObjectPool<Connection, Connection::Ptr>& pool) : _pool(pool)
+	{
+		_connection = _pool.borrowObject();
+	}
+
+	virtual ~PooledConnection()
+	{
+		try
+		{
+			if (_connection)
+			{
+				_pool.returnObject(_connection);
+			}
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	operator Connection::Ptr ()
+	{
+		return _connection;
+	}
+
+private:
+	Poco::ObjectPool<Connection, Connection::Ptr>& _pool;
+	Connection::Ptr _connection;
+};
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_PoolableConnectionFactory_INCLUDED
diff --git a/Poco/MongoDB/QueryRequest.h b/Poco/MongoDB/QueryRequest.h
new file mode 100644
index 0000000..4108287
--- /dev/null
+++ b/Poco/MongoDB/QueryRequest.h
@@ -0,0 +1,187 @@
+//
+// QueryRequest.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  QueryRequest
+//
+// Definition of the QueryRequest class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_QueryRequest_INCLUDED
+#define MongoDB_QueryRequest_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/RequestMessage.h"
+#include "Poco/MongoDB/Document.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API QueryRequest: public RequestMessage
+	/// A request to query documents in a MongoDB database
+	/// using an OP_QUERY request.
+{
+public:
+	enum Flags
+	{
+		QUERY_DEFAULT = 0, 
+			/// Do not set any flags.
+	
+		QUERY_TAILABLE_CURSOR = 2, 
+			/// Tailable means cursor is not closed when the last data is retrieved. 
+			/// Rather, the cursor marks the final object’s position. 
+			/// You can resume using the cursor later, from where it was located, 
+			/// if more data were received. Like any "latent cursor", the cursor may 
+			/// become invalid at some point (CursorNotFound) – for example if the final 
+			/// object it references were deleted.
+	
+		QUERY_SLAVE_OK = 4, 
+			/// Allow query of replica slave. Normally these return an error except 
+			/// for namespace "local".
+			
+		// QUERY_OPLOG_REPLAY = 8 (internal replication use only - drivers should not implement)
+		
+		QUERY_NO_CURSOR_TIMEOUT = 16,
+			/// The server normally times out idle cursors after an inactivity period 
+			/// (10 minutes) to prevent excess memory use. Set this option to prevent that.
+	
+		QUERY_AWAIT_DATA = 32,
+			/// Use with QUERY_TAILABLECURSOR. If we are at the end of the data, block for 
+			/// a while rather than returning no data. After a timeout period, we do 
+			/// return as normal.
+
+		QUERY_EXHAUST = 64,
+			/// Stream the data down full blast in multiple "more" packages, on the 
+			/// assumption that the client will fully read all data queried. 
+			/// Faster when you are pulling a lot of data and know you want to pull 
+			/// it all down. 
+			/// Note: the client is not allowed to not read all the data unless it 
+			/// closes the connection.
+
+		QUERY_PARTIAL = 128
+			/// Get partial results from a mongos if some shards are down 
+			/// (instead of throwing an error).
+	};
+
+	QueryRequest(const std::string& collectionName, Flags flags = QUERY_DEFAULT);
+		/// Creates a QueryRequest.
+		///
+		/// The full collection name is the concatenation of the database 
+		/// name with the collection name, using a "." for the concatenation. For example, 
+		/// for the database "foo" and the collection "bar", the full collection name is 
+		/// "foo.bar".
+
+	virtual ~QueryRequest();
+		/// Destroys the QueryRequest.
+
+	Flags getFlags() const;
+		/// Returns the flags.
+
+	void setFlags(Flags flag);
+		/// Set the flags.
+
+	std::string fullCollectionName() const;
+		/// Returns the <db>.<collection> used for this query.
+
+	Int32 getNumberToSkip() const;
+		/// Returns the number of documents to skip.
+
+	void setNumberToSkip(Int32 n);
+		/// Sets the number of documents to skip.
+
+	Int32 getNumberToReturn() const;
+		/// Returns the number of documents to return.
+
+	void setNumberToReturn(Int32 n);
+		/// Sets the number of documents to return (limit).
+
+	Document& selector();
+		/// Returns the selector document.
+
+	Document& returnFieldSelector();
+		/// Returns the field selector document.
+
+protected:
+	void buildRequest(BinaryWriter& writer);
+
+private:
+	Flags       _flags;
+	std::string _fullCollectionName;
+	Int32       _numberToSkip;
+	Int32       _numberToReturn;
+	Document    _selector;
+	Document    _returnFieldSelector;
+};
+
+
+//
+// inlines
+//
+inline QueryRequest::Flags QueryRequest::getFlags() const
+{
+	return _flags;
+}
+
+
+inline void QueryRequest::setFlags(QueryRequest::Flags flags)
+{
+	_flags = flags;
+}
+
+
+inline std::string QueryRequest::fullCollectionName() const
+{
+	return _fullCollectionName;
+}
+
+
+inline Document& QueryRequest::selector()
+{
+	return _selector;
+}
+
+
+inline Document& QueryRequest::returnFieldSelector()
+{
+	return _returnFieldSelector;
+}
+
+
+inline Int32 QueryRequest::getNumberToSkip() const
+{
+	return _numberToSkip;
+}
+
+
+inline void QueryRequest::setNumberToSkip(Int32 n)
+{
+	_numberToSkip = n;
+}
+
+
+inline Int32 QueryRequest::getNumberToReturn() const
+{
+	return _numberToReturn;
+}
+
+
+inline void QueryRequest::setNumberToReturn(Int32 n)
+{
+	_numberToReturn = n;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_QueryRequest_INCLUDED
diff --git a/Poco/MongoDB/RegularExpression.h b/Poco/MongoDB/RegularExpression.h
new file mode 100644
index 0000000..49ef3b0
--- /dev/null
+++ b/Poco/MongoDB/RegularExpression.h
@@ -0,0 +1,129 @@
+//
+// RegularExpression.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  RegularExpression
+//
+// Definition of the RegularExpression class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_RegularExpression_INCLUDED
+#define MongoDB_RegularExpression_INCLUDED
+
+
+#include "Poco/RegularExpression.h"
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Element.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API RegularExpression
+	/// Represents a regular expression in BSON format.
+{
+public:
+	typedef SharedPtr<RegularExpression> Ptr;
+
+	RegularExpression();
+		/// Creates an empty RegularExpression.
+
+	RegularExpression(const std::string& pattern, const std::string& options);
+		/// Creates a RegularExpression using the given pattern and options.
+
+	virtual ~RegularExpression();
+		/// Destroys the RegularExpression.
+
+	SharedPtr<Poco::RegularExpression> createRE() const;
+		/// Tries to create a Poco::RegularExpression from the MongoDB regular expression.
+
+	std::string getOptions() const;
+		/// Returns the options string.
+
+	void setOptions(const std::string& options);
+		/// Sets the options string.
+
+	std::string getPattern() const;
+		/// Returns the pattern.
+
+	void setPattern(const std::string& pattern);
+		/// Sets the pattern.
+
+private:
+	std::string _pattern;
+	std::string _options;
+};
+
+
+///
+/// inlines
+///
+inline std::string RegularExpression::getPattern() const
+{
+	return _pattern;
+}
+
+
+inline void RegularExpression::setPattern(const std::string& pattern)
+{
+	_pattern = pattern;
+}
+
+
+inline std::string RegularExpression::getOptions() const
+{
+	return _options;
+}
+
+
+inline void RegularExpression::setOptions(const std::string& options)
+{
+	_options = options;
+}
+
+
+// BSON Regex
+// spec: cstring cstring
+template<>
+struct ElementTraits<RegularExpression::Ptr>
+{
+	enum { TypeId = 0x0B };
+
+	static std::string toString(const RegularExpression::Ptr& value, int indent = 0)
+	{
+		//TODO
+		return "RE: not implemented yet";
+	}
+};
+
+
+template<>
+inline void BSONReader::read<RegularExpression::Ptr>(RegularExpression::Ptr& to)
+{
+	std::string pattern = readCString();
+	std::string options = readCString();
+
+	to = new RegularExpression(pattern, options);
+}
+
+
+template<>
+inline void BSONWriter::write<RegularExpression::Ptr>(RegularExpression::Ptr& from)
+{
+	writeCString(from->getPattern());
+	writeCString(from->getOptions());
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_RegularExpression_INCLUDED
diff --git a/Poco/MongoDB/ReplicaSet.h b/Poco/MongoDB/ReplicaSet.h
new file mode 100644
index 0000000..1f7cd93
--- /dev/null
+++ b/Poco/MongoDB/ReplicaSet.h
@@ -0,0 +1,58 @@
+//
+// ReplicaSet.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  ReplicaSet
+//
+// Definition of the ReplicaSet class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_ReplicaSet_INCLUDED
+#define MongoDB_ReplicaSet_INCLUDED
+
+
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/MongoDB/Connection.h"
+#include <vector>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API ReplicaSet
+	/// Class for working with a MongoDB replica set.
+{
+public:
+	explicit ReplicaSet(const std::vector<Net::SocketAddress>& addresses);
+		/// Creates the ReplicaSet using the given server addresses.
+
+	virtual ~ReplicaSet();
+		/// Destroys the ReplicaSet.
+
+	Connection::Ptr findMaster();
+		/// Tries to find the master MongoDB instance from the addresses
+		/// passed to the constructor.
+		///
+		/// Returns the Connection to the master, or null if no master
+		/// instance was found.
+
+protected:
+	Connection::Ptr isMaster(const Net::SocketAddress& host);
+
+private:
+	std::vector<Net::SocketAddress> _addresses;
+};
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_ReplicaSet_INCLUDED
diff --git a/Poco/MongoDB/RequestMessage.h b/Poco/MongoDB/RequestMessage.h
new file mode 100644
index 0000000..9ebb4a5
--- /dev/null
+++ b/Poco/MongoDB/RequestMessage.h
@@ -0,0 +1,51 @@
+//
+// RequestMessage.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  RequestMessage
+//
+// Definition of the RequestMessage class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_RequestMessage_INCLUDED
+#define MongoDB_RequestMessage_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Message.h"
+#include <ostream>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API RequestMessage: public Message
+	/// Base class for a request sent to the MongoDB server.
+{
+public:
+	explicit RequestMessage(MessageHeader::OpCode opcode);
+		/// Creates a RequestMessage using the given opcode.
+
+	virtual ~RequestMessage();
+		/// Destroys the RequestMessage.
+
+	void send(std::ostream& ostr);
+		/// Writes the request to stream.
+
+protected:
+	virtual void buildRequest(BinaryWriter& ss) = 0;
+};
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_RequestMessage_INCLUDED
diff --git a/Poco/MongoDB/ResponseMessage.h b/Poco/MongoDB/ResponseMessage.h
new file mode 100644
index 0000000..dd9ecd2
--- /dev/null
+++ b/Poco/MongoDB/ResponseMessage.h
@@ -0,0 +1,108 @@
+//
+// ResponseMessage.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  ResponseMessage
+//
+// Definition of the ResponseMessage class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_ResponseMessage_INCLUDED
+#define MongoDB_ResponseMessage_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/Message.h"
+#include "Poco/MongoDB/Document.h"
+#include <istream>
+#include <cstdlib>
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class MongoDB_API ResponseMessage: public Message
+	/// This class represents a response (OP_REPLY) from MongoDB.
+{
+public:
+	ResponseMessage();
+		/// Creates an empty ResponseMessage.
+
+	virtual ~ResponseMessage();
+		/// Destroys the ResponseMessage.
+
+	Int64 cursorID() const;
+		/// Returns the cursor ID.
+
+	void clear();
+		/// Clears the response.
+
+	std::size_t count() const;
+		/// Returns the number of documents in the response.
+
+	Document::Vector& documents();
+		/// Returns a vector containing the received documents.
+
+	bool empty() const;
+		/// Returns true if the response does not contain any documents.
+
+	bool hasDocuments() const;
+		/// Returns true if there is at least one document in the response.
+
+	void read(std::istream& istr);
+		/// Reads the response from the stream.
+
+private:
+	Int32 _responseFlags;
+	Int64 _cursorID;
+	Int32 _startingFrom;
+	Int32 _numberReturned;
+	Document::Vector _documents;
+};
+
+
+//
+// inlines
+//
+inline std::size_t ResponseMessage::count() const
+{
+	return _documents.size();
+}
+
+
+inline bool ResponseMessage::empty() const
+{
+	return _documents.size() == 0;
+}
+
+
+inline Int64 ResponseMessage::cursorID() const
+{
+	return _cursorID;
+}
+
+
+inline Document::Vector& ResponseMessage::documents()
+{
+	return _documents;
+}
+
+
+inline bool ResponseMessage::hasDocuments() const
+{
+	return _documents.size() > 0;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_ResponseMessage_INCLUDED
diff --git a/Poco/MongoDB/UpdateRequest.h b/Poco/MongoDB/UpdateRequest.h
new file mode 100644
index 0000000..0aa14bc
--- /dev/null
+++ b/Poco/MongoDB/UpdateRequest.h
@@ -0,0 +1,114 @@
+//
+// UpdateRequest.h
+//
+// Library: MongoDB
+// Package: MongoDB
+// Module:  UpdateRequest
+//
+// Definition of the UpdateRequest class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef MongoDB_UpdateRequest_INCLUDED
+#define MongoDB_UpdateRequest_INCLUDED
+
+
+#include "Poco/MongoDB/MongoDB.h"
+#include "Poco/MongoDB/RequestMessage.h"
+#include "Poco/MongoDB/Document.h"
+
+
+namespace Poco {
+namespace MongoDB {
+
+
+class UpdateRequest: public RequestMessage
+	/// This request is used to update a document in a database
+	/// using the OP_UPDATE client request. 
+{
+public:
+	enum Flags
+	{
+		UPDATE_DEFAULT = 0,
+			/// If set, the database will insert the supplied object into the
+			/// collection if no matching document is found.
+			
+		UPDATE_UPSERT = 1,
+			/// If set, the database will update all matching objects in the collection.
+			/// Otherwise only updates first matching doc.
+
+		UPDATE_MULTIUPDATE = 2
+			/// If set to, updates multiple documents that meet the query criteria.
+			/// Otherwise only updates one document.
+	};
+
+	UpdateRequest(const std::string& collectionName, Flags flags = UPDATE_DEFAULT);
+		/// Creates the UpdateRequest.
+		///
+		/// The full collection name is the concatenation of the database 
+		/// name with the collection name, using a "." for the concatenation. For example, 
+		/// for the database "foo" and the collection "bar", the full collection name is 
+		/// "foo.bar".
+
+	virtual ~UpdateRequest();
+		/// Destroys the UpdateRequest.
+
+	Document& selector();
+		/// Returns the selector document.
+
+	Document& update();
+		/// Returns the document to update.
+
+	Flags flags() const;
+		/// Returns the flags
+
+	void flags(Flags flags);
+		/// Sets the flags
+
+protected:
+	void buildRequest(BinaryWriter& writer);
+
+private:
+	Flags       _flags;
+	std::string _fullCollectionName;
+	Document    _selector;
+	Document    _update;
+};
+
+
+//
+// inlines
+//
+inline UpdateRequest::Flags UpdateRequest::flags() const
+{
+	return _flags;
+}
+
+
+inline void UpdateRequest::flags(UpdateRequest::Flags flags)
+{
+	_flags = flags;
+}
+
+
+inline Document& UpdateRequest::selector()
+{
+	return _selector;
+}
+
+
+inline Document& UpdateRequest::update()
+{
+	return _update;
+}
+
+
+} } // namespace Poco::MongoDB
+
+
+#endif // MongoDB_UpdateRequest_INCLUDED
diff --git a/Poco/Mutex.h b/Poco/Mutex.h
new file mode 100644
index 0000000..64d0efc
--- /dev/null
+++ b/Poco/Mutex.h
@@ -0,0 +1,270 @@
+//
+// Mutex.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the Mutex and FastMutex classes.
+//
+// Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Mutex_INCLUDED
+#define Foundation_Mutex_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/ScopedLock.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#if defined(_WIN32_WCE)
+#include "Poco/Mutex_WINCE.h"
+#else
+#include "Poco/Mutex_WIN32.h"
+#endif
+#elif defined(POCO_VXWORKS)
+#include "Poco/Mutex_VX.h"
+#else
+#include "Poco/Mutex_POSIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API Mutex: private MutexImpl
+	/// A Mutex (mutual exclusion) is a synchronization 
+	/// mechanism used to control access to a shared resource
+	/// in a concurrent (multithreaded) scenario.
+	/// Mutexes are recursive, that is, the same mutex can be 
+	/// locked multiple times by the same thread (but, of course,
+	/// not by other threads).
+	/// Using the ScopedLock class is the preferred way to automatically
+	/// lock and unlock a mutex.
+{
+public:
+	typedef Poco::ScopedLock<Mutex> ScopedLock;
+	
+	Mutex();
+		/// creates the Mutex.
+		
+	~Mutex();
+		/// destroys the Mutex.
+
+	void lock();
+		/// Locks the mutex. Blocks if the mutex
+		/// is held by another thread.
+		
+	void lock(long milliseconds);
+		/// Locks the mutex. Blocks up to the given number of milliseconds
+		/// if the mutex is held by another thread. Throws a TimeoutException
+		/// if the mutex can not be locked within the given timeout.
+		///
+		/// Performance Note: On most platforms (including Windows), this member function is 
+		/// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep().
+		/// On POSIX platforms that support pthread_mutex_timedlock(), this is used.
+
+	bool tryLock();
+		/// Tries to lock the mutex. Returns false immediately
+		/// if the mutex is already held by another thread.
+		/// Returns true if the mutex was successfully locked.
+
+	bool tryLock(long milliseconds);
+		/// Locks the mutex. Blocks up to the given number of milliseconds
+		/// if the mutex is held by another thread.
+		/// Returns true if the mutex was successfully locked.
+		///
+		/// Performance Note: On most platforms (including Windows), this member function is 
+		/// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep().
+		/// On POSIX platforms that support pthread_mutex_timedlock(), this is used.
+
+	void unlock();
+		/// Unlocks the mutex so that it can be acquired by
+		/// other threads.
+	
+private:
+	Mutex(const Mutex&);
+	Mutex& operator = (const Mutex&);
+};
+
+
+class Foundation_API FastMutex: private FastMutexImpl
+	/// A FastMutex (mutual exclusion) is similar to a Mutex.
+	/// Unlike a Mutex, however, a FastMutex is not recursive,
+	/// which means that a deadlock will occur if the same
+	/// thread tries to lock a mutex it has already locked again.
+	/// Locking a FastMutex is faster than locking a recursive Mutex.
+	/// Using the ScopedLock class is the preferred way to automatically
+	/// lock and unlock a mutex.
+{
+public:
+	typedef Poco::ScopedLock<FastMutex> ScopedLock;
+
+	FastMutex();
+		/// creates the Mutex.
+		
+	~FastMutex();
+		/// destroys the Mutex.
+
+	void lock();
+		/// Locks the mutex. Blocks if the mutex
+		/// is held by another thread.
+
+	void lock(long milliseconds);
+		/// Locks the mutex. Blocks up to the given number of milliseconds
+		/// if the mutex is held by another thread. Throws a TimeoutException
+		/// if the mutex can not be locked within the given timeout.
+		///
+		/// Performance Note: On most platforms (including Windows), this member function is 
+		/// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep().
+		/// On POSIX platforms that support pthread_mutex_timedlock(), this is used.
+
+	bool tryLock();
+		/// Tries to lock the mutex. Returns false immediately
+		/// if the mutex is already held by another thread.
+		/// Returns true if the mutex was successfully locked.
+
+	bool tryLock(long milliseconds);
+		/// Locks the mutex. Blocks up to the given number of milliseconds
+		/// if the mutex is held by another thread.
+		/// Returns true if the mutex was successfully locked.
+		///
+		/// Performance Note: On most platforms (including Windows), this member function is 
+		/// implemented using a loop calling (the equivalent of) tryLock() and Thread::sleep().
+		/// On POSIX platforms that support pthread_mutex_timedlock(), this is used.
+
+	void unlock();
+		/// Unlocks the mutex so that it can be acquired by
+		/// other threads.
+	
+private:
+	FastMutex(const FastMutex&);
+	FastMutex& operator = (const FastMutex&);
+};
+
+
+class Foundation_API NullMutex
+	/// A NullMutex is an empty mutex implementation
+	/// which performs no locking at all. Useful in policy driven design
+	/// where the type of mutex used can be now a template parameter allowing the user to switch
+	/// between thread-safe and not thread-safe depending on his need
+	/// Works with the ScopedLock class
+{
+public:
+	typedef Poco::ScopedLock<NullMutex> ScopedLock;
+	
+	NullMutex()
+		/// Creates the NullMutex.
+	{
+	}
+		
+	~NullMutex()
+		/// Destroys the NullMutex.
+	{
+	}
+
+	void lock()
+		/// Does nothing.
+	{
+	}
+		
+	void lock(long)
+		/// Does nothing.
+	{
+	}
+
+	bool tryLock()
+		/// Does nothing and always returns true.
+	{
+		return true;
+	}
+
+	bool tryLock(long)
+		/// Does nothing and always returns true.
+	{
+		return true;
+	}
+
+	void unlock()
+		/// Does nothing.
+	{
+	}
+};
+
+
+//
+// inlines
+//
+inline void Mutex::lock()
+{
+	lockImpl();
+}
+
+
+inline void Mutex::lock(long milliseconds)
+{
+	if (!tryLockImpl(milliseconds))
+		throw TimeoutException();
+}
+
+
+inline bool Mutex::tryLock()
+{
+	return tryLockImpl();
+}
+
+
+inline bool Mutex::tryLock(long milliseconds)
+{
+	return tryLockImpl(milliseconds);
+}
+
+
+inline void Mutex::unlock()
+{
+	unlockImpl();
+}
+
+
+inline void FastMutex::lock()
+{
+	lockImpl();
+}
+
+
+inline void FastMutex::lock(long milliseconds)
+{
+	if (!tryLockImpl(milliseconds))
+		throw TimeoutException();
+}
+
+
+inline bool FastMutex::tryLock()
+{
+	return tryLockImpl();
+}
+
+
+inline bool FastMutex::tryLock(long milliseconds)
+{
+	return tryLockImpl(milliseconds);
+}
+
+
+inline void FastMutex::unlock()
+{
+	unlockImpl();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Mutex_INCLUDED
diff --git a/Poco/Mutex_POSIX.h b/Poco/Mutex_POSIX.h
new file mode 100644
index 0000000..12f61dd
--- /dev/null
+++ b/Poco/Mutex_POSIX.h
@@ -0,0 +1,86 @@
+//
+// Mutex_POSIX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the MutexImpl and FastMutexImpl classes for POSIX Threads.
+//
+// Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Mutex_POSIX_INCLUDED
+#define Foundation_Mutex_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <pthread.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API MutexImpl
+{
+protected:
+	MutexImpl();
+	MutexImpl(bool fast);
+	~MutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	bool tryLockImpl(long milliseconds);
+	void unlockImpl();
+	
+private:
+	pthread_mutex_t _mutex;
+};
+
+
+class Foundation_API FastMutexImpl: public MutexImpl
+{
+protected:
+	FastMutexImpl();
+	~FastMutexImpl();
+};
+
+
+//
+// inlines
+//
+inline void MutexImpl::lockImpl()
+{
+	if (pthread_mutex_lock(&_mutex)) 
+		throw SystemException("cannot lock mutex");
+}
+
+
+inline bool MutexImpl::tryLockImpl()
+{
+	int rc = pthread_mutex_trylock(&_mutex);
+	if (rc == 0)
+		return true;
+	else if (rc == EBUSY)
+		return false;
+	else
+		throw SystemException("cannot lock mutex");
+}
+
+
+inline void MutexImpl::unlockImpl()
+{
+	if (pthread_mutex_unlock(&_mutex))
+		throw SystemException("cannot unlock mutex");
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Mutex_POSIX_INCLUDED
diff --git a/Poco/Mutex_VX.h b/Poco/Mutex_VX.h
new file mode 100644
index 0000000..f0f43ea
--- /dev/null
+++ b/Poco/Mutex_VX.h
@@ -0,0 +1,80 @@
+//
+// Mutex_VX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the MutexImpl and FastMutexImpl classes for VxWorks.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Mutex_VX_INCLUDED
+#define Foundation_Mutex_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <semLib.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API MutexImpl
+{
+protected:
+	MutexImpl();
+	MutexImpl(bool fast);
+	~MutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	bool tryLockImpl(long milliseconds);
+	void unlockImpl();
+	
+private:
+	SEM_ID _sem;
+};
+
+
+class Foundation_API FastMutexImpl: public MutexImpl
+{
+protected:
+	FastMutexImpl();
+	~FastMutexImpl();
+};
+
+
+//
+// inlines
+//
+inline void MutexImpl::lockImpl()
+{
+	if (semTake(_sem, WAIT_FOREVER) != OK)
+		throw SystemException("cannot lock mutex");
+}
+
+
+inline bool MutexImpl::tryLockImpl()
+{
+	return semTake(_sem, NO_WAIT) == OK;
+}
+
+
+inline void MutexImpl::unlockImpl()
+{
+	if (semGive(_sem) != OK)
+		throw SystemException("cannot unlock mutex");
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Mutex_VX_INCLUDED
diff --git a/Poco/Mutex_WIN32.h b/Poco/Mutex_WIN32.h
new file mode 100644
index 0000000..8e18c52
--- /dev/null
+++ b/Poco/Mutex_WIN32.h
@@ -0,0 +1,85 @@
+//
+// Mutex_WIN32.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the MutexImpl and FastMutexImpl classes for WIN32.
+//
+// Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Mutex_WIN32_INCLUDED
+#define Foundation_Mutex_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API MutexImpl
+{
+protected:
+	MutexImpl();
+	~MutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	bool tryLockImpl(long milliseconds);
+	void unlockImpl();
+	
+private:
+	CRITICAL_SECTION _cs;
+};
+
+
+typedef MutexImpl FastMutexImpl;
+
+
+//
+// inlines
+//
+inline void MutexImpl::lockImpl()
+{
+	try
+	{
+		EnterCriticalSection(&_cs);
+	}
+	catch (...)
+	{
+		throw SystemException("cannot lock mutex");
+	}
+}
+
+
+inline bool MutexImpl::tryLockImpl()
+{
+	try
+	{
+		return TryEnterCriticalSection(&_cs) != 0;
+	}
+	catch (...)
+	{
+	}
+	throw SystemException("cannot lock mutex");
+}
+
+
+inline void MutexImpl::unlockImpl()
+{
+	LeaveCriticalSection(&_cs);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Mutex_WIN32_INCLUDED
diff --git a/Poco/Mutex_WINCE.h b/Poco/Mutex_WINCE.h
new file mode 100644
index 0000000..2720068
--- /dev/null
+++ b/Poco/Mutex_WINCE.h
@@ -0,0 +1,50 @@
+//
+// Mutex_WIN32.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the MutexImpl and FastMutexImpl classes for WIN32.
+//
+// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Mutex_WINCE_INCLUDED
+#define Foundation_Mutex_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API MutexImpl
+{
+protected:
+	MutexImpl();
+	~MutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	bool tryLockImpl(long milliseconds);
+	void unlockImpl();
+	
+private:
+	HANDLE _mutex;
+};
+
+
+typedef MutexImpl FastMutexImpl;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Mutex_WINCE_INCLUDED
diff --git a/Poco/NObserver.h b/Poco/NObserver.h
new file mode 100644
index 0000000..8b5106c
--- /dev/null
+++ b/Poco/NObserver.h
@@ -0,0 +1,126 @@
+//
+// NObserver.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  NotificationCenter
+//
+// Definition of the NObserver class template.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NObserver_INCLUDED
+#define Foundation_NObserver_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractObserver.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class C, class N>
+class NObserver: public AbstractObserver
+	/// This template class implements an adapter that sits between
+	/// a NotificationCenter and an object receiving notifications
+	/// from it. It is quite similar in concept to the 
+	/// RunnableAdapter, but provides some NotificationCenter
+	/// specific additional methods.
+	/// See the NotificationCenter class for information on how
+	/// to use this template class.
+	///
+	/// This class template is quite similar to the Observer class
+	/// template. The only difference is that the NObserver
+	/// expects the callback function to accept a const AutoPtr& 
+	/// instead of a plain pointer as argument, thus simplifying memory
+	/// management.
+{
+public:
+	typedef AutoPtr<N> NotificationPtr;
+	typedef void (C::*Callback)(const NotificationPtr&);
+
+	NObserver(C& object, Callback method): 
+		_pObject(&object), 
+		_method(method)
+	{
+	}
+	
+	NObserver(const NObserver& observer):
+		AbstractObserver(observer),
+		_pObject(observer._pObject), 
+		_method(observer._method)
+	{
+	}
+	
+	~NObserver()
+	{
+	}
+	
+	NObserver& operator = (const NObserver& observer)
+	{
+		if (&observer != this)
+		{
+			_pObject = observer._pObject;
+			_method  = observer._method;
+		}
+		return *this;
+	}
+	
+	void notify(Notification* pNf) const
+	{
+		Poco::Mutex::ScopedLock lock(_mutex);
+
+		if (_pObject)
+		{
+			N* pCastNf = dynamic_cast<N*>(pNf);
+			if (pCastNf)
+			{
+				NotificationPtr ptr(pCastNf, true);
+				(_pObject->*_method)(ptr);
+			}
+		}
+	}
+	
+	bool equals(const AbstractObserver& abstractObserver) const
+	{
+		const NObserver* pObs = dynamic_cast<const NObserver*>(&abstractObserver);
+		return pObs && pObs->_pObject == _pObject && pObs->_method == _method;
+	}
+
+	bool accepts(Notification* pNf) const
+	{
+		return dynamic_cast<N*>(pNf) != 0;
+	}
+	
+	AbstractObserver* clone() const
+	{
+		return new NObserver(*this);
+	}
+	
+	void disable()
+	{
+		Poco::Mutex::ScopedLock lock(_mutex);
+		
+		_pObject = 0;
+	}
+
+private:
+	NObserver();
+
+	C*       _pObject;
+	Callback _method;
+	mutable Poco::Mutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NObserver_INCLUDED
diff --git a/Poco/NamedEvent.h b/Poco/NamedEvent.h
new file mode 100644
index 0000000..b473be1
--- /dev/null
+++ b/Poco/NamedEvent.h
@@ -0,0 +1,96 @@
+//
+// NamedEvent.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedEvent
+//
+// Definition of the NamedEvent class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedEvent_INCLUDED
+#define Foundation_NamedEvent_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+#include "Poco/NamedEvent_WIN32U.h"
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/NamedEvent_WIN32.h"
+#elif POCO_OS == POCO_OS_ANDROID
+#include "Poco/NamedEvent_Android.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/NamedEvent_UNIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API NamedEvent: public NamedEventImpl
+	/// An NamedEvent is a global synchronization object
+	/// that allows one process or thread to signal an
+	/// other process or thread that a certain event
+	/// has happened.
+	///
+	/// Unlike an Event, which itself is the unit of synchronization,
+	/// a NamedEvent refers to a named operating system resource being the
+	/// unit of synchronization.
+	/// In other words, there can be multiple instances of NamedEvent referring
+	/// to the same actual synchronization object.
+	///
+	/// NamedEvents are always autoresetting.
+	///
+	/// There should not be more than one instance of NamedEvent for
+	/// a given name in a process. Otherwise, the instances may
+	/// interfere with each other.
+{
+public:
+	NamedEvent(const std::string& name);
+		/// Creates the event.
+
+	~NamedEvent();
+		/// Destroys the event.
+
+	void set();
+		/// Signals the event.
+		/// The one thread or process waiting for the event
+		/// can resume execution.
+
+	void wait();
+		/// Waits for the event to become signalled.
+
+private:
+	NamedEvent();
+	NamedEvent(const NamedEvent&);
+	NamedEvent& operator = (const NamedEvent&);
+};
+
+
+//
+// inlines
+//
+inline void NamedEvent::set()
+{
+	setImpl();
+}
+
+
+inline void NamedEvent::wait()
+{
+	waitImpl();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedEvent_INCLUDED
diff --git a/Poco/NamedEvent_Android.h b/Poco/NamedEvent_Android.h
new file mode 100644
index 0000000..910c8a4
--- /dev/null
+++ b/Poco/NamedEvent_Android.h
@@ -0,0 +1,40 @@
+//
+// NamedEvent_Android.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedEvent
+//
+// Definition of the NamedEventImpl class for Android.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedEvent_Android_INCLUDED
+#define Foundation_NamedEvent_Android_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NamedEventImpl
+{
+protected:
+	NamedEventImpl(const std::string& name);	
+	~NamedEventImpl();
+	void setImpl();
+	void waitImpl();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedEvent_Android_INCLUDED
diff --git a/Poco/NamedEvent_UNIX.h b/Poco/NamedEvent_UNIX.h
new file mode 100644
index 0000000..e593790
--- /dev/null
+++ b/Poco/NamedEvent_UNIX.h
@@ -0,0 +1,53 @@
+//
+// NamedEvent_UNIX.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedEvent
+//
+// Definition of the NamedEventImpl class for Unix.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedEvent_UNIX_INCLUDED
+#define Foundation_NamedEvent_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX)
+#include <semaphore.h>
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API NamedEventImpl
+{
+protected:
+	NamedEventImpl(const std::string& name);	
+	~NamedEventImpl();
+	void setImpl();
+	void waitImpl();
+	
+private:
+	std::string getFileName();
+
+	std::string _name;
+#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX)
+	sem_t* _sem;
+#else
+	int _semid;  // semaphore id
+#endif
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedEvent_UNIX_INCLUDED
diff --git a/Poco/NamedEvent_WIN32.h b/Poco/NamedEvent_WIN32.h
new file mode 100644
index 0000000..4d09f90
--- /dev/null
+++ b/Poco/NamedEvent_WIN32.h
@@ -0,0 +1,45 @@
+//
+// NamedEvent_WIN32.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedEvent
+//
+// Definition of the NamedEventImpl class for Windows.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedEvent_WIN32_INCLUDED
+#define Foundation_NamedEvent_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NamedEventImpl
+{
+protected:
+	NamedEventImpl(const std::string& name);	
+	~NamedEventImpl();
+	void setImpl();
+	void waitImpl();
+	
+private:
+	std::string _name;
+	HANDLE      _event;	
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedEvent_WIN32_INCLUDED
diff --git a/Poco/NamedEvent_WIN32U.h b/Poco/NamedEvent_WIN32U.h
new file mode 100644
index 0000000..b2936c4
--- /dev/null
+++ b/Poco/NamedEvent_WIN32U.h
@@ -0,0 +1,46 @@
+//
+// NamedEvent_WIN32U.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedEvent
+//
+// Definition of the NamedEventImpl class for Windows.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedEvent_WIN32U_INCLUDED
+#define Foundation_NamedEvent_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NamedEventImpl
+{
+protected:
+	NamedEventImpl(const std::string& name);	
+	~NamedEventImpl();
+	void setImpl();
+	void waitImpl();
+	
+private:
+	std::string  _name;
+	std::wstring _uname;
+	HANDLE      _event;	
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedEvent_WIN32U_INCLUDED
diff --git a/Poco/NamedMutex.h b/Poco/NamedMutex.h
new file mode 100644
index 0000000..421f018
--- /dev/null
+++ b/Poco/NamedMutex.h
@@ -0,0 +1,110 @@
+//
+// NamedMutex.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedMutex
+//
+// Definition of the NamedMutex class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedMutex_INCLUDED
+#define Foundation_NamedMutex_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/ScopedLock.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+#include "Poco/NamedMutex_WIN32U.h"
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/NamedMutex_WIN32.h"
+#elif POCO_OS == POCO_OS_ANDROID
+#include "Poco/NamedMutex_Android.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/NamedMutex_UNIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API NamedMutex: private NamedMutexImpl
+	/// A NamedMutex (mutual exclusion) is a global synchronization
+	/// mechanism used to control access to a shared resource
+	/// in a concurrent (multi process) scenario.
+	/// Using the ScopedLock class is the preferred way to automatically
+	/// lock and unlock a mutex.
+	///
+	/// Unlike a Mutex or a FastMutex, which itself is the unit of synchronization,
+	/// a NamedMutex refers to a named operating system resource being the
+	/// unit of synchronization.
+	/// In other words, there can be multiple instances of NamedMutex referring
+	/// to the same actual synchronization object.
+	///
+	///
+	/// There should not be more than one instance of NamedMutex for
+	/// a given name in a process. Otherwise, the instances may
+	/// interfere with each other.
+{
+public:
+	typedef Poco::ScopedLock<NamedMutex> ScopedLock;
+
+	NamedMutex(const std::string& name);
+		/// creates the Mutex.
+
+	~NamedMutex();
+		/// destroys the Mutex.
+
+	void lock();
+		/// Locks the mutex. Blocks if the mutex
+		/// is held by another process or thread.
+
+	bool tryLock();
+		/// Tries to lock the mutex. Returns false immediately
+		/// if the mutex is already held by another process or thread.
+		/// Returns true if the mutex was successfully locked.
+
+	void unlock();
+		/// Unlocks the mutex so that it can be acquired by
+		/// other threads.
+
+private:
+	NamedMutex();
+	NamedMutex(const NamedMutex&);
+	NamedMutex& operator = (const NamedMutex&);
+};
+
+
+//
+// inlines
+//
+inline void NamedMutex::lock()
+{
+	lockImpl();
+}
+
+
+inline bool NamedMutex::tryLock()
+{
+	return tryLockImpl();
+}
+
+
+inline void NamedMutex::unlock()
+{
+	unlockImpl();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedMutex_INCLUDED
diff --git a/Poco/NamedMutex_Android.h b/Poco/NamedMutex_Android.h
new file mode 100644
index 0000000..c570b86
--- /dev/null
+++ b/Poco/NamedMutex_Android.h
@@ -0,0 +1,41 @@
+//
+// NamedMutex_Android.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedMutex
+//
+// Definition of the NamedMutexImpl class for Android.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedMutex_Android_INCLUDED
+#define Foundation_NamedMutex_Android_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NamedMutexImpl
+{
+protected:
+	NamedMutexImpl(const std::string& name);
+	~NamedMutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	void unlockImpl();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedMutex_Android_INCLUDED
diff --git a/Poco/NamedMutex_UNIX.h b/Poco/NamedMutex_UNIX.h
new file mode 100644
index 0000000..da77a32
--- /dev/null
+++ b/Poco/NamedMutex_UNIX.h
@@ -0,0 +1,57 @@
+//
+// NamedMutex_UNIX.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedMutex
+//
+// Definition of the NamedMutexImpl class for Unix.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedMutex_UNIX_INCLUDED
+#define Foundation_NamedMutex_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX)
+#include <semaphore.h>
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API NamedMutexImpl
+{
+protected:
+	NamedMutexImpl(const std::string& name);
+	~NamedMutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	void unlockImpl();
+	
+private:
+	std::string getFileName();
+
+	std::string _name;
+#if defined(sun) || defined(__APPLE__) || defined(__osf__) || defined(__QNX__) || defined(_AIX)
+	sem_t* _sem;
+#else
+	int _semid;  // semaphore id
+	bool _owned;
+#endif
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedMutex_UNIX_INCLUDED
diff --git a/Poco/NamedMutex_WIN32.h b/Poco/NamedMutex_WIN32.h
new file mode 100644
index 0000000..c43dd35
--- /dev/null
+++ b/Poco/NamedMutex_WIN32.h
@@ -0,0 +1,46 @@
+//
+// NamedMutex_WIN32.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedMutex
+//
+// Definition of the NamedMutexImpl class for Windows.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedMutex_WIN32_INCLUDED
+#define Foundation_NamedMutex_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NamedMutexImpl
+{
+protected:
+	NamedMutexImpl(const std::string& name);
+	~NamedMutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	void unlockImpl();
+	
+private:
+	std::string _name;
+	HANDLE      _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedMutex_WIN32_INCLUDED
diff --git a/Poco/NamedMutex_WIN32U.h b/Poco/NamedMutex_WIN32U.h
new file mode 100644
index 0000000..8ee3158
--- /dev/null
+++ b/Poco/NamedMutex_WIN32U.h
@@ -0,0 +1,47 @@
+//
+// NamedMutex_WIN32U.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  NamedMutex
+//
+// Definition of the NamedMutexImpl class for Windows.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedMutex_WIN32U_INCLUDED
+#define Foundation_NamedMutex_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NamedMutexImpl
+{
+protected:
+	NamedMutexImpl(const std::string& name);
+	~NamedMutexImpl();
+	void lockImpl();
+	bool tryLockImpl();
+	void unlockImpl();
+	
+private:
+	std::string  _name;
+	std::wstring _uname;
+	HANDLE       _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NamedMutex_WIN32U_INCLUDED
diff --git a/Poco/NamedTuple.h b/Poco/NamedTuple.h
new file mode 100644
index 0000000..9a19357
--- /dev/null
+++ b/Poco/NamedTuple.h
@@ -0,0 +1,4462 @@
+//
+// NamedTuple.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  NamedTuple
+//
+// Definition of the NamedTuple class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NamedTuple_INCLUDED
+#define Foundation_NamedTuple_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Tuple.h"
+#include "Poco/TypeList.h"
+#include "Poco/DynamicAny.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Format.h"
+
+
+namespace Poco {
+
+
+template<class T0, 
+	class T1 = NullTypeList,
+	class T2 = NullTypeList,
+	class T3 = NullTypeList,
+	class T4 = NullTypeList,
+	class T5 = NullTypeList,
+	class T6 = NullTypeList,
+	class T7 = NullTypeList, 
+	class T8 = NullTypeList,
+	class T9 = NullTypeList,
+	class T10 = NullTypeList,
+	class T11 = NullTypeList,
+	class T12 = NullTypeList,
+	class T13 = NullTypeList,
+	class T14 = NullTypeList,
+	class T15 = NullTypeList,
+	class T16 = NullTypeList,
+	class T17 = NullTypeList,
+	class T18 = NullTypeList,
+	class T19 = NullTypeList>
+struct NamedTuple: public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::Type Type;
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16), 
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17), 
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18), 
+		typename TypeWrapper<T19>::CONSTTYPE& t19 = POCO_TYPEWRAPPER_DEFAULTVALUE(T19)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16), 
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17), 
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18), 
+		typename TypeWrapper<T19>::CONSTTYPE& t19 = POCO_TYPEWRAPPER_DEFAULTVALUE(T19)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		const std::string& n14 = "O",
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		const std::string& n15 = "P",
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		const std::string& n16 = "Q",
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16),
+		const std::string& n17 = "R",
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17),
+		const std::string& n18 = "S",
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18),
+		const std::string& n19 = "T",
+		typename TypeWrapper<T19>::CONSTTYPE& t19 = POCO_TYPEWRAPPER_DEFAULTVALUE(T19)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,n18,n19);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					case 14: return TupleType::template get<14>();
+					case 15: return TupleType::template get<15>();
+					case 16: return TupleType::template get<16>();
+					case 17: return TupleType::template get<17>();
+					case 18: return TupleType::template get<18>();
+					case 19: return TupleType::template get<19>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N",
+		const std::string& n14 = "O",
+		const std::string& n15 = "P",
+		const std::string& n16 = "Q",
+		const std::string& n17 = "R",
+		const std::string& n18 = "S",
+		const std::string& n19 = "T")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+			_pNames->push_back(n14); 
+			_pNames->push_back(n15); 
+			_pNames->push_back(n16); 
+			_pNames->push_back(n17); 
+			_pNames->push_back(n18); 
+			_pNames->push_back(n19); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15,
+	class T16,
+	class T17,
+	class T18>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::Type Type;
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16), 
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17), 
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16), 
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17), 
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		const std::string& n14 = "O",
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		const std::string& n15 = "P",
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		const std::string& n16 = "Q",
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16),
+		const std::string& n17 = "R",
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17),
+		const std::string& n18 = "S",
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,n18);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					case 14: return TupleType::template get<14>();
+					case 15: return TupleType::template get<15>();
+					case 16: return TupleType::template get<16>();
+					case 17: return TupleType::template get<17>();
+					case 18: return TupleType::template get<18>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N",
+		const std::string& n14 = "O",
+		const std::string& n15 = "P",
+		const std::string& n16 = "Q",
+		const std::string& n17 = "R",
+		const std::string& n18 = "S")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+			_pNames->push_back(n14); 
+			_pNames->push_back(n15); 
+			_pNames->push_back(n16); 
+			_pNames->push_back(n17); 
+			_pNames->push_back(n18); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15,
+	class T16,
+	class T17>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::Type Type;
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16), 
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16), 
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		const std::string& n14 = "O",
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		const std::string& n15 = "P",
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		const std::string& n16 = "Q",
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16),
+		const std::string& n17 = "R",
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					case 14: return TupleType::template get<14>();
+					case 15: return TupleType::template get<15>();
+					case 16: return TupleType::template get<16>();
+					case 17: return TupleType::template get<17>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N",
+		const std::string& n14 = "O",
+		const std::string& n15 = "P",
+		const std::string& n16 = "Q",
+		const std::string& n17 = "R")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+			_pNames->push_back(n14); 
+			_pNames->push_back(n15); 
+			_pNames->push_back(n16); 
+			_pNames->push_back(n17); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15,
+	class T16>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::Type Type;
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15), 
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		const std::string& n14 = "O",
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		const std::string& n15 = "P",
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		const std::string& n16 = "Q",
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					case 14: return TupleType::template get<14>();
+					case 15: return TupleType::template get<15>();
+					case 16: return TupleType::template get<16>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N",
+		const std::string& n14 = "O",
+		const std::string& n15 = "P",
+		const std::string& n16 = "Q")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+			_pNames->push_back(n14); 
+			_pNames->push_back(n15); 
+			_pNames->push_back(n16); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14), 
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		const std::string& n14 = "O",
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		const std::string& n15 = "P",
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					case 14: return TupleType::template get<14>();
+					case 15: return TupleType::template get<15>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N",
+		const std::string& n14 = "O",
+		const std::string& n15 = "P")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+			_pNames->push_back(n14); 
+			_pNames->push_back(n15); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13), 
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		const std::string& n14 = "O",
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					case 14: return TupleType::template get<14>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N",
+		const std::string& n14 = "O")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+			_pNames->push_back(n14); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12), 
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		const std::string& n13 = "N",
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					case 13: return TupleType::template get<13>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M",
+		const std::string& n13 = "N")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+			_pNames->push_back(n13); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11), 
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		const std::string& n12 = "M",
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12)): 
+	TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12), _pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					case 12: return TupleType::template get<12>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L",
+		const std::string& n12 = "M")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+			_pNames->push_back(n12); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10,
+	class T11>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10), 
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		const std::string& n11 = "L",
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					case 11: return TupleType::template get<11>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K",
+		const std::string& n11 = "L")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+			_pNames->push_back(n11); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9,
+	class T10>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9), 
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		const std::string& n10 = "K",
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10)): 
+	TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10), _pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					case 10: return TupleType::template get<10>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J",
+		const std::string& n10 = "K")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+			_pNames->push_back(n10); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8,
+	class T9>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8), 
+		const std::string& n9 = "J",
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8,t9), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					case 9: return TupleType::template get<9>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I",
+		const std::string& n9 = "J")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+			_pNames->push_back(n9); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7, 
+	class T8>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		const std::string& n8 = "I",
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7,t8), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7,n8);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					case 8: return TupleType::template get<8>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H",
+		const std::string& n8 = "I")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+			_pNames->push_back(n8);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,T7,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6,T7>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6,T7> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6,T7>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6), 
+		const std::string& n7 = "H",
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7)): 
+		TupleType(t0,t1,t2,t3,t4,t5,t6,t7), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6,n7);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					case 7: return TupleType::template get<7>(); 
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G",
+		const std::string& n7 = "H")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+			_pNames->push_back(n7);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,T6,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5,T6>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5,T6> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5,T6>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6)): 
+	TupleType(t0,t1,t2,t3,t4,t5,t6), _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5), 
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6)): 
+	TupleType(t0,t1,t2,t3,t4,t5,t6)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		const std::string& n6 = "G",
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6)): 
+	TupleType(t0,t1,t2,t3,t4,t5,t6), _pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5,n6);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					case 6: return TupleType::template get<6>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F", 
+		const std::string& n6 = "G")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+			_pNames->push_back(n6);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5>
+struct NamedTuple<T0,T1,T2,T3,T4,T5,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4,T5>
+{
+	typedef Tuple<T0,T1,T2,T3,T4,T5> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4,T5>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5)): 
+	TupleType(t0,t1,t2,t3,t4,t5), _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5)): 
+	TupleType(t0,t1,t2,t3,t4,t5)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4), 
+		const std::string& n5 = "F",
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5)): 
+	TupleType(t0,t1,t2,t3,t4,t5), _pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4,n5);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					case 5: return TupleType::template get<5>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E",
+		const std::string& n5 = "F")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+			_pNames->push_back(n5);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3,
+	class T4>
+struct NamedTuple<T0,T1,T2,T3,T4,NullTypeList>:
+	public Tuple<T0,T1,T2,T3,T4>
+{
+	typedef Tuple<T0,T1,T2,T3,T4> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3,T4>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4)): 
+		TupleType(t0,t1,t2,t3,t4), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4)): 
+		TupleType(t0,t1,t2,t3,t4)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		const std::string& n4 = "E",
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4)): 
+		TupleType(t0,t1,t2,t3,t4), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2,n3,n4);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					case 4: return TupleType::template get<4>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D",
+		const std::string& n4 = "E")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+			_pNames->push_back(n4);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2,
+	class T3>
+struct NamedTuple<T0,T1,T2,T3,NullTypeList>:
+	public Tuple<T0,T1,T2,T3>
+{
+	typedef Tuple<T0,T1,T2,T3> TupleType;
+	typedef typename Tuple<T0,T1,T2,T3>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3)): 
+		TupleType(t0,t1,t2,t3), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3)): 
+		TupleType(t0,t1,t2,t3)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2), 
+		const std::string& n3 = "D",
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3)): 
+	TupleType(t0,t1,t2,t3), _pNames(0) 
+	{
+		init(n0,n1,n2,n3);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					case 3: return TupleType::template get<3>(); 
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C",
+		const std::string& n3 = "D")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+			_pNames->push_back(n3); 
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1,
+	class T2>
+struct NamedTuple<T0,T1,T2,NullTypeList>:
+	public Tuple<T0,T1,T2>
+{
+	typedef Tuple<T0,T1,T2> TupleType;
+	typedef typename Tuple<T0,T1,T2>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1), 
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2)): 
+		TupleType(t0,t1,t2), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2)): 
+		TupleType(t0,t1,t2)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		const std::string& n2 = "C",
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2)): 
+		TupleType(t0,t1,t2), 
+		_pNames(0) 
+	{
+		init(n0,n1,n2);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					case 2: return TupleType::template get<2>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B",
+		const std::string& n2 = "C")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+			_pNames->push_back(n2);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0, 
+	class T1>
+struct NamedTuple<T0,T1,NullTypeList>:
+	public Tuple<T0,T1>
+{
+	typedef Tuple<T0,T1> TupleType;
+	typedef typename Tuple<T0,T1>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1)): 
+		TupleType(t0,t1), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1)): 
+		TupleType(t0,t1)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0,
+		typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		const std::string& n1 = "B",
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1)): 
+		TupleType(t0,t1), 
+		_pNames(0) 
+	{
+		init(n0,n1);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					case 1: return TupleType::template get<1>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A",
+		const std::string& n1 = "B")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+			_pNames->push_back(n1);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+template<class T0>
+struct NamedTuple<T0,NullTypeList>:
+	public Tuple<T0>
+{
+	typedef Tuple<T0> TupleType;
+	typedef typename Tuple<T0>::Type Type;
+
+	typedef std::vector<std::string> NameVec; 
+	typedef SharedPtr<NameVec> NameVecPtr; 
+
+	NamedTuple(): _pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames) 
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(typename TypeWrapper<T0>::CONSTTYPE& t0): 
+		TupleType(t0), 
+		_pNames(0)
+	{
+		init();
+	}
+
+	NamedTuple(const NameVecPtr& rNames, 
+		typename TypeWrapper<T0>::CONSTTYPE& t0): 
+		TupleType(t0)
+	{
+		if (rNames->size() != TupleType::length)
+			throw InvalidArgumentException("Wrong names vector length."); 
+
+		_pNames = rNames;
+	}
+
+	NamedTuple(const std::string& n0, typename TypeWrapper<T0>::CONSTTYPE& t0): 
+		TupleType(t0), 
+		_pNames(0) 
+	{
+		init(n0);
+	}
+
+	const DynamicAny get(const std::string& name) const
+	{
+		NameVec::const_iterator it = _pNames->begin(); 
+		NameVec::const_iterator itEnd = _pNames->end();
+
+		for(std::size_t counter = 0; it != itEnd; ++it, ++counter)
+		{
+			if (name == *it)
+			{
+				switch (counter)
+				{ 
+					case 0: return TupleType::template get<0>();
+					default: throw RangeException();
+				}
+			}
+		} 
+
+		throw NotFoundException("Name not found: " + name);
+	}
+
+	const DynamicAny operator [] (const std::string& name) const
+	{
+		return get(name);
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const 
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return TupleType::template get<N>();
+	}
+
+	template<int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		return TupleType::template set<N>(val);
+	}
+
+	const NameVecPtr& names()
+	{
+		return _pNames; 
+	}
+
+	void setName(std::size_t index, const std::string& name)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		(*_pNames)[index] = name;
+	}
+
+	const std::string& getName(std::size_t index)
+	{
+		if (index >= _pNames->size())
+			throw InvalidArgumentException(format("Invalid index: %z", index));
+
+		return (*_pNames)[index];
+	}
+
+	bool operator == (const NamedTuple& other) const
+	{
+		return TupleType(*this) == TupleType(other) && _pNames == other._pNames;
+	}
+
+	bool operator != (const NamedTuple& other) const 
+	{
+		return !(*this == other);
+	}
+
+	bool operator < (const NamedTuple& other) const
+	{
+		TupleType th(*this);
+		TupleType oth(other); 
+
+		return (th < oth && _pNames == other._pNames) || 
+			(th == oth && _pNames < other._pNames) ||
+			(th < oth && _pNames < other._pNames);
+	}
+
+private:
+	void init(const std::string& n0 = "A")
+	{ 
+		if (!_pNames)
+		{
+			_pNames = new NameVec;
+			_pNames->push_back(n0);
+		}
+	}
+
+	NameVecPtr _pNames;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Tuple_INCLUDED
diff --git a/Poco/NestedDiagnosticContext.h b/Poco/NestedDiagnosticContext.h
new file mode 100644
index 0000000..ccb29a5
--- /dev/null
+++ b/Poco/NestedDiagnosticContext.h
@@ -0,0 +1,181 @@
+//
+// NestedDiagnosticContext.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  NestedDiagnosticContext
+//
+// Definition of the NestedDiagnosticContext class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NestedDiagnosticContext_INCLUDED
+#define Foundation_NestedDiagnosticContext_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class NDCScope;
+
+
+class Foundation_API NestedDiagnosticContext
+	/// This class implements a Nested Diagnostic Context (NDC),
+	/// as described in Neil Harrison's article "Patterns for Logging 
+	/// Diagnostic Messages" in "Pattern Languages of Program Design 3"
+	/// (Addison-Wesley).
+	///
+	/// A NDC maintains a stack of context information, consisting of
+	/// an informational string (e.g., a method name), as well as an
+	/// optional source code line number and file name.
+	/// NDCs are especially useful for tagging log messages with
+	/// context information which is very helpful in a multithreaded
+	/// server scenario.
+	/// Every thread has its own private NDC, which is automatically
+	/// created when needed and destroyed when the thread terminates.
+	///
+	/// The NDCScope (or NDC::Scope) class can be used to automatically
+	/// push information at the beginning of a scope, and to pop it
+	/// at the end.
+	/// The poco_ndc(info) macro augments the information with a
+	/// source code line number and file name.
+{
+public:
+	typedef NDCScope Scope;
+
+	NestedDiagnosticContext();
+		/// Creates the NestedDiagnosticContext.
+
+	NestedDiagnosticContext(const NestedDiagnosticContext& ctx);
+		/// Copy constructor.
+
+	~NestedDiagnosticContext();
+		/// Destroys the NestedDiagnosticContext.
+		
+	NestedDiagnosticContext& operator = (const NestedDiagnosticContext& ctx);
+		/// Assignment operator.
+		
+	void push(const std::string& info);
+		/// Pushes a context (without line number and filename) onto the stack.
+		
+	void push(const std::string& info, int line, const char* filename);
+		/// Pushes a context (including line number and filename) 
+		/// onto the stack. Filename must be a static string, such as the
+		/// one produced by the __FILE__ preprocessor macro.
+
+	void pop();
+		/// Pops the top-most context off the stack.
+		
+	int depth() const;
+		/// Returns the depth (number of contexts) of the stack.
+	
+	std::string toString() const;
+		/// Returns the stack as a string with entries
+		/// delimited by colons. The string does not contain
+		/// line numbers and filenames.
+		
+	void dump(std::ostream& ostr) const;
+		/// Dumps the stack (including line number and filenames)
+		/// to the given stream. The entries are delimited by
+		/// a newline.
+
+	void dump(std::ostream& ostr, const std::string& delimiter) const;
+		/// Dumps the stack (including line number and filenames)
+		/// to the given stream.
+		
+	void clear();
+		/// Clears the NDC stack.
+	
+	static NestedDiagnosticContext& current();
+		/// Returns the current thread's NDC.
+
+private:
+	struct Context
+	{
+		std::string info;
+		const char* file;
+		int         line;
+	};
+	typedef std::vector<Context> Stack;
+	
+	Stack _stack;
+};
+
+
+typedef NestedDiagnosticContext NDC;
+
+
+class Foundation_API NDCScope
+	/// This class can be used to automatically push a context onto
+	/// the NDC stack at the beginning of a scope, and to pop
+	/// the context at the end of the scope.
+{
+public:
+	NDCScope(const std::string& info);
+		/// Pushes a context on the stack.
+		
+	NDCScope(const std::string& info, int line, const char* filename);
+		/// Pushes a context on the stack.
+
+	~NDCScope();
+		/// Pops the top-most context off the stack.
+};
+
+
+//
+// inlines
+//
+inline NDCScope::NDCScope(const std::string& info)
+{
+	NestedDiagnosticContext::current().push(info);
+}
+
+	
+inline NDCScope::NDCScope(const std::string& info, int line, const char* filename)
+{
+	NestedDiagnosticContext::current().push(info, line, filename);
+}
+
+
+inline NDCScope::~NDCScope()
+{
+	try
+	{
+		NestedDiagnosticContext::current().pop();
+	}
+	catch (...)
+	{
+		poco_unexpected();
+	}
+}
+
+
+//
+// helper macros
+//
+#define poco_ndc(func) \
+	Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__)
+
+
+#if defined(_DEBUG)
+	#define poco_ndc_dbg(func) \
+		Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__)
+#else
+	#define poco_ndc_dbg(func)
+#endif
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NestedDiagnosticContext_INCLUDED
diff --git a/Poco/Net/AbstractHTTPRequestHandler.h b/Poco/Net/AbstractHTTPRequestHandler.h
new file mode 100644
index 0000000..7bbc174
--- /dev/null
+++ b/Poco/Net/AbstractHTTPRequestHandler.h
@@ -0,0 +1,136 @@
+//
+// AbstractHTTPRequestHandler.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  AbstractHTTPRequestHandler
+//
+// Definition of the AbstractHTTPRequestHandler class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_AbstractHTTPRequestHandler_INCLUDED
+#define Net_AbstractHTTPRequestHandler_INCLUDED
+
+
+#include "Poco/Net/HTTPRequestHandler.h"
+#include "Poco/Net/HTTPResponse.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTMLForm;
+
+
+class Net_API AbstractHTTPRequestHandler: public HTTPRequestHandler
+	/// The abstract base class for AbstractHTTPRequestHandlers 
+	/// created by HTTPServer.
+	///
+	/// Derived classes must override the run() method.
+
+	/// Contrary to a HTTPRequestHandler, an AbstractHTTPRequestHandler
+	/// stores request and response as member variables to avoid having
+	/// to pass them around as method parameters. Additionally, a
+	/// HTMLForm object is created for use by subclasses.
+	///
+	/// The run() method must perform the complete handling
+	/// of the HTTP request connection. As soon as the run() 
+	/// method returns, the request handler object is destroyed.
+	///
+	/// A new AbstractHTTPRequestHandler object will be created for
+	/// each new HTTP request that is received by the HTTPServer.
+{
+public:
+	AbstractHTTPRequestHandler();
+		/// Creates the AbstractHTTPRequestHandler.
+
+	virtual ~AbstractHTTPRequestHandler();
+		/// Destroys the AbstractHTTPRequestHandler.
+
+	void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response);
+		/// This class implements some common behavior,
+		/// before calling run() to actually handle the request:
+		///   - save request and response objects;
+		///   - call authorize();
+		///   - if authorize() returns true call run(),
+		///     else send 401 (Unauthorized) response.
+		///
+		/// If run() throws an exception and the response has not been
+		/// sent yet, sends a 500 (Internal Server Error) response with
+		/// the exception's display text.
+
+	HTTPServerRequest& request();
+		/// Returns the request.
+
+	HTTPServerResponse& response();
+		/// Returns the response.
+
+	HTMLForm& form();
+		/// Returns a HTMLForm for the given request.
+		/// The HTMLForm object is created when this
+		/// member function is executed the first time.
+
+	void sendErrorResponse(HTTPResponse::HTTPStatus status, const std::string& message);
+		/// Sends a HTML error page for the given status code.
+		/// The given message is added to the page:
+		///     <HTML>
+		///         <HEAD>
+		///             <TITLE>status - reason</TITLE>
+		///         </HEAD>
+		///         <BODY>
+		///            <H1>status - reason</H1>
+		///            <P>message</P>
+		///         </BODY>
+		///     </HTML>
+	
+protected:
+	virtual void run() = 0;
+		/// Must be overridden by subclasses.
+		///
+		/// Handles the given request.
+
+	virtual bool authenticate();
+		/// Check authentication; returns true if okay, false if failed to authenticate.
+		/// The default implementation always returns true.
+		///
+		/// Subclasses can override this member function to perform
+		/// some form of client or request authentication before
+		/// the request is actually handled.
+
+private:
+	HTTPServerRequest*  _pRequest;
+	HTTPServerResponse* _pResponse;
+	HTMLForm*           _pForm;
+};
+
+
+//
+// inlines
+//
+inline HTTPServerRequest& AbstractHTTPRequestHandler::request()
+{
+	poco_check_ptr (_pRequest);
+	
+	return *_pRequest;
+}
+
+
+inline HTTPServerResponse& AbstractHTTPRequestHandler::response()
+{
+	poco_check_ptr (_pResponse);
+
+	return *_pResponse;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_AbstractHTTPRequestHandler_INCLUDED
diff --git a/Poco/Net/AcceptCertificateHandler.h b/Poco/Net/AcceptCertificateHandler.h
new file mode 100644
index 0000000..2d92c62
--- /dev/null
+++ b/Poco/Net/AcceptCertificateHandler.h
@@ -0,0 +1,52 @@
+//
+// AcceptCertificateHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  AcceptCertificateHandler
+//
+// Definition of the AcceptCertificateHandler class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_AcceptCertificateHandler_INCLUDED
+#define NetSSL_AcceptCertificateHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/InvalidCertificateHandler.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API AcceptCertificateHandler: public InvalidCertificateHandler
+	/// A AcceptCertificateHandler is invoked whenever an error 
+	/// occurs verifying the certificate. It always accepts
+	/// the certificate.
+	///
+	/// Should be using for testing purposes only.
+{
+public:
+	AcceptCertificateHandler(bool handleErrorsOnServerSide);
+		/// Creates the AcceptCertificateHandler
+
+	virtual ~AcceptCertificateHandler();
+		/// Destroys the AcceptCertificateHandler.
+
+	void onInvalidCertificate(const void* pSender, VerificationErrorArgs& errorCert);
+		/// Receives the questionable certificate in parameter errorCert. If one wants to accept the
+		/// certificate, call errorCert.setIgnoreError(true).
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_AcceptCertificateHandler_INCLUDED
diff --git a/Poco/Net/CertificateHandlerFactory.h b/Poco/Net/CertificateHandlerFactory.h
new file mode 100644
index 0000000..5e3699c
--- /dev/null
+++ b/Poco/Net/CertificateHandlerFactory.h
@@ -0,0 +1,93 @@
+//
+// CertificateHandlerFactory.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  CertificateHandlerFactory
+//
+// Definition of the CertificateHandlerFactory class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_CertificateHandlerFactory_INCLUDED
+#define NetSSL_CertificateHandlerFactory_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class InvalidCertificateHandler;
+
+
+class NetSSL_API CertificateHandlerFactory
+	/// A CertificateHandlerFactory is responsible for creating InvalidCertificateHandlers.
+	///
+	/// You don't need to access this class directly. Use the macro
+	///     POCO_REGISTER_CHFACTORY(namespace, InvalidCertificateHandlerName) 
+	/// instead (see the documentation of InvalidCertificateHandler for an example).
+{
+public:
+	CertificateHandlerFactory();
+		/// Creates the CertificateHandlerFactory.
+
+	virtual ~CertificateHandlerFactory();
+		/// Destroys the CertificateHandlerFactory.
+
+	virtual InvalidCertificateHandler* create(bool server) const = 0;
+		/// Creates a new InvalidCertificateHandler. Set server to true if the certificate handler is used on the server side.
+};
+
+
+class NetSSL_API CertificateHandlerFactoryRegistrar
+	/// Registrar class which automatically registers CertificateHandlerFactory at the CertificateHandlerFactoryMgr.
+	/// You don't need to access this class directly. Use the macro
+	///     POCO_REGISTER_CHFACTORY(namespace, InvalidCertificateHandlerName) 
+	/// instead (see the documentation of InvalidCertificateHandler for an example).
+{
+public:
+	CertificateHandlerFactoryRegistrar(const std::string& name, CertificateHandlerFactory* pFactory);
+		/// Registers the CertificateHandlerFactory with the given name at the factory manager.
+
+	virtual ~CertificateHandlerFactoryRegistrar();
+		/// Destroys the CertificateHandlerFactoryRegistrar.
+};
+
+
+template <typename T>
+class CertificateHandlerFactoryImpl: public Poco::Net::CertificateHandlerFactory
+{
+public:
+	CertificateHandlerFactoryImpl()
+	{
+	}
+
+	~CertificateHandlerFactoryImpl()
+	{
+	}
+
+	InvalidCertificateHandler* create(bool server) const
+	{
+		return new T(server);
+	}
+};
+
+
+} } // namespace Poco::Net
+
+
+// DEPRECATED: register the factory directly at the FactoryMgr:
+// Poco::Net::SSLManager::instance().certificateHandlerFactoryMgr().setFactory(name, new Poco::Net::CertificateHandlerFactoryImpl<MyConsoleHandler>());
+#define POCO_REGISTER_CHFACTORY(API, PKCLS)		\
+	static Poco::Net::CertificateHandlerFactoryRegistrar aRegistrar(std::string(#PKCLS), new Poco::Net::CertificateHandlerFactoryImpl<PKCLS>());
+
+
+#endif // NetSSL_CertificateHandlerFactory_INCLUDED
diff --git a/Poco/Net/CertificateHandlerFactoryMgr.h b/Poco/Net/CertificateHandlerFactoryMgr.h
new file mode 100644
index 0000000..e70c906
--- /dev/null
+++ b/Poco/Net/CertificateHandlerFactoryMgr.h
@@ -0,0 +1,64 @@
+//
+// CertificateHandlerFactoryMgr.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  CertificateHandlerFactoryMgr
+//
+// Definition of the CertificateHandlerFactoryMgr class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_CertificateHandlerFactoryMgr_INCLUDED
+#define NetSSL_CertificateHandlerFactoryMgr_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/CertificateHandlerFactory.h"
+#include "Poco/SharedPtr.h"
+#include <map>
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API CertificateHandlerFactoryMgr
+	/// A CertificateHandlerFactoryMgr manages all existing CertificateHandlerFactories.
+{
+public:
+	typedef std::map<std::string, Poco::SharedPtr<CertificateHandlerFactory> > FactoriesMap;
+	
+	CertificateHandlerFactoryMgr();
+		/// Creates the CertificateHandlerFactoryMgr.
+
+	~CertificateHandlerFactoryMgr();
+		/// Destroys the CertificateHandlerFactoryMgr.
+
+	void setFactory(const std::string& name, CertificateHandlerFactory* pFactory);
+		/// Registers the factory. Class takes ownership of the pointer.
+		/// If a factory with the same name already exists, an exception is thrown.
+
+	bool hasFactory(const std::string& name) const;
+		/// Returns true if for the given name a factory is already registered
+	
+	const CertificateHandlerFactory* getFactory(const std::string& name) const;
+		/// Returns NULL if for the given name a factory does not exist, otherwise the factory is returned
+
+	void removeFactory(const std::string& name);
+		/// Removes the factory from the manager. 
+
+private:
+	FactoriesMap _factories;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_CertificateHandlerFactoryMgr_INCLUDED
diff --git a/Poco/Net/ConsoleCertificateHandler.h b/Poco/Net/ConsoleCertificateHandler.h
new file mode 100644
index 0000000..c58962c
--- /dev/null
+++ b/Poco/Net/ConsoleCertificateHandler.h
@@ -0,0 +1,50 @@
+//
+// ConsoleCertificateHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  ConsoleCertificateHandler
+//
+// Definition of the ConsoleCertificateHandler class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_ConsoleCertificateHandler_INCLUDED
+#define NetSSL_ConsoleCertificateHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/InvalidCertificateHandler.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API ConsoleCertificateHandler: public InvalidCertificateHandler
+	/// A ConsoleCertificateHandler is invoked whenever an error occurs verifying the certificate.
+	/// 
+	/// The certificate is printed to stdout and the user is asked via console if he wants to accept it.
+{
+public:
+	ConsoleCertificateHandler(bool handleErrorsOnServerSide);
+		/// Creates the ConsoleCertificateHandler.
+
+	virtual ~ConsoleCertificateHandler();
+		/// Destroys the ConsoleCertificateHandler.
+
+	void onInvalidCertificate(const void* pSender, VerificationErrorArgs& errorCert);
+		/// Prints the certificate to stdout and waits for user input on the console
+		/// to decide if a certificate should be accepted/rejected.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_ConsoleCertificateHandler_INCLUDED
diff --git a/Poco/Net/Context.h b/Poco/Net/Context.h
new file mode 100644
index 0000000..d663283
--- /dev/null
+++ b/Poco/Net/Context.h
@@ -0,0 +1,405 @@
+//
+// Context.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  Context
+//
+// Definition of the Context class.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_Context_INCLUDED
+#define NetSSL_Context_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Crypto/X509Certificate.h"
+#include "Poco/Crypto/RSAKey.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <openssl/ssl.h>
+#include <cstdlib>
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API Context: public Poco::RefCountedObject
+	/// This class encapsulates context information for
+	/// an SSL server or client, such as the certificate
+	/// verification mode and the location of certificates
+	/// and private key files, as well as the list of
+	/// supported ciphers.
+	///
+	/// The Context class is also used to control
+	/// SSL session caching on the server and client side.
+{
+public:
+	typedef Poco::AutoPtr<Context> Ptr;
+
+	enum Usage
+	{
+		CLIENT_USE, 	    /// Context is used by a client.
+		SERVER_USE,         /// Context is used by a server.
+		TLSV1_CLIENT_USE,   /// Context is used by a client requiring TLSv1.
+		TLSV1_SERVER_USE,   /// Context is used by a server requiring TLSv1.
+		TLSV1_1_CLIENT_USE, /// Context is used by a client requiring TLSv1.1 (OpenSSL 1.0.0 or newer).
+		TLSV1_1_SERVER_USE, /// Context is used by a server requiring TLSv1.1 (OpenSSL 1.0.0 or newer).
+		TLSV1_2_CLIENT_USE, /// Context is used by a client requiring TLSv1.2 (OpenSSL 1.0.1 or newer).
+		TLSV1_2_SERVER_USE  /// Context is used by a server requiring TLSv1.2 (OpenSSL 1.0.1 or newer).
+	};
+
+	enum VerificationMode
+	{
+		VERIFY_NONE    = SSL_VERIFY_NONE,
+			/// Server: The server will not send a client certificate
+			/// request to the client, so the client will not send a certificate.
+			///
+			/// Client: If not using an anonymous cipher (by default disabled),
+			/// the server will send a certificate which will be checked, but
+			/// the result of the check will be ignored.
+
+		VERIFY_RELAXED = SSL_VERIFY_PEER,
+			/// Server: The server sends a client certificate request to the
+			/// client. The certificate returned (if any) is checked.
+			/// If the verification process fails, the TLS/SSL handshake is
+			/// immediately terminated with an alert message containing the
+			/// reason for the verification failure.
+			///
+			/// Client: The server certificate is verified, if one is provided.
+			/// If the verification process fails, the TLS/SSL handshake is
+			/// immediately terminated with an alert message containing the
+			/// reason for the verification failure.
+
+		VERIFY_STRICT  = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+			/// Server: If the client did not return a certificate, the TLS/SSL
+			/// handshake is immediately terminated with a handshake failure
+			/// alert.
+			///
+			/// Client: Same as VERIFY_RELAXED.
+
+		VERIFY_ONCE    = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE
+			/// Server: Only request a client certificate on the initial
+			/// TLS/SSL handshake. Do not ask for a client certificate
+			/// again in case of a renegotiation.
+			///
+			/// Client: Same as VERIFY_RELAXED.
+	};
+
+	enum Protocols
+	{
+		PROTO_SSLV2   = 0x01,
+		PROTO_SSLV3   = 0x02,
+		PROTO_TLSV1   = 0x04,
+		PROTO_TLSV1_1 = 0x08,
+		PROTO_TLSV1_2 = 0x10
+	};
+
+	struct NetSSL_API Params
+	{
+		Params();
+			/// Initializes the struct with default values.
+
+		std::string privateKeyFile;
+			/// Path to the private key file used for encryption.
+			/// Can be empty if no private key file is used.
+
+		std::string certificateFile;
+			/// Path to the certificate file (in PEM format).
+			/// If the private key and the certificate are stored in the same file, this
+			/// can be empty if privateKeyFile is given.
+
+		std::string caLocation;
+			/// Path to the file or directory containing the CA/root certificates.
+			/// Can be empty if the OpenSSL builtin CA certificates
+			/// are used (see loadDefaultCAs).
+
+		VerificationMode verificationMode;
+			/// Specifies whether and how peer certificates are validated.
+			/// Defaults to VERIFY_RELAXED.
+
+		int verificationDepth;
+			/// Sets the upper limit for verification chain sizes. Verification
+			/// will fail if a certificate chain larger than this is encountered.
+			/// Defaults to 9.
+
+		bool loadDefaultCAs;
+			/// Specifies whether the builtin CA certificates from OpenSSL are used.
+			/// Defaults to false.
+
+		std::string cipherList;
+			/// Specifies the supported ciphers in OpenSSL notation.
+			/// Defaults to "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH".
+
+		std::string dhParamsFile;
+			/// Specifies a file containing Diffie-Hellman parameters.
+			/// If empty, the default parameters are used.
+
+		std::string ecdhCurve;
+			/// Specifies the name of the curve to use for ECDH, based
+			/// on the curve names specified in RFC 4492.
+			/// Defaults to "prime256v1".
+	};
+
+	Context(Usage usage, const Params& params);
+		/// Creates a Context using the given parameters.
+		///
+		///   * usage specifies whether the context is used by a client or server.
+		///   * params specifies the context parameters.
+
+	Context(
+		Usage usage,
+		const std::string& privateKeyFile,
+		const std::string& certificateFile,
+		const std::string& caLocation,
+		VerificationMode verificationMode = VERIFY_RELAXED,
+		int verificationDepth = 9,
+		bool loadDefaultCAs = false,
+		const std::string& cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+		/// Creates a Context.
+		///
+		///   * usage specifies whether the context is used by a client or server.
+		///   * privateKeyFile contains the path to the private key file used for encryption.
+		///     Can be empty if no private key file is used.
+		///   * certificateFile contains the path to the certificate file (in PEM format).
+		///     If the private key and the certificate are stored in the same file, this
+		///     can be empty if privateKeyFile is given.
+		///   * caLocation contains the path to the file or directory containing the
+		///     CA/root certificates. Can be empty if the OpenSSL builtin CA certificates
+		///     are used (see loadDefaultCAs).
+		///   * verificationMode specifies whether and how peer certificates are validated.
+		///   * verificationDepth sets the upper limit for verification chain sizes. Verification
+		///     will fail if a certificate chain larger than this is encountered.
+		///   * loadDefaultCAs specifies whether the builtin CA certificates from OpenSSL are used.
+		///   * cipherList specifies the supported ciphers in OpenSSL notation.
+		///
+		/// Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler
+		/// must have been setup with the SSLManager, or the SSLManager's PrivateKeyPassphraseRequired
+		/// event must be handled.
+
+	Context(
+		Usage usage,
+		const std::string& caLocation,
+		VerificationMode verificationMode = VERIFY_RELAXED,
+		int verificationDepth = 9,
+		bool loadDefaultCAs = false,
+		const std::string& cipherList = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+		/// Creates a Context.
+		///
+		///   * usage specifies whether the context is used by a client or server.
+		///   * caLocation contains the path to the file or directory containing the
+		///     CA/root certificates. Can be empty if the OpenSSL builtin CA certificates
+		///     are used (see loadDefaultCAs).
+		///   * verificationMode specifies whether and how peer certificates are validated.
+		///   * verificationDepth sets the upper limit for verification chain sizes. Verification
+		///     will fail if a certificate chain larger than this is encountered.
+		///   * loadDefaultCAs specifies whether the builtin CA certificates from OpenSSL are used.
+		///   * cipherList specifies the supported ciphers in OpenSSL notation.
+		///
+		/// Note that a private key and/or certificate must be specified with
+		/// usePrivateKey()/useCertificate() before the Context can be used.
+
+	~Context();
+		/// Destroys the Context.
+
+	void useCertificate(const Poco::Crypto::X509Certificate& certificate);
+		/// Sets the certificate to be used by the Context.
+		///
+		/// To set-up a complete certificate chain, it might be
+		/// necessary to call addChainCertificate() to specify
+		/// additional certificates.
+		///
+		/// Note that useCertificate() must always be called before
+		/// usePrivateKey().
+
+	void addChainCertificate(const Poco::Crypto::X509Certificate& certificate);
+		/// Adds a certificate for certificate chain validation.
+
+	void addCertificateAuthority(const Poco::Crypto::X509Certificate& certificate);
+		/// Add one trusted certification authority to be used by the Context.
+
+	void usePrivateKey(const Poco::Crypto::RSAKey& key);
+		/// Sets the private key to be used by the Context.
+		///
+		/// Note that useCertificate() must always be called before
+		/// usePrivateKey().
+		///
+		/// Note: If the private key is protected by a passphrase, a PrivateKeyPassphraseHandler
+		/// must have been setup with the SSLManager, or the SSLManager's PrivateKeyPassphraseRequired
+		/// event must be handled.
+
+	SSL_CTX* sslContext() const;
+		/// Returns the underlying OpenSSL SSL Context object.
+
+	Usage usage() const;
+		/// Returns whether the context is for use by a client or by a server
+		/// and whether TLSv1 is required.
+
+	bool isForServerUse() const;
+		/// Returns true iff the context is for use by a server.
+
+	Context::VerificationMode verificationMode() const;
+		/// Returns the verification mode.
+
+	void enableSessionCache(bool flag = true);
+		/// Enable or disable SSL/TLS session caching.
+		/// For session caching to work, it must be enabled
+		/// on the server, as well as on the client side.
+		///
+		/// The default is disabled session caching.
+		///
+		/// To enable session caching on the server side, use the
+		/// two-argument version of this method to specify
+		/// a session ID context.
+
+	void enableSessionCache(bool flag, const std::string& sessionIdContext);
+		/// Enables or disables SSL/TLS session caching on the server.
+		/// For session caching to work, it must be enabled
+		/// on the server, as well as on the client side.
+		///
+		/// SessionIdContext contains the application's unique
+		/// session ID context, which becomes part of each
+		/// session identifier generated by the server within this
+		/// context. SessionIdContext can be an arbitrary sequence
+		/// of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH.
+		///
+		/// A non-empty sessionIdContext should be specified even if
+		/// session caching is disabled to avoid problems with clients
+		/// requesting to reuse a session (e.g. Firefox 3.6).
+		///
+		/// This method may only be called on SERVER_USE Context objects.
+
+	bool sessionCacheEnabled() const;
+		/// Returns true iff the session cache is enabled.
+
+	void setSessionCacheSize(std::size_t size);
+		/// Sets the maximum size of the server session cache, in number of
+		/// sessions. The default size (according to OpenSSL documentation)
+		/// is 1024*20, which may be too large for many applications,
+		/// especially on embedded platforms with limited memory.
+		///
+		/// Specifying a size of 0 will set an unlimited cache size.
+		///
+		/// This method may only be called on SERVER_USE Context objects.
+
+	std::size_t getSessionCacheSize() const;
+		/// Returns the current maximum size of the server session cache.
+		///
+		/// This method may only be called on SERVER_USE Context objects.
+
+	void setSessionTimeout(long seconds);
+		/// Sets the timeout (in seconds) of cached sessions on the server.
+		/// A cached session will be removed from the cache if it has
+		/// not been used for the given number of seconds.
+		///
+		/// This method may only be called on SERVER_USE Context objects.
+
+	long getSessionTimeout() const;
+		/// Returns the timeout (in seconds) of cached sessions on the server.
+		///
+		/// This method may only be called on SERVER_USE Context objects.
+
+	void flushSessionCache();
+		/// Flushes the SSL session cache on the server.
+		///
+		/// This method may only be called on SERVER_USE Context objects.
+
+	void enableExtendedCertificateVerification(bool flag = true);
+		/// Enable or disable the automatic post-connection
+		/// extended certificate verification.
+		///
+		/// See X509Certificate::verify() for more information.
+
+	bool extendedCertificateVerificationEnabled() const;
+		/// Returns true iff automatic extended certificate
+		/// verification is enabled.
+
+	void disableStatelessSessionResumption();
+		/// Newer versions of OpenSSL support RFC 4507 tickets for stateless
+		/// session resumption.
+		///
+		/// The feature can be disabled by calling this method.
+
+	void disableProtocols(int protocols);
+		/// Disables the given protocols.
+		///
+		/// The protocols to be disabled are specified by OR-ing
+		/// values from the Protocols enumeration, e.g.:
+		///
+		///   context.disableProtocols(PROTO_SSLV2 | PROTO_SSLV3);
+
+	void preferServerCiphers();
+		/// When choosing a cipher, use the server's preferences instead of the client
+		/// preferences. When not called, the SSL server will always follow the clients
+		/// preferences. When called, the SSL/TLS server will choose following its own
+		/// preferences.
+
+private:
+	void init(const Params& params);
+		/// Initializes the Context with the given parameters.
+
+	void initDH(const std::string& dhFile);
+		/// Initializes the Context with Diffie-Hellman parameters.
+
+	void initECDH(const std::string& curve);
+		/// Initializes the Context with Elliptic-Curve Diffie-Hellman key
+		/// exchange curve parameters.
+
+	void createSSLContext();
+		/// Create a SSL_CTX object according to Context configuration.
+
+	Usage _usage;
+	VerificationMode _mode;
+	SSL_CTX* _pSSLContext;
+	bool _extendedCertificateVerification;
+};
+
+
+//
+// inlines
+//
+inline Context::Usage Context::usage() const
+{
+	return _usage;
+}
+
+
+inline bool Context::isForServerUse() const
+{
+	return _usage == SERVER_USE
+		|| _usage == TLSV1_SERVER_USE
+		|| _usage == TLSV1_1_SERVER_USE
+		|| _usage == TLSV1_2_SERVER_USE;
+}
+
+
+inline Context::VerificationMode Context::verificationMode() const
+{
+	return _mode;
+}
+
+
+inline SSL_CTX* Context::sslContext() const
+{
+	return _pSSLContext;
+}
+
+
+inline bool Context::extendedCertificateVerificationEnabled() const
+{
+	return _extendedCertificateVerification;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_Context_INCLUDED
diff --git a/Poco/Net/DNS.h b/Poco/Net/DNS.h
new file mode 100644
index 0000000..2de47b3
--- /dev/null
+++ b/Poco/Net/DNS.h
@@ -0,0 +1,199 @@
+//
+// DNS.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  DNS
+//
+// Definition of the DNS class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_DNS_INCLUDED
+#define Net_DNS_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Net/IPAddress.h"
+#include "Poco/Net/HostEntry.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API DNS
+	/// This class provides an interface to the
+	/// domain name service.
+	///
+	/// Starting with POCO C++ Libraries release 1.9.0,
+	/// this class also supports Internationalized Domain Names (IDNs).
+	///
+	/// Regarding IDNs, the following rules apply:
+	///
+	///   * An IDN passed to hostByName() must be encoded manually, by calling
+	///     encodeIDN() (after testing with isIDN() first).
+	///   * An UTF-8 IDN passed to resolve() or resolveOne() is automatically encoded.
+	///   * IDNs returned in HostEntry objects are never decoded. They can be
+	///     decoded by calling decodeIDN() (after testing for an encoded IDN by
+	///     calling isEncodedIDN()).
+{
+public:
+	enum HintFlag
+	{
+		DNS_HINT_NONE           = 0,
+#ifdef POCO_HAVE_ADDRINFO
+		DNS_HINT_AI_PASSIVE     = AI_PASSIVE,     /// Socket address will be used in bind() call
+		DNS_HINT_AI_CANONNAME   = AI_CANONNAME,   /// Return canonical name in first ai_canonname
+		DNS_HINT_AI_NUMERICHOST = AI_NUMERICHOST, /// Nodename must be a numeric address string
+		DNS_HINT_AI_NUMERICSERV = AI_NUMERICSERV, /// Servicename must be a numeric port number
+		DNS_HINT_AI_ALL         = AI_ALL,         /// Query both IP6 and IP4 with AI_V4MAPPED
+		DNS_HINT_AI_ADDRCONFIG  = AI_ADDRCONFIG,  /// Resolution only if global address configured
+		DNS_HINT_AI_V4MAPPED    = AI_V4MAPPED     /// On v6 failure, query v4 and convert to V4MAPPED format
+#endif
+	};
+
+	static HostEntry hostByName(const std::string& hostname, unsigned hintFlags =
+#ifdef POCO_HAVE_ADDRINFO
+		DNS_HINT_AI_CANONNAME | DNS_HINT_AI_ADDRCONFIG
+#else
+		DNS_HINT_NONE
+#endif
+		);
+		/// Returns a HostEntry object containing the DNS information
+		/// for the host with the given name. HintFlag argument is only
+		/// used on platforms that have getaddrinfo().
+		///
+		/// Note that Internationalized Domain Names must be encoded
+		/// using Punycode (see encodeIDN()) before calling this method.
+		///
+		/// Throws a HostNotFoundException if a host with the given
+		/// name cannot be found.
+		///
+		/// Throws a NoAddressFoundException if no address can be
+		/// found for the hostname.
+		///
+		/// Throws a DNSException in case of a general DNS error.
+		///
+		/// Throws an IOException in case of any other error.
+
+	static HostEntry hostByAddress(const IPAddress& address, unsigned hintFlags =
+#ifdef POCO_HAVE_ADDRINFO
+		DNS_HINT_AI_CANONNAME | DNS_HINT_AI_ADDRCONFIG
+#else
+		DNS_HINT_NONE
+#endif
+		);
+		/// Returns a HostEntry object containing the DNS information
+		/// for the host with the given IP address. HintFlag argument is only
+		/// used on platforms that have getaddrinfo().
+		///
+		/// Throws a HostNotFoundException if a host with the given
+		/// name cannot be found.
+		///
+		/// Throws a DNSException in case of a general DNS error.
+		///
+		/// Throws an IOException in case of any other error.
+
+	static HostEntry resolve(const std::string& address);
+		/// Returns a HostEntry object containing the DNS information
+		/// for the host with the given IP address or host name.
+		///
+		/// If address contains a UTF-8 encoded IDN (internationalized
+		/// domain name), the domain name will be encoded first using
+		/// Punycode.
+		///
+		/// Throws a HostNotFoundException if a host with the given
+		/// name cannot be found.
+		///
+		/// Throws a NoAddressFoundException if no address can be
+		/// found for the hostname.
+		///
+		/// Throws a DNSException in case of a general DNS error.
+		///
+		/// Throws an IOException in case of any other error.
+
+	static IPAddress resolveOne(const std::string& address);
+		/// Convenience method that calls resolve(address) and returns
+		/// the first address from the HostInfo.
+
+	static HostEntry thisHost();
+		/// Returns a HostEntry object containing the DNS information
+		/// for this host.
+		///
+		/// Throws a HostNotFoundException if DNS information
+		/// for this host cannot be found.
+		///
+		/// Throws a NoAddressFoundException if no address can be
+		/// found for this host.
+		///
+		/// Throws a DNSException in case of a general DNS error.
+		///
+		/// Throws an IOException in case of any other error.
+
+	static void reload();
+		/// Reloads the resolver configuration.
+		///
+		/// This method will call res_init() if the Net library
+		/// has been compiled with -DPOCO_HAVE_LIBRESOLV. Otherwise
+		/// it will do nothing.
+
+	static std::string hostName();
+		/// Returns the host name of this host.
+
+	static bool isIDN(const std::string& hostname);
+		/// Returns true if the given hostname is an internationalized
+		/// domain name (IDN) containing non-ASCII characters, otherwise false.
+		///
+		/// The IDN must be UTF-8 encoded.
+
+	static bool isEncodedIDN(const std::string& hostname);
+		/// Returns true if the given hostname is an Punycode-encoded
+		/// internationalized domain name (IDN), otherwise false.
+		///
+		/// An encoded IDN starts with the character sequence "xn--".
+
+	static std::string encodeIDN(const std::string& idn);
+		/// Encodes the given IDN (internationalized domain name), which must
+		/// be in UTF-8 encoding.
+		///
+		/// The resulting string will be encoded according to Punycode.
+
+	static std::string decodeIDN(const std::string& encodedIDN);
+		/// Decodes the given Punycode-encoded IDN (internationalized domain name).
+		///
+		/// The resulting string will be UTF-8 encoded.
+
+protected:
+	static int lastError();
+		/// Returns the code of the last error.
+
+	static void error(int code, const std::string& arg);
+		/// Throws an exception according to the error code.
+
+	static void aierror(int code, const std::string& arg);
+		/// Throws an exception according to the getaddrinfo() error code.
+
+	static std::string encodeIDNLabel(const std::string& idn);
+		/// Encodes the given IDN (internationalized domain name) label, which must
+		/// be in UTF-8 encoding.
+		///
+		/// The resulting string will be encoded according to Punycode.
+
+	static std::string decodeIDNLabel(const std::string& encodedIDN);
+		/// Decodes the given Punycode-encoded IDN (internationalized domain name) label.
+		///
+		/// The resulting string will be UTF-8 encoded.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_DNS_INCLUDED
diff --git a/Poco/Net/DatagramSocket.h b/Poco/Net/DatagramSocket.h
new file mode 100644
index 0000000..17d0253
--- /dev/null
+++ b/Poco/Net/DatagramSocket.h
@@ -0,0 +1,168 @@
+//
+// DatagramSocket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  DatagramSocket
+//
+// Definition of the DatagramSocket class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_DatagramSocket_INCLUDED
+#define Net_DatagramSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API DatagramSocket: public Socket
+	/// This class provides an interface to an
+	/// UDP stream socket.
+{
+public:
+	DatagramSocket();
+		/// Creates an unconnected, unbound datagram socket.
+		///
+		/// Before the datagram socket can be used, bind(),
+		/// bind6() or connect() must be called.
+		///
+		/// Notice: The behavior of this constructor has changed
+		/// in release 2.0. Previously, the constructor created
+		/// an unbound IPv4 datagram socket.
+
+	explicit DatagramSocket(SocketAddress::Family family);
+		/// Creates an unconnected datagram socket.
+		///
+		/// The socket will be created for the
+		/// given address family.
+
+	DatagramSocket(const SocketAddress& address, bool reuseAddress = false);
+		/// Creates a datagram socket and binds it
+		/// to the given address.
+		///
+		/// Depending on the address family, the socket
+		/// will be either an IPv4 or an IPv6 socket.
+
+	DatagramSocket(const Socket& socket);
+		/// Creates the DatagramSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a DatagramSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	~DatagramSocket();
+		/// Destroys the DatagramSocket.
+
+	DatagramSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	void connect(const SocketAddress& address);
+		/// Restricts incoming and outgoing
+		/// packets to the specified address.
+		///
+		/// Calls to connect() cannot come before calls to bind().
+
+	void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// Calls to connect cannot() come before calls to bind().
+
+	void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+		///
+		/// Calls to connect cannot() come before calls to bind().
+
+	int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+
+	int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		///
+		/// Returns the number of bytes received.
+
+	int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket to the given address.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+
+	int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		/// Stores the address of the sender in address.
+		///
+		/// Returns the number of bytes received.
+
+	void setBroadcast(bool flag);
+		/// Sets the value of the SO_BROADCAST socket option.
+		///
+		/// Setting this flag allows sending datagrams to
+		/// the broadcast address.
+	
+	bool getBroadcast() const;
+		/// Returns the value of the SO_BROADCAST socket option.
+
+protected:
+	DatagramSocket(SocketImpl* pImpl);
+		/// Creates the Socket and attaches the given SocketImpl.
+		/// The socket takes ownership of the SocketImpl.
+		///
+		/// The SocketImpl must be a StreamSocketImpl, otherwise
+		/// an InvalidArgumentException will be thrown.
+};
+
+
+//
+// inlines
+//
+inline void DatagramSocket::setBroadcast(bool flag)
+{
+	impl()->setBroadcast(flag);
+}
+
+
+inline bool DatagramSocket::getBroadcast() const
+{
+	return impl()->getBroadcast();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_DatagramSocket_INCLUDED
diff --git a/Poco/Net/DatagramSocketImpl.h b/Poco/Net/DatagramSocketImpl.h
new file mode 100644
index 0000000..f9d280a
--- /dev/null
+++ b/Poco/Net/DatagramSocketImpl.h
@@ -0,0 +1,55 @@
+//
+// DatagramSocketImpl.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  DatagramSocketImpl
+//
+// Definition of the DatagramSocketImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_DatagramSocketImpl_INCLUDED
+#define Net_DatagramSocketImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketImpl.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API DatagramSocketImpl: public SocketImpl
+	/// This class implements an UDP socket.
+{
+public:
+	DatagramSocketImpl();
+		/// Creates an unconnected, unbound datagram socket.
+
+	explicit DatagramSocketImpl(SocketAddress::Family family);
+		/// Creates an unconnected datagram socket.
+		///
+		/// The socket will be created for the
+		/// given address family.
+
+	DatagramSocketImpl(poco_socket_t sockfd);
+		/// Creates a StreamSocketImpl using the given native socket.
+		
+protected:
+	void init(int af);
+	
+	~DatagramSocketImpl();
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_DatagramSocketImpl_INCLUDED
diff --git a/Poco/Net/DialogSocket.h b/Poco/Net/DialogSocket.h
new file mode 100644
index 0000000..ca47b73
--- /dev/null
+++ b/Poco/Net/DialogSocket.h
@@ -0,0 +1,211 @@
+//
+// DialogSocket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  DialogSocket
+//
+// Definition of the DialogSocket class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_DialogSocket_INCLUDED
+#define Net_DialogSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/StreamSocket.h"
+#include <cstdlib>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API DialogSocket: public StreamSocket
+	/// DialogSocket is a subclass of StreamSocket that
+	/// can be used for implementing request-response
+	/// based client server connections.
+	///
+	/// A request is always a single-line command terminated
+	/// by CR-LF.
+	///
+	/// A response can either be a single line of text terminated
+	/// by CR-LF, or multiple lines of text in the format used
+	/// by the FTP and SMTP protocols.
+	///
+	/// Limited support for the TELNET protocol (RFC 854) is
+	/// available.
+	///
+	/// Warning: Do not call receiveBytes() on a DialogSocket.
+	/// Due to internal buffering in DialogSocket, receiveBytes()
+	/// may return an unexpected result and interfere with
+	/// DialogSocket's buffering. Use receiveRawBytes() instead.
+{
+public:
+	DialogSocket();
+		/// Creates an unconnected stream socket.
+		///
+		/// Before sending or receiving data, the socket
+		/// must be connected with a call to connect().
+
+	explicit DialogSocket(const SocketAddress& address);
+		/// Creates a stream socket and connects it to
+		/// the socket specified by address.
+
+	DialogSocket(const Socket& socket);
+		/// Creates the DialogSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a StreamSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	DialogSocket(const DialogSocket& socket);
+		/// Creates the DialogSocket as copy of another dialog socket.
+
+	~DialogSocket();
+		/// Destroys the DialogSocket.
+
+	DialogSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	DialogSocket& operator = (const DialogSocket& socket);
+		/// Assignment operator.
+		
+	void sendByte(unsigned char ch);
+		/// Sends a single byte over the socket connection.
+
+	void sendString(const char* str);
+		/// Sends the given null-terminated string over
+		/// the socket connection.
+
+	void sendString(const std::string& str);
+		/// Sends the given string over the socket connection.
+
+	void sendMessage(const std::string& message);
+		/// Appends a CR-LF sequence to the message and sends it
+		/// over the socket connection.
+
+	void sendMessage(const std::string& message, const std::string& arg);
+		/// Concatenates message and arg, separated by a space, appends a
+		/// CR-LF sequence, and sends the result over the socket connection.
+
+	void sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2);
+		/// Concatenates message and args, separated by a space, appends a
+		/// CR-LF sequence, and sends the result over the socket connection.
+		
+	bool receiveMessage(std::string& message);
+		/// Receives a single-line message, terminated by CR-LF,
+		/// from the socket connection and appends it to response.
+		/// 
+		/// Returns true if a message has been read or false if
+		/// the connection has been closed by the peer.
+	
+	int receiveStatusMessage(std::string& message);
+		/// Receives a single-line or multi-line response from
+		/// the socket connection. The format must be according to
+		/// one of the response formats specified in the FTP (RFC 959) 
+		/// or SMTP (RFC 2821) specifications.
+		///
+		/// The first line starts with a 3-digit status code.
+		/// Following the status code is either a space character (' ' ) 
+		/// (in case of a single-line response) or a minus character ('-')
+		/// in case of a multi-line response. The following lines can have
+		/// a three-digit status code followed by a minus-sign and some
+		/// text, or some arbitrary text only. The last line again begins
+		/// with a three-digit status code (which must be the same as the
+		/// one in the first line), followed by a space and some arbitrary 
+		/// text. All lines must be terminated by a CR-LF sequence.
+		///
+		/// The response contains all response lines, separated by a newline
+		/// character, including the status code. The status code is returned.
+		/// If the response line does not contain a status code, 0 is returned.
+	
+	int get();
+		/// Reads one character from the connection.
+		///
+		/// Returns -1 (EOF_CHAR) if no more characters are available.
+
+	int peek();
+		/// Returns the character that would be returned by the next call
+		/// to get(), without actually extracting the character from the
+		/// buffer.
+		///
+		/// Returns -1 (EOF_CHAR) if no more characters are available.
+
+	int receiveRawBytes(void* buffer, int length);
+		/// Read up to length bytes from the connection and place
+		/// them into buffer. If there are data bytes in the internal
+		/// buffer, these bytes are returned first.
+		///
+		/// Use this member function instead of receiveBytes().
+		///
+		/// Returns the number of bytes read, which may be
+		/// less than requested.
+
+	void synch();
+		/// Sends a TELNET SYNCH signal over the connection.
+		///
+		/// According to RFC 854, a TELNET_DM char is sent
+		/// via sendUrgent().
+		
+	void sendTelnetCommand(unsigned char command);
+		/// Sends a TELNET command sequence (TELNET_IAC followed
+		/// by the given command) over the connection.
+
+	void sendTelnetCommand(unsigned char command, unsigned char arg);
+		/// Sends a TELNET command sequence (TELNET_IAC followed
+		/// by the given command, followed by arg) over the connection.
+
+	enum TelnetCodes
+	{
+		TELNET_SE   = 240,
+		TELNET_NOP  = 241,
+		TELNET_DM   = 242,
+		TELNET_BRK  = 243,
+		TELNET_IP   = 244,
+		TELNET_AO   = 245,
+		TELNET_AYT  = 246,
+		TELNET_EC   = 247,
+		TELNET_EL   = 248,
+		TELNET_GA   = 249,
+		TELNET_SB   = 250,
+		TELNET_WILL = 251,
+		TELNET_WONT = 252,
+		TELNET_DO   = 253,
+		TELNET_DONT = 254,
+		TELNET_IAC  = 255
+	};
+
+protected:
+	void allocBuffer();
+	void refill();
+	bool receiveLine(std::string& line, std::size_t lineLengthLimit = 0);
+	int receiveStatusLine(std::string& line, std::size_t lineLengthLimit = 0);
+
+private:
+	enum
+	{
+		RECEIVE_BUFFER_SIZE = 1024,
+		MAX_LINE_LENGTH     = 4096,
+		EOF_CHAR            = -1
+	};
+	
+	char* _pBuffer;
+	char* _pNext;
+	char* _pEnd;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_DialogSocket_INCLUDED
diff --git a/Poco/Net/FTPClientSession.h b/Poco/Net/FTPClientSession.h
new file mode 100644
index 0000000..1750cfc
--- /dev/null
+++ b/Poco/Net/FTPClientSession.h
@@ -0,0 +1,403 @@
+//
+// FTPClientSession.h
+//
+// Library: Net
+// Package: FTP
+// Module:  FTPClientSession
+//
+// Definition of the FTPClientSession class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_FTPClientSession_INCLUDED
+#define Net_FTPClientSession_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/DialogSocket.h"
+#include "Poco/Timespan.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class SocketStream;
+
+
+class Net_API FTPClientSession
+	/// This class implements an File Transfer Protocol
+	/// (FTP, RFC 959) client.
+	///
+	/// Most of the features of the FTP protocol, as specified
+	/// in RFC 959, are supported. Not supported are EBCDIC and
+	/// LOCAL data types and format control and structured files.
+	///
+	/// Also supported are the EPRT and EPSV commands from
+	/// RFC 1738 (FTP Extensions for IPv6 and NAT).
+	/// The client will first attempt to use the EPRT and EPSV
+	/// commands. If the server does not supports these commands,
+	/// the client will fall back to PORT and PASV.
+{
+public:
+	enum
+	{
+		FTP_PORT = 21
+	};
+	
+	enum FileType
+	{
+		TYPE_TEXT,   // TYPE A (ASCII)
+		TYPE_BINARY  // TYPE I (Image)
+	};
+	
+	FTPClientSession();
+		/// Creates an FTPClientSession.
+		///
+		/// Passive mode will be used for data transfers.
+
+	explicit FTPClientSession(const StreamSocket& socket);
+		/// Creates an FTPClientSession using the given
+		/// connected socket for the control connection.
+		///
+		/// Passive mode will be used for data transfers.
+		
+	FTPClientSession(const std::string& host,
+		Poco::UInt16 port = FTP_PORT,
+		const std::string& username = "",
+		const std::string& password = "");
+		/// Creates an FTPClientSession using a socket connected
+		/// to the given host and port. If username is supplied,
+		/// login is attempted.
+		///
+		/// Passive mode will be used for data transfers.
+		
+	virtual ~FTPClientSession();
+		/// Destroys the FTPClientSession.
+	
+	void setTimeout(const Poco::Timespan& timeout);
+		/// Sets the timeout for socket operations.
+		
+	Poco::Timespan getTimeout() const;
+		/// Returns the timeout for socket operations.
+
+	void setPassive(bool flag, bool useRFC1738 = true);
+		/// Enables (default) or disables FTP passive mode for this session.
+		///
+		/// If useRFC1738 is true (the default), the RFC 1738
+		/// EPSV command is used (with a fallback to PASV if EPSV fails)
+		/// for switching to passive mode. The same applies to
+		/// EPRT and PORT for active connections.
+		
+	bool getPassive() const;
+		/// Returns true iff passive mode is enabled for this connection.
+		
+	void open(const std::string& host,
+		Poco::UInt16 port,
+		const std::string& username = "",
+		const std::string& password = "");
+		/// Opens the FTP connection to the given host and port.
+		/// If username is supplied, login is attempted.
+
+	void login(const std::string& username, const std::string& password);
+		/// Authenticates the user against the FTP server. Must be
+		/// called before any other commands (except QUIT) can be sent.
+		///
+		/// Sends a USER command followed by a PASS command with the
+		/// respective arguments to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void logout();
+
+	void close();
+		/// Sends a QUIT command and closes the connection to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+	
+	std::string systemType();
+		/// Returns the system type of the FTP server.
+		///
+		/// Sends a SYST command to the server and returns the result.
+	
+	void setFileType(FileType type);
+		/// Sets the file type for transferring files.
+		///
+		/// Sends a TYPE command with a corresponding argument to the
+		/// server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	FileType getFileType() const;
+		/// Returns the file type for transferring files.
+
+	void setWorkingDirectory(const std::string& path);
+		/// Changes the current working directory on the server.
+		///
+		/// Sends a CWD command with the given path as argument to the 
+		/// server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	std::string getWorkingDirectory();
+		/// Returns the current working directory on the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+		
+	void cdup();
+		/// Moves one directory up from the current working directory
+		/// on the server.
+		///
+		/// Sends a CDUP command to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+		
+	void rename(const std::string& oldName, const std::string& newName);
+		/// Renames the file on the server given by oldName to newName.
+		///
+		/// Sends a RNFR command, followed by a RNTO command to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+		
+	void remove(const std::string& path);
+		/// Deletes the file specified by path on the server.
+		///
+		/// Sends a DELE command with path as argument to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void createDirectory(const std::string& path);
+		/// Creates a new directory with the given path on the server.
+		///
+		/// Sends a MKD command with path as argument to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void removeDirectory(const std::string& path);
+		/// Removes the directory specified by path from the server.
+		///
+		/// Sends a RMD command with path as argument to the server.
+		///
+		/// Throws a FTPException in case of a FTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	std::istream& beginDownload(const std::string& path);
+		/// Starts downloading the file with the given name.
+		/// After all data has been read from the returned stream,
+		/// endDownload() must be called to finish the download.
+		///
+		/// A stream for reading the file's content is returned.
+		/// The stream is valid until endDownload() is called.
+		///
+		/// Creates a data connection between the client and the
+		/// server. If passive mode is on, then the server waits for
+		/// a connection request from the client. Otherwise, the
+		/// client waits for a connection request from the server.
+		/// After establishing the data connection, a SocketStream
+		/// for transferring the data is created.
+		///
+		/// If ASCII transfer mode is selected, the caller is
+		/// responsible for converting the received data to
+		/// the native text file format.
+		/// The InputLineEndingConverter class from the Foundation
+		/// library can be used for that purpose.
+		
+	void endDownload();
+		/// Must be called to complete a download initiated with
+		/// beginDownload().
+		
+	std::ostream& beginUpload(const std::string& path);
+		/// Starts uploading the file with the given name.
+		/// After all data has been written to the returned stream,
+		/// endUpload() must be called to finish the upload.
+		///
+		/// A stream for reading the file's content is returned.
+		/// The stream is valid until endUpload() is called.
+		///
+		/// Creates a data connection between the client and the
+		/// server. If passive mode is on, then the server waits for
+		/// a connection request from the client. Otherwise, the
+		/// client waits for a connection request from the server.
+		/// After establishing the data connection, a SocketStream
+		/// for transferring the data is created.
+		///
+		/// If ASCII transfer mode is selected, the caller is
+		/// responsible for converting the data to be sent
+		/// into network (CR-LF line endings) format.
+		/// The OutputLineEndingConverter class from the Foundation
+		/// library can be used for that purpose.
+
+	void endUpload();
+		/// Must be called to complete an upload initiated with
+		/// beginUpload().
+
+	std::istream& beginList(const std::string& path = "", bool extended = false);
+		/// Starts downloading a directory listing.
+		/// After all data has been read from the returned stream,
+		/// endList() must be called to finish the download.
+		///
+		/// A stream for reading the directory data is returned.
+		/// The stream is valid until endList() is called.
+		///
+		/// Optionally, a path to a directory or file can be specified.
+		/// According to the FTP protocol, if a path to a filename is
+		/// given, only information for the specific file is returned.
+		/// If a path to a directory is given, a listing of that directory
+		/// is returned. If no path is given, a listing of the current
+		/// working directory is returned.
+		///
+		/// If extended is false, only a filenames (one per line) are
+		/// returned. Otherwise, a full directory listing including
+		/// file attributes is returned. The format of this listing
+		/// depends on the FTP server. No attempt is made to interpret
+		/// this data.
+		///
+		/// Creates a data connection between the client and the
+		/// server. If passive mode is on, then the server waits for
+		/// a connection request from the client. Otherwise, the
+		/// client waits for a connection request from the server.
+		/// After establishing the data connection, a SocketStream
+		/// for transferring the data is created.
+		
+	void endList();
+		/// Must be called to complete a directory listing download 
+		/// initiated with beginList().
+
+	void abort();
+		/// Aborts the download or upload currently in progress.
+		///
+		/// Sends a TELNET IP/SYNCH sequence, followed by an ABOR
+		/// command to the server.
+		///
+		/// A separate call to endDownload() or endUpload() is
+		/// not necessary.
+		
+	int sendCommand(const std::string& command, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+
+	int sendCommand(const std::string& command, const std::string& arg, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+
+	bool isOpen() const;
+		/// Returns true if the connection with FTP server is opened.
+
+	bool isLoggedIn() const;
+		/// Returns true if the session is logged in.
+
+protected:
+	enum StatusClass
+	{
+		FTP_POSITIVE_PRELIMINARY  = 1,
+		FTP_POSITIVE_COMPLETION   = 2,
+		FTP_POSITIVE_INTERMEDIATE = 3,
+		FTP_TRANSIENT_NEGATIVE    = 4,
+		FTP_PERMANENT_NEGATIVE    = 5
+	};
+	enum
+	{
+		DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations	
+	};
+
+	static bool isPositivePreliminary(int status);
+	static bool isPositiveCompletion(int status);
+	static bool isPositiveIntermediate(int status);
+	static bool isTransientNegative(int status);
+	static bool isPermanentNegative(int status);
+	std::string extractPath(const std::string& response);
+	StreamSocket establishDataConnection(const std::string& command, const std::string& arg);
+	StreamSocket activeDataConnection(const std::string& command, const std::string& arg);
+	StreamSocket passiveDataConnection(const std::string& command, const std::string& arg);
+	void sendPortCommand(const SocketAddress& addr);
+	SocketAddress sendPassiveCommand();
+	bool sendEPRT(const SocketAddress& addr);
+	void sendPORT(const SocketAddress& addr);
+	bool sendEPSV(SocketAddress& addr);
+	void sendPASV(SocketAddress& addr);
+	void parseAddress(const std::string& str, SocketAddress& addr);
+	void parseExtAddress(const std::string& str, SocketAddress& addr);
+	void endTransfer();
+	
+private:
+	FTPClientSession(const FTPClientSession&);
+	FTPClientSession& operator = (const FTPClientSession&);
+		
+	std::string    _host;
+	Poco::UInt16   _port;
+	DialogSocket*  _pControlSocket;
+	SocketStream*  _pDataStream;
+	bool	   _passiveMode;
+	FileType       _fileType;
+	bool	   _supports1738;
+	bool	   _serverReady;
+	bool	   _isLoggedIn;
+	Poco::Timespan _timeout;
+};
+
+
+//
+// inlines
+//
+inline bool FTPClientSession::isPositivePreliminary(int status)
+{
+	return status/100 == FTP_POSITIVE_PRELIMINARY;
+}
+
+
+inline bool FTPClientSession::isPositiveCompletion(int status)
+{
+	return status/100 == FTP_POSITIVE_COMPLETION;
+}
+
+
+inline bool FTPClientSession::isPositiveIntermediate(int status)
+{
+	return status/100 == FTP_POSITIVE_INTERMEDIATE;
+}
+
+
+inline bool FTPClientSession::isTransientNegative(int status)
+{
+	return status/100 == FTP_TRANSIENT_NEGATIVE;
+}
+
+
+inline bool FTPClientSession::isPermanentNegative(int status)
+{
+	return status/100 == FTP_PERMANENT_NEGATIVE;
+}
+
+
+inline bool FTPClientSession::isOpen() const
+{
+	return _pControlSocket != 0;
+}
+
+
+inline bool FTPClientSession::isLoggedIn() const
+{
+	return _isLoggedIn;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_FTPClientSession_INCLUDED
diff --git a/Poco/Net/FTPStreamFactory.h b/Poco/Net/FTPStreamFactory.h
new file mode 100644
index 0000000..4f33f19
--- /dev/null
+++ b/Poco/Net/FTPStreamFactory.h
@@ -0,0 +1,120 @@
+//
+// FTPStreamFactory.h
+//
+// Library: Net
+// Package: FTP
+// Module:  FTPStreamFactory
+//
+// Definition of the FTPStreamFactory class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_FTPStreamFactory_INCLUDED
+#define Net_FTPStreamFactory_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPSession.h"
+#include "Poco/URIStreamFactory.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API FTPPasswordProvider
+	/// The base class for all password providers.
+	/// An instance of a subclass of this class can be
+	/// registered with the FTPStreamFactory to 
+	/// provide a password
+{
+public:
+	virtual std::string password(const std::string& username, const std::string& host) = 0;
+		/// Provide the password for the given user on the given host.
+
+protected:
+	FTPPasswordProvider();
+	virtual ~FTPPasswordProvider();
+};
+
+
+class Net_API FTPStreamFactory: public Poco::URIStreamFactory
+	/// An implementation of the URIStreamFactory interface
+	/// that handles File Transfer Protocol (ftp) URIs.
+	///
+	/// The URI's path may end with an optional type specification
+	/// in the form (;type=<typecode>), where <typecode> is
+	/// one of a, i or d. If type=a, the file identified by the path
+	/// is transferred in ASCII (text) mode. If type=i, the file
+	/// is transferred in Image (binary) mode. If type=d, a directory
+	/// listing (in NLST format) is returned. This corresponds with
+	/// the FTP URL format specified in RFC 1738.
+	///
+	/// If the URI does not contain a username and password, the
+	/// username "anonymous" and the password "
+{
+public:
+	FTPStreamFactory();
+		/// Creates the FTPStreamFactory.
+
+	~FTPStreamFactory();
+		/// Destroys the FTPStreamFactory.
+		
+	std::istream* open(const Poco::URI& uri);
+		/// Creates and opens a HTTP stream for the given URI.
+		/// The URI must be a ftp://... URI.
+		///
+		/// Throws a NetException if anything goes wrong.
+		
+	static void setAnonymousPassword(const std::string& password);
+		/// Sets the password used for anonymous FTP.
+		///
+		/// WARNING: Setting the anonymous password is not
+		/// thread-safe, so it's best to call this method
+		/// during application initialization, before the
+		/// FTPStreamFactory is used for the first time.
+		
+	static const std::string& getAnonymousPassword();
+		/// Returns the password used for anonymous FTP.
+		
+	static void setPasswordProvider(FTPPasswordProvider* pProvider);
+		/// Sets the FTPPasswordProvider. If NULL is given,
+		/// no password provider is used.
+		///
+		/// WARNING: Setting the password provider is not
+		/// thread-safe, so it's best to call this method
+		/// during application initialization, before the
+		/// FTPStreamFactory is used for the first time.
+		
+	static FTPPasswordProvider* getPasswordProvider();
+		/// Returns the FTPPasswordProvider currently in use,
+		/// or NULL if no one has been set.
+
+	static void registerFactory();
+		/// Registers the FTPStreamFactory with the
+		/// default URIStreamOpener instance.
+
+	static void unregisterFactory();
+		/// Unregisters the FTPStreamFactory with the
+		/// default URIStreamOpener instance.
+
+protected:
+	static void splitUserInfo(const std::string& userInfo, std::string& username, std::string& password);
+	static void getUserInfo(const Poco::URI& uri, std::string& username, std::string& password);
+	static void getPathAndType(const Poco::URI& uri, std::string& path, char& type);
+	
+private:
+	static std::string          _anonymousPassword;
+	static FTPPasswordProvider* _pPasswordProvider;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_FTPStreamFactory_INCLUDED
diff --git a/Poco/Net/FilePartSource.h b/Poco/Net/FilePartSource.h
new file mode 100644
index 0000000..0567185
--- /dev/null
+++ b/Poco/Net/FilePartSource.h
@@ -0,0 +1,77 @@
+//
+// FilePartSource.h
+//
+// Library: Net
+// Package: Messages
+// Module:  FilePartSource
+//
+// Definition of the FilePartSource class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_FilePartSource_INCLUDED
+#define Net_FilePartSource_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/PartSource.h"
+#include "Poco/FileStream.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API FilePartSource: public PartSource
+	/// An implementation of PartSource for
+	/// plain files.
+{
+public:
+	FilePartSource(const std::string& path);
+		/// Creates the FilePartSource for the given path.
+		///
+		/// The MIME type is set to application/octet-stream.
+		///
+		/// Throws an OpenFileException if the file cannot be opened.
+	
+	FilePartSource(const std::string& path, const std::string& mediaType);
+		/// Creates the FilePartSource for the given
+		/// path and MIME type.
+		///
+		/// Throws an OpenFileException if the file cannot be opened.
+
+	FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType);
+		/// Creates the FilePartSource for the given
+		/// path and MIME type. The given filename is 
+		/// used as part filename (see filename()) only.
+		///
+		/// Throws an OpenFileException if the file cannot be opened.
+
+	~FilePartSource();
+		/// Destroys the FilePartSource.
+
+	std::istream& stream();
+		/// Returns a file input stream for the given file.
+		
+	const std::string& filename() const;
+		/// Returns the filename portion of the path.
+
+	std::streamsize getContentLength() const;
+		/// Returns the file size.
+
+private:
+	std::string _path;
+	std::string _filename;
+	Poco::FileInputStream _istr;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_FilePartSource_INCLUDED
diff --git a/Poco/Net/HTMLForm.h b/Poco/Net/HTMLForm.h
new file mode 100644
index 0000000..a4649dd
--- /dev/null
+++ b/Poco/Net/HTMLForm.h
@@ -0,0 +1,272 @@
+//
+// HTMLForm.h
+//
+// Library: Net
+// Package: HTML
+// Module:  HTMLForm
+//
+// Definition of the HTMLForm class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTMLForm_INCLUDED
+#define Net_HTMLForm_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/NameValueCollection.h"
+#include <ostream>
+#include <istream>
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+class PartHandler;
+class PartSource;
+
+
+class Net_API HTMLForm: public NameValueCollection
+	/// HTMLForm is a helper class for working with HTML forms,
+	/// both on the client and on the server side.
+	///
+	/// The maximum number of form fields can be restricted
+	/// by calling setFieldLimit(). This is useful to
+	/// defend against certain kinds of denial-of-service
+	/// attacks. The limit is only enforced when parsing
+	/// form data from a stream or string, not when adding
+	/// form fields programmatically. The default limit is 100.
+{
+public:
+	enum Options
+	{
+		OPT_USE_CONTENT_LENGTH = 0x01
+			/// Don't use Chunked Transfer-Encoding for multipart requests.
+	};
+
+	HTMLForm();
+		/// Creates an empty HTMLForm and sets the
+		/// encoding to "application/x-www-form-urlencoded".
+
+	explicit HTMLForm(const std::string& encoding);
+		/// Creates an empty HTMLForm that uses
+		/// the given encoding.
+		///
+		/// Encoding must be either "application/x-www-form-urlencoded"
+		/// (which is the default) or "multipart/form-data".
+
+	HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler);
+		/// Creates a HTMLForm from the given HTTP request.
+		///
+		/// Uploaded files are passed to the given PartHandler.
+
+	HTMLForm(const HTTPRequest& request, std::istream& requestBody);
+		/// Creates a HTMLForm from the given HTTP request.
+		///
+		/// Uploaded files are silently discarded.
+
+	explicit HTMLForm(const HTTPRequest& request);
+		/// Creates a HTMLForm from the given HTTP request.
+		///
+		/// The request must be a GET request and the form data
+		/// must be in the query string (URL encoded).
+		///
+		/// For POST requests, you must use one of the constructors
+		/// taking an additional input stream for the request body.
+
+	~HTMLForm();
+		/// Destroys the HTMLForm.
+
+	void setEncoding(const std::string& encoding);
+		/// Sets the encoding used for posting the form.
+		///
+		/// Encoding must be either "application/x-www-form-urlencoded"
+		/// (which is the default) or "multipart/form-data".
+
+	const std::string& getEncoding() const;
+		/// Returns the encoding used for posting the form.
+
+	void addPart(const std::string& name, PartSource* pSource);
+		/// Adds an part/attachment (file upload) to the form.
+		///
+		/// The form takes ownership of the PartSource and deletes it
+		/// when it is no longer needed.
+		///
+		/// The part will only be sent if the encoding
+		/// set for the form is "multipart/form-data"
+
+	void load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler);
+		/// Reads the form data from the given HTTP request.
+		///
+		/// Uploaded files are passed to the given PartHandler.
+
+	void load(const HTTPRequest& request, std::istream& requestBody);
+		/// Reads the form data from the given HTTP request.
+		///
+		/// Uploaded files are silently discarded.
+
+	void load(const HTTPRequest& request);
+		/// Reads the form data from the given HTTP request.
+		///
+		/// The request must be a GET request and the form data
+		/// must be in the query string (URL encoded).
+		///
+		/// For POST requests, you must use one of the overloads
+		/// taking an additional input stream for the request body.
+
+	void read(std::istream& istr, PartHandler& handler);
+		/// Reads the form data from the given input stream.
+		///
+		/// The form data read from the stream must be
+		/// in the encoding specified for the form.
+		///
+		/// Note that read() does not clear the form before
+		/// reading the new values.
+
+	void read(std::istream& istr);
+		/// Reads the URL-encoded form data from the given input stream.
+		///
+		/// Note that read() does not clear the form before
+		/// reading the new values.
+
+	void read(const std::string& queryString);
+		/// Reads the form data from the given HTTP query string.
+		///
+		/// Note that read() does not clear the form before
+		/// reading the new values.
+
+	void prepareSubmit(HTTPRequest& request, int options = 0);
+		/// Fills out the request object for submitting the form.
+		///
+		/// If the request method is GET, the encoded form is appended to the
+		/// request URI as query string. Otherwise (the method is
+		/// POST), the form's content type is set to the form's encoding.
+		/// The form's parameters must be written to the
+		/// request body separately, with a call to write.
+		/// If the request's HTTP version is HTTP/1.0:
+		///    - persistent connections are disabled
+		///    - the content transfer encoding is set to identity encoding
+		/// Otherwise, if the request's HTTP version is HTTP/1.1:
+		///    - the request's persistent connection state is left unchanged
+		///    - the content transfer encoding is set to chunked, unless
+		///      the OPT_USE_CONTENT_LENGTH is given in options
+		///
+		/// Note: Not using chunked transfer encoding for multipart forms
+		/// degrades performance, as the request content must be generated
+		/// twice, first to determine its size, then to actually send it.
+
+	std::streamsize calculateContentLength();
+		/// Calculate the content length for the form.
+		/// May be UNKNOWN_CONTENT_LENGTH if not possible
+		/// to calculate
+
+	void write(std::ostream& ostr, const std::string& boundary);
+		/// Writes the form data to the given output stream,
+		/// using the specified encoding.
+
+	void write(std::ostream& ostr);
+		/// Writes the form data to the given output stream,
+		/// using the specified encoding.
+
+	const std::string& boundary() const;
+		/// Returns the MIME boundary used for writing
+		/// multipart form data.
+
+	int getFieldLimit() const;
+		/// Returns the maximum number of header fields
+		/// allowed.
+		///
+		/// See setFieldLimit() for more information.
+
+	void setFieldLimit(int limit);
+		/// Sets the maximum number of header fields
+		/// allowed. This limit is used to defend certain
+		/// kinds of denial-of-service attacks.
+		/// Specify 0 for unlimited (not recommended).
+		///
+		/// The default limit is 100.
+
+	void setValueLengthLimit(int limit);
+		/// Sets the maximum size for form field values
+		/// stored as strings.
+
+	int getValueLengthLimit() const;
+		/// Returns the maximum size for form field values
+		/// stored as strings.
+
+	static const std::string ENCODING_URL;       /// "application/x-www-form-urlencoded"
+	static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
+	static const int         UNKNOWN_CONTENT_LENGTH;
+
+protected:
+	void readUrl(std::istream& istr);
+	void readMultipart(std::istream& istr, PartHandler& handler);
+	void writeUrl(std::ostream& ostr);
+	void writeMultipart(std::ostream& ostr);
+
+private:
+	HTMLForm(const HTMLForm&);
+	HTMLForm& operator = (const HTMLForm&);
+
+	enum Limits
+	{
+		DFL_FIELD_LIMIT = 100,
+		MAX_NAME_LENGTH  = 1024,
+		DFL_MAX_VALUE_LENGTH = 256*1024
+	};
+
+	struct Part
+	{
+		std::string name;
+		PartSource* pSource;
+	};
+
+	typedef std::vector<Part> PartVec;
+
+	int         _fieldLimit;
+	int         _valueLengthLimit;
+	std::string _encoding;
+	std::string _boundary;
+	PartVec     _parts;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTMLForm::getEncoding() const
+{
+	return _encoding;
+}
+
+
+inline const std::string& HTMLForm::boundary() const
+{
+	return _boundary;
+}
+
+
+inline int HTMLForm::getFieldLimit() const
+{
+	return _fieldLimit;
+}
+
+
+inline int HTMLForm::getValueLengthLimit() const
+{
+	return _valueLengthLimit;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTMLForm_INCLUDED
diff --git a/Poco/Net/HTTPAuthenticationParams.h b/Poco/Net/HTTPAuthenticationParams.h
new file mode 100644
index 0000000..492e2c4
--- /dev/null
+++ b/Poco/Net/HTTPAuthenticationParams.h
@@ -0,0 +1,103 @@
+//
+// HTTPAuthenticationParams.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPAuthenticationParams
+//
+// Definition of the HTTPAuthenticationParams class.
+//
+// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPAuthenticationParams_INCLUDED
+#define Net_HTTPAuthenticationParams_INCLUDED
+
+
+#include "Poco/Net/NameValueCollection.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+class HTTPResponse;
+
+
+class Net_API HTTPAuthenticationParams: public NameValueCollection
+	/// Collection of name-value pairs of HTTP authentication header (i.e.
+	/// "realm", "qop", "nonce" in case of digest authentication header).
+{
+public:
+	HTTPAuthenticationParams();
+		/// Creates an empty authentication parameters collection.
+
+	explicit HTTPAuthenticationParams(const std::string& authInfo);
+		/// See fromAuthInfo() documentation.
+
+	explicit HTTPAuthenticationParams(const HTTPRequest& request);
+		/// See fromRequest() documentation.
+
+	HTTPAuthenticationParams(const HTTPResponse& response, const std::string& header = WWW_AUTHENTICATE);
+		/// See fromResponse() documentation.
+
+	virtual ~HTTPAuthenticationParams();
+		/// Destroys the HTTPAuthenticationParams.
+
+	HTTPAuthenticationParams& operator = (const HTTPAuthenticationParams& authParams);
+		/// Assigns the content of another HTTPAuthenticationParams.
+
+	void fromAuthInfo(const std::string& authInfo);
+		/// Creates an HTTPAuthenticationParams by parsing authentication
+		/// information.
+
+	void fromRequest(const HTTPRequest& request);
+		/// Extracts authentication information from the request and creates
+		/// HTTPAuthenticationParams by parsing it.
+		///
+		/// Throws a NotAuthenticatedException if no authentication
+		/// information is contained in request.
+		/// Throws a InvalidArgumentException if authentication scheme is
+		/// unknown or invalid.
+
+	void fromResponse(const HTTPResponse& response, const std::string& header = WWW_AUTHENTICATE);
+		/// Extracts authentication information from the response and creates
+		/// HTTPAuthenticationParams by parsing it.
+		///
+		/// Throws a NotAuthenticatedException if no authentication
+		/// information is contained in response.
+		/// Throws a InvalidArgumentException if authentication scheme is
+		/// unknown or invalid.
+
+	void setRealm(const std::string& realm);
+		/// Sets the "realm" parameter to the provided string.
+
+	const std::string& getRealm() const;
+		/// Returns value of the "realm" parameter.
+		///
+		/// Throws NotFoundException is there is no "realm" set in the
+		/// HTTPAuthenticationParams.
+
+	std::string toString() const;
+		/// Formats the HTTPAuthenticationParams for inclusion in HTTP
+		/// request or response authentication header.
+
+	static const std::string REALM;
+	static const std::string WWW_AUTHENTICATE;
+	static const std::string PROXY_AUTHENTICATE;
+
+private:
+	void parse(std::string::const_iterator first, std::string::const_iterator last);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPAuthenticationParams_INCLUDED
diff --git a/Poco/Net/HTTPBasicCredentials.h b/Poco/Net/HTTPBasicCredentials.h
new file mode 100644
index 0000000..56894db
--- /dev/null
+++ b/Poco/Net/HTTPBasicCredentials.h
@@ -0,0 +1,123 @@
+//
+// HTTPBasicCredentials.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPBasicCredentials
+//
+// Definition of the HTTPBasicCredentials class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPBasicCredentials_INCLUDED
+#define Net_HTTPBasicCredentials_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+
+
+class Net_API HTTPBasicCredentials
+	/// This is a utility class for working with
+	/// HTTP Basic Authentication in HTTPRequest
+	/// objects.
+{
+public:
+	HTTPBasicCredentials();
+		/// Creates an empty HTTPBasicCredentials object.
+
+	HTTPBasicCredentials(const std::string& username, const std::string& password);
+		/// Creates a HTTPBasicCredentials object with the given username and password.
+
+	explicit HTTPBasicCredentials(const HTTPRequest& request);
+		/// Creates a HTTPBasicCredentials object with the authentication information
+		/// from the given request.
+		///
+		/// Throws a NotAuthenticatedException if the request does
+		/// not contain basic authentication information.
+
+	explicit HTTPBasicCredentials(const std::string& authInfo);
+		/// Creates a HTTPBasicCredentials object with the authentication information
+		/// in the given string. The authentication information can be extracted
+		/// from a HTTPRequest object by calling HTTPRequest::getCredentials().
+
+	~HTTPBasicCredentials();
+		/// Destroys the HTTPBasicCredentials.
+
+	void clear();
+		/// Clears both username and password.
+
+	void setUsername(const std::string& username);
+		/// Sets the username.
+
+	const std::string& getUsername() const;
+		/// Returns the username.
+
+	void setPassword(const std::string& password);
+		/// Sets the password.
+
+	const std::string& getPassword() const;
+		/// Returns the password.
+
+	bool empty() const;
+		/// Returns true if both username and password are empty, otherwise false.
+
+	void authenticate(HTTPRequest& request) const;
+		/// Adds authentication information to the given HTTPRequest.
+
+	void proxyAuthenticate(HTTPRequest& request) const;
+		/// Adds proxy authentication information to the given HTTPRequest.
+
+	static const std::string SCHEME;
+
+protected:
+	void parseAuthInfo(const std::string& authInfo);
+		/// Extracts username and password from Basic authentication info
+		/// by base64-decoding authInfo and splitting the resulting
+		/// string at the ':' delimiter.
+
+private:
+	HTTPBasicCredentials(const HTTPBasicCredentials&);
+	HTTPBasicCredentials& operator = (const HTTPBasicCredentials&);
+
+	std::string _username;
+	std::string _password;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPBasicCredentials::getUsername() const
+{
+	return _username;
+}
+
+
+inline const std::string& HTTPBasicCredentials::getPassword() const
+{
+	return _password;
+}
+
+
+inline bool HTTPBasicCredentials::empty() const
+{
+	return _username.empty() && _password.empty();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPBasicCredentials_INCLUDED
diff --git a/Poco/Net/HTTPBasicStreamBuf.h b/Poco/Net/HTTPBasicStreamBuf.h
new file mode 100644
index 0000000..0edbec3
--- /dev/null
+++ b/Poco/Net/HTTPBasicStreamBuf.h
@@ -0,0 +1,36 @@
+//
+// HTTPBasicStreamBuf.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPBasicStreamBuf
+//
+// Definition of the HTTPBasicStreamBuf class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPBasicStreamBuf_INCLUDED
+#define Net_HTTPBasicStreamBuf_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/BufferedStreamBuf.h"
+#include "Poco/Net/HTTPBufferAllocator.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+typedef Poco::BasicBufferedStreamBuf<char, std::char_traits<char>, HTTPBufferAllocator> HTTPBasicStreamBuf;
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPBasicStreamBuf_INCLUDED
diff --git a/Poco/Net/HTTPBufferAllocator.h b/Poco/Net/HTTPBufferAllocator.h
new file mode 100644
index 0000000..ce2039a
--- /dev/null
+++ b/Poco/Net/HTTPBufferAllocator.h
@@ -0,0 +1,50 @@
+//
+// HTTPBufferAllocator.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPBufferAllocator
+//
+// Definition of the HTTPBufferAllocator class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPBufferAllocator_INCLUDED
+#define Net_HTTPBufferAllocator_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/MemoryPool.h"
+#include <ios>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPBufferAllocator
+	/// A BufferAllocator for HTTP streams.
+{
+public:
+	static char* allocate(std::streamsize size);
+	static void deallocate(char* ptr, std::streamsize size);
+
+	enum
+	{
+		BUFFER_SIZE = 4096
+	};
+
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPBufferAllocator_INCLUDED
diff --git a/Poco/Net/HTTPChunkedStream.h b/Poco/Net/HTTPChunkedStream.h
new file mode 100644
index 0000000..7e140ed
--- /dev/null
+++ b/Poco/Net/HTTPChunkedStream.h
@@ -0,0 +1,105 @@
+//
+// HTTPChunkedStream.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPChunkedStream
+//
+// Definition of the HTTPChunkedStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPChunkedStream_INCLUDED
+#define Net_HTTPChunkedStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPBasicStreamBuf.h"
+#include "Poco/MemoryPool.h"
+#include <cstddef>
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPSession;
+
+
+class Net_API HTTPChunkedStreamBuf: public HTTPBasicStreamBuf
+	/// This is the streambuf class used for reading and writing
+	/// HTTP message bodies in chunked transfer coding.
+{
+public:
+	typedef HTTPBasicStreamBuf::openmode openmode;
+
+	HTTPChunkedStreamBuf(HTTPSession& session, openmode mode);
+	~HTTPChunkedStreamBuf();
+	void close();
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	HTTPSession&    _session;
+	openmode        _mode;
+	std::streamsize _chunk;
+	std::string     _chunkBuffer;
+};
+
+
+class Net_API HTTPChunkedIOS: public virtual std::ios
+	/// The base class for HTTPInputStream.
+{
+public:
+	HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode);
+	~HTTPChunkedIOS();
+	HTTPChunkedStreamBuf* rdbuf();
+
+protected:
+	HTTPChunkedStreamBuf _buf;
+};
+
+
+class Net_API HTTPChunkedInputStream: public HTTPChunkedIOS, public std::istream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPChunkedInputStream(HTTPSession& session);
+	~HTTPChunkedInputStream();
+	
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+class Net_API HTTPChunkedOutputStream: public HTTPChunkedIOS, public std::ostream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPChunkedOutputStream(HTTPSession& session);
+	~HTTPChunkedOutputStream();
+
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPChunkedStream_INCLUDED
diff --git a/Poco/Net/HTTPClientSession.h b/Poco/Net/HTTPClientSession.h
new file mode 100644
index 0000000..2f2e21c
--- /dev/null
+++ b/Poco/Net/HTTPClientSession.h
@@ -0,0 +1,391 @@
+//
+// HTTPClientSession.h
+//
+// Library: Net
+// Package: HTTPClient
+// Module:  HTTPClientSession
+//
+// Definition of the HTTPClientSession class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPClientSession_INCLUDED
+#define Net_HTTPClientSession_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPSession.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/SharedPtr.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+class HTTPResponse;
+
+
+class Net_API HTTPClientSession: public HTTPSession
+	/// This class implements the client-side of
+	/// a HTTP session.
+	///
+	/// To send a HTTP request to a HTTP server, first
+	/// instantiate a HTTPClientSession object and
+	/// specify the server's host name and port number.
+	///
+	/// Then create a HTTPRequest object, fill it accordingly,
+	/// and pass it as argument to the sendRequest() method.
+	///
+	/// sendRequest() will return an output stream that can
+	/// be used to send the request body, if there is any.
+	///
+	/// After you are done sending the request body, create
+	/// a HTTPResponse object and pass it to receiveResponse().
+	///
+	/// This will return an input stream that can be used to
+	/// read the response body.
+	///
+	/// See RFC 2616 <http://www.faqs.org/rfcs/rfc2616.html> for more
+	/// information about the HTTP protocol.
+	///
+	/// Proxies and proxy authorization (only HTTP Basic Authorization)
+	/// is supported. Use setProxy() and setProxyCredentials() to
+	/// set up a session through a proxy.
+{
+public:
+	struct ProxyConfig
+		/// HTTP proxy server configuration.
+	{
+		ProxyConfig():
+			port(HTTP_PORT)
+		{
+		}
+
+		std::string  host;
+			/// Proxy server host name or IP address.
+		Poco::UInt16 port;
+			/// Proxy server TCP port.
+		std::string  username;
+			/// Proxy server username.
+		std::string  password;
+			/// Proxy server password.
+		std::string  nonProxyHosts;
+			/// A regular expression defining hosts for which the proxy should be bypassed,
+			/// e.g. "localhost|127\.0\.0\.1|192\.168\.0\.\d+". Can also be an empty
+			/// string to disable proxy bypassing.
+	};
+
+	HTTPClientSession();
+		/// Creates an unconnected HTTPClientSession.
+
+	explicit HTTPClientSession(const StreamSocket& socket);
+		/// Creates a HTTPClientSession using the given socket.
+		/// The socket must not be connected. The session
+		/// takes ownership of the socket.
+
+	explicit HTTPClientSession(const SocketAddress& address);
+		/// Creates a HTTPClientSession using the given address.
+
+	HTTPClientSession(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT);
+		/// Creates a HTTPClientSession using the given host and port.
+
+	HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig);
+		/// Creates a HTTPClientSession using the given host, port and proxy configuration.
+
+	virtual ~HTTPClientSession();
+		/// Destroys the HTTPClientSession and closes
+		/// the underlying socket.
+
+	void setHost(const std::string& host);
+		/// Sets the host name of the target HTTP server.
+		///
+		/// The host must not be changed once there is an
+		/// open connection to the server.
+
+	const std::string& getHost() const;
+		/// Returns the host name of the target HTTP server.
+
+	void setPort(Poco::UInt16 port);
+		/// Sets the port number of the target HTTP server.
+		///
+		/// The port number must not be changed once there is an
+		/// open connection to the server.
+
+	Poco::UInt16 getPort() const;
+		/// Returns the port number of the target HTTP server.
+
+	void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT);
+		/// Sets the proxy host name and port number.
+
+	void setProxyHost(const std::string& host);
+		/// Sets the host name of the proxy server.
+
+	void setProxyPort(Poco::UInt16 port);
+		/// Sets the port number of the proxy server.
+
+	const std::string& getProxyHost() const;
+		/// Returns the proxy host name.
+
+	Poco::UInt16 getProxyPort() const;
+		/// Returns the proxy port number.
+
+	void setProxyCredentials(const std::string& username, const std::string& password);
+		/// Sets the username and password for proxy authentication.
+		/// Only Basic authentication is supported.
+
+	void setProxyUsername(const std::string& username);
+		/// Sets the username for proxy authentication.
+		/// Only Basic authentication is supported.
+
+	const std::string& getProxyUsername() const;
+		/// Returns the username for proxy authentication.
+
+	void setProxyPassword(const std::string& password);
+		/// Sets the password for proxy authentication.
+		/// Only Basic authentication is supported.
+
+	const std::string& getProxyPassword() const;
+		/// Returns the password for proxy authentication.
+
+	void setProxyConfig(const ProxyConfig& config);
+		/// Sets the proxy configuration.
+
+	const ProxyConfig& getProxyConfig() const;
+		/// Returns the proxy configuration.
+
+	static void setGlobalProxyConfig(const ProxyConfig& config);
+		/// Sets the global proxy configuration.
+		///
+		/// The global proxy configuration is used by all HTTPClientSession
+		/// instances, unless a different proxy configuration is explicitly set.
+		///
+		/// Warning: Setting the global proxy configuration is not thread safe.
+		/// The global proxy configuration should be set at start up, before
+		/// the first HTTPClientSession instance is created.
+
+	static const ProxyConfig& getGlobalProxyConfig();
+		/// Returns the global proxy configuration.
+
+	void setKeepAliveTimeout(const Poco::Timespan& timeout);
+		/// Sets the connection timeout for HTTP connections.
+
+	const Poco::Timespan& getKeepAliveTimeout() const;
+		/// Returns the connection timeout for HTTP connections.
+
+	virtual std::ostream& sendRequest(HTTPRequest& request);
+		/// Sends the header for the given HTTP request to
+		/// the server.
+		///
+		/// The HTTPClientSession will set the request's
+		/// Host and Keep-Alive headers accordingly.
+		///
+		/// The returned output stream can be used to write
+		/// the request body. The stream is valid until
+		/// receiveResponse() is called or the session
+		/// is destroyed.
+		///
+		/// In case a network or server failure happens
+		/// while writing the request body to the returned stream,
+		/// the stream state will change to bad or fail. In this
+		/// case, reset() should be called if the session will
+		/// be reused and persistent connections are enabled
+		/// to ensure a new connection will be set up
+		/// for the next request.
+
+	virtual std::istream& receiveResponse(HTTPResponse& response);
+		/// Receives the header for the response to the previous
+		/// HTTP request.
+		///
+		/// The returned input stream can be used to read
+		/// the response body. The stream is valid until
+		/// sendRequest() is called or the session is
+		/// destroyed.
+		///
+		/// It must be ensured that the response stream
+		/// is fully consumed before sending a new request
+		/// and persistent connections are enabled. Otherwise,
+		/// the unread part of the response body may be treated as
+		/// part of the next request's response header, resulting
+		/// in a Poco::Net::MessageException being thrown.
+		///
+		/// In case a network or server failure happens
+		/// while reading the response body from the returned stream,
+		/// the stream state will change to bad or fail. In this
+		/// case, reset() should be called if the session will
+		/// be reused and persistent connections are enabled
+		/// to ensure a new connection will be set up
+		/// for the next request.
+
+	virtual bool peekResponse(HTTPResponse& response);
+		/// If the request contains a "Expect: 100-continue" header,
+		/// (see HTTPRequest::setExpectContinue()) this method can be
+		/// used to check whether the server has sent a 100 Continue response
+		/// before continuing with the request, i.e. sending the request body,
+		/// after calling sendRequest().
+		///
+		/// Returns true if the server has responded with 100 Continue,
+		/// otherwise false. The HTTPResponse object contains the
+		/// response sent by the server.
+		///
+		/// In any case, receiveResponse() must be called afterwards as well in
+		/// order to complete the request. The same HTTPResponse object
+		/// passed to peekResponse() must also be passed to receiveResponse().
+		///
+		/// This method should only be called if the request contains
+		/// a "Expect: 100-continue" header.
+
+	void flushRequest();
+		/// Flushes the request stream.
+		///
+		/// Normally this method does not need to be called.
+		/// It can be used to ensure the request has been
+		/// fully sent if receiveResponse() is not called, e.g.,
+		/// because the underlying socket will be detached.
+
+	void reset();
+		/// Resets the session and closes the socket.
+		///
+		/// The next request will initiate a new connection,
+		/// even if persistent connections are enabled.
+		///
+		/// This should be called whenever something went
+		/// wrong when sending a request (e.g., sendRequest()
+		/// or receiveResponse() throws an exception, or
+		/// the request or response stream changes into
+		/// fail or bad state, but not eof state).
+
+	virtual bool secure() const;
+		/// Return true iff the session uses SSL or TLS,
+		/// or false otherwise.
+
+	bool bypassProxy() const;
+		/// Returns true if the proxy should be bypassed
+		/// for the current host.
+
+protected:
+	enum
+	{
+		DEFAULT_KEEP_ALIVE_TIMEOUT = 8
+	};
+
+	void reconnect();
+		/// Connects the underlying socket to the HTTP server.
+
+	int write(const char* buffer, std::streamsize length);
+		/// Tries to re-connect if keep-alive is on.
+
+	virtual std::string proxyRequestPrefix() const;
+		/// Returns the prefix prepended to the URI for proxy requests
+		/// (e.g., "http://myhost.com").
+
+	virtual bool mustReconnect() const;
+		/// Checks if we can reuse a persistent connection.
+
+	virtual void proxyAuthenticate(HTTPRequest& request);
+		/// Sets the proxy credentials (Proxy-Authorization header), if
+		/// proxy username and password have been set.
+
+	void proxyAuthenticateImpl(HTTPRequest& request);
+		/// Sets the proxy credentials (Proxy-Authorization header), if
+		/// proxy username and password have been set.
+
+	StreamSocket proxyConnect();
+		/// Sends a CONNECT request to the proxy server and returns
+		/// a StreamSocket for the resulting connection.
+
+	void proxyTunnel();
+		/// Calls proxyConnect() and attaches the resulting StreamSocket
+		/// to the HTTPClientSession.
+
+private:
+	std::string     _host;
+	Poco::UInt16    _port;
+	ProxyConfig     _proxyConfig;
+	Poco::Timespan  _keepAliveTimeout;
+	Poco::Timestamp _lastRequest;
+	bool            _reconnect;
+	bool            _mustReconnect;
+	bool            _expectResponseBody;
+	bool            _responseReceived;
+	Poco::SharedPtr<std::ostream> _pRequestStream;
+	Poco::SharedPtr<std::istream> _pResponseStream;
+
+	static ProxyConfig _globalProxyConfig;
+
+	HTTPClientSession(const HTTPClientSession&);
+	HTTPClientSession& operator = (const HTTPClientSession&);
+
+	friend class WebSocket;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPClientSession::getHost() const
+{
+	return _host;
+}
+
+
+inline Poco::UInt16 HTTPClientSession::getPort() const
+{
+	return _port;
+}
+
+
+inline const std::string& HTTPClientSession::getProxyHost() const
+{
+	return _proxyConfig.host;
+}
+
+
+inline Poco::UInt16 HTTPClientSession::getProxyPort() const
+{
+	return _proxyConfig.port;
+}
+
+
+inline const std::string& HTTPClientSession::getProxyUsername() const
+{
+	return _proxyConfig.username;
+}
+
+
+inline const std::string& HTTPClientSession::getProxyPassword() const
+{
+	return _proxyConfig.password;
+}
+
+
+inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getProxyConfig() const
+{
+	return _proxyConfig;
+}
+
+
+inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getGlobalProxyConfig()
+{
+	return _globalProxyConfig;
+}
+
+
+inline const Poco::Timespan& HTTPClientSession::getKeepAliveTimeout() const
+{
+	return _keepAliveTimeout;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPClientSession_INCLUDED
diff --git a/Poco/Net/HTTPCookie.h b/Poco/Net/HTTPCookie.h
new file mode 100644
index 0000000..c7c47b2
--- /dev/null
+++ b/Poco/Net/HTTPCookie.h
@@ -0,0 +1,272 @@
+//
+// HTTPCookie.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPCookie
+//
+// Definition of the HTTPCookie class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPCookie_INCLUDED
+#define Net_HTTPCookie_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NameValueCollection;
+
+
+class Net_API HTTPCookie
+	/// This class represents a HTTP Cookie.
+	///
+	/// A cookie is a small amount of information sent by a Web 
+	/// server to a Web browser, saved by the browser, and later sent back 
+	/// to the server. A cookie's value can uniquely identify a client, so 
+	/// cookies are commonly used for session management.
+	///
+	/// A cookie has a name, a single value, and optional attributes such 
+	/// as a comment, path and domain qualifiers, a maximum age, and a 
+	/// version number.
+	///
+	/// This class supports both the Version 0 (by Netscape) and Version 1 
+	/// (by RFC 2109) cookie specifications. By default, cookies are created 
+	/// using Version 0 to ensure the best interoperability.
+{
+public:
+	HTTPCookie();
+		/// Creates an empty HTTPCookie.
+		
+	explicit HTTPCookie(const std::string& name);
+		/// Creates a cookie with the given name.	
+		/// The cookie never expires.
+		
+	explicit HTTPCookie(const NameValueCollection& nvc);
+		/// Creates a cookie from the given NameValueCollection.
+		
+	HTTPCookie(const std::string& name, const std::string& value);
+		/// Creates a cookie with the given name and value.
+		/// The cookie never expires.
+		///
+		/// Note: If value contains whitespace or non-alphanumeric
+		/// characters, the value should be escaped by calling escape()
+		/// before passing it to the constructor.
+		
+	HTTPCookie(const HTTPCookie& cookie);
+		/// Creates the HTTPCookie by copying another one.
+
+	~HTTPCookie();
+		/// Destroys the HTTPCookie.
+		
+	HTTPCookie& operator = (const HTTPCookie& cookie);
+		/// Assigns a cookie.
+		
+	void setVersion(int version);
+		/// Sets the version of the cookie.
+		///
+		/// Version must be either 0 (denoting a Netscape cookie)
+		/// or 1 (denoting a RFC 2109 cookie).
+		
+	int getVersion() const;
+		/// Returns the version of the cookie, which is
+		/// either 0 or 1.	
+		
+	void setName(const std::string& name);
+		/// Sets the name of the cookie.
+		
+	const std::string& getName() const;
+		/// Returns the name of the cookie.
+		
+	void setValue(const std::string& value);
+		/// Sets the value of the cookie.
+		///
+		/// According to the cookie specification, the
+		/// size of the value should not exceed 4 Kbytes.
+		///
+		/// Note: If value contains whitespace or non-alphanumeric
+		/// characters, the value should be escaped by calling escape()
+		/// prior to passing it to setName().
+		
+	const std::string& getValue() const;
+		/// Returns the value of the cookie.
+		
+	void setComment(const std::string& comment);
+		/// Sets the comment for the cookie.
+		///
+		/// Comments are only supported for version 1 cookies.
+
+	const std::string& getComment() const;
+		/// Returns the comment for the cookie.
+
+	void setDomain(const std::string& domain);
+		/// Sets the domain for the cookie.
+		
+	const std::string& getDomain() const;
+		/// Returns the domain for the cookie.
+
+	void setPath(const std::string& path);
+		/// Sets the path for the cookie.
+
+	void setPriority(const std::string& priority);
+		/// Sets the priority for the cookie.
+		
+	const std::string& getPath() const;
+		/// Returns the path for the cookie.
+
+	const std::string& getPriority() const;
+		/// Returns the priority for the cookie.
+
+	void setSecure(bool secure);
+		/// Sets the value of the secure flag for
+		/// the cookie.
+		
+	bool getSecure() const;
+		/// Returns the value of the secure flag
+		/// for the cookie.
+
+	void setMaxAge(int maxAge);
+		/// Sets the maximum age in seconds for
+		/// the cookie.
+		///
+		/// A value of -1 (default) causes the cookie 
+		/// to become a session cookie, which will
+		/// be deleted when the browser window
+		/// is closed.
+		///
+		/// A value of 0 deletes the cookie on
+		/// the client.
+
+	int getMaxAge() const;
+		/// Returns the maximum age in seconds for
+		/// the cookie.
+		
+	void setHttpOnly(bool flag = true);
+		/// Sets the HttpOnly flag for the cookie.
+		
+	bool getHttpOnly() const;
+		/// Returns true iff the cookie's HttpOnly flag is set.
+		
+	std::string toString() const;
+		/// Returns a string representation of the cookie,
+		/// suitable for use in a Set-Cookie header.
+		
+	static std::string escape(const std::string& str);
+		/// Escapes the given string by replacing all 
+		/// non-alphanumeric characters with escape
+		/// sequences in the form %xx, where xx is the
+		/// hexadecimal character code.
+		///
+		/// The following characters will be replaced
+		/// with escape sequences:
+		///   - percent sign %
+		///   - less-than and greater-than < and >
+		///   - curly brackets { and }
+		///   - square brackets [ and ]
+		///   - parenthesis ( and )
+		///   - solidus /
+		///   - vertical line |
+		///   - reverse solidus (backslash /)
+		///   - quotation mark "
+		///   - apostrophe '
+		///   - circumflex accent ^
+		///   - grave accent `
+		///   - comma and semicolon , and ;
+		///   - whitespace and control characters
+		
+	static std::string unescape(const std::string& str);
+		/// Unescapes the given string by replacing all
+		/// escape sequences in the form %xx with the
+		/// respective characters.
+
+private:
+	int         _version;
+	std::string _name;
+	std::string _value;
+	std::string _comment;
+	std::string _domain;
+	std::string _path;
+	std::string _priority;
+	bool        _secure;
+	int         _maxAge;
+	bool        _httpOnly;
+};
+
+
+//
+// inlines
+//
+inline int HTTPCookie::getVersion() const
+{
+	return _version;
+}
+
+
+inline const std::string& HTTPCookie::getName() const
+{
+	return _name;
+}
+
+
+inline const std::string& HTTPCookie::getValue() const
+{
+	return _value;
+}
+
+
+inline const std::string& HTTPCookie::getComment() const
+{
+	return _comment;
+}
+
+
+inline const std::string& HTTPCookie::getDomain() const
+{
+	return _domain;
+}
+
+
+inline const std::string& HTTPCookie::getPath() const
+{
+	return _path;
+}
+
+
+inline const std::string& HTTPCookie::getPriority() const
+{
+	return _priority;
+}
+
+
+inline bool HTTPCookie::getSecure() const
+{
+	return _secure;
+}
+
+
+inline int HTTPCookie::getMaxAge() const
+{
+	return _maxAge;
+}
+
+
+inline bool HTTPCookie::getHttpOnly() const
+{
+	return _httpOnly;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPCookie_INCLUDED
diff --git a/Poco/Net/HTTPCredentials.h b/Poco/Net/HTTPCredentials.h
new file mode 100644
index 0000000..e62b8c2
--- /dev/null
+++ b/Poco/Net/HTTPCredentials.h
@@ -0,0 +1,206 @@
+//
+// HTTPCredentials.h
+//
+// Library: Net
+// Package: HTTP
+// Module:	HTTPCredentials
+//
+// Definition of the HTTPCredentials class.
+//
+// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPCredentials_INCLUDED
+#define Net_HTTPCredentials_INCLUDED
+
+
+#include "Poco/Net/HTTPDigestCredentials.h"
+
+
+namespace Poco {
+
+
+class URI;
+
+
+namespace Net {
+
+
+class HTTPRequest;
+class HTTPResponse;
+
+
+class Net_API HTTPCredentials
+	/// This is a utility class for working with HTTP
+	/// authentication (Basic or Digest) in HTTPRequest objects.
+	///
+	/// Usage is as follows:
+	/// First, create a HTTPCredentials object containing
+	/// the username and password.
+	///     Poco::Net::HTTPCredentials creds("user", "s3cr3t");
+	///
+	/// Second, send the HTTP request with Poco::Net::HTTPClientSession.
+	///     Poco::Net::HTTPClientSession session("pocoproject.org");
+	///     Poco::Net::HTTPRequest request(HTTPRequest::HTTP_GET, "/index.html", HTTPMessage::HTTP_1_1);
+	///     session.sendRequest(request);
+	///     Poco::Net::HTTPResponse;
+	///     std::istream& istr = session.receiveResponse(response);
+	///
+	/// If the server responds with a 401 status, authenticate the
+	/// request and resend it:
+	///     if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
+	///     {
+	///         creds.authenticate(request, response);
+	///         session.sendRequest(request);
+	///         ...
+	///     }
+	///
+	/// To perform multiple authenticated requests, call updateAuthInfo()
+	/// instead of authenticate() on subsequent requests.
+	///     creds.updateAuthInfo(request);
+	///     session.sendRequest(request);
+	///     ...
+	///
+	/// Note: Do not forget to read the entire response stream from the 401 response
+	/// before sending the authenticated request, otherwise there may be
+	/// problems if a persistent connection is used.
+{
+public:
+	HTTPCredentials();
+		/// Creates an empty HTTPCredentials object.
+
+	HTTPCredentials(const std::string& username, const std::string& password);
+		/// Creates an HTTPCredentials object with the given username and password.
+
+	~HTTPCredentials();
+		/// Destroys the HTTPCredentials.
+
+	void fromUserInfo(const std::string& userInfo);
+		/// Parses username:password string and sets username and password of
+		/// the credentials object.
+		/// Throws SyntaxException on invalid user information.
+
+	void fromURI(const URI& uri);
+		/// Extracts username and password from the given URI and sets username
+		/// and password of the credentials object.
+		/// Does nothing if URI has no user info part.
+
+	void clear();
+		/// Clears username, password and host.
+
+	void setUsername(const std::string& username);
+		/// Sets the username.
+
+	const std::string& getUsername() const;
+		/// Returns the username.
+
+	void setPassword(const std::string& password);
+		/// Sets the password.
+
+	const std::string& getPassword() const;
+		/// Returns the password.
+
+	bool empty() const;
+		/// Returns true if both username and password are empty, otherwise false.
+
+	void authenticate(HTTPRequest& request, const HTTPResponse& response);
+		/// Inspects WWW-Authenticate header of the response, initializes
+		/// the internal state (in case of digest authentication) and
+		/// adds required information to the given HTTPRequest.
+		///
+		/// Does nothing if there is no WWW-Authenticate header in the
+		/// HTTPResponse.
+
+	void updateAuthInfo(HTTPRequest& request);
+		/// Updates internal state (in case of digest authentication) and
+		/// replaces authentication information in the request accordingly.
+
+	void proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response);
+		/// Inspects Proxy-Authenticate header of the response, initializes
+		/// the internal state (in case of digest authentication) and
+		/// adds required information to the given HTTPRequest.
+		///
+		/// Does nothing if there is no Proxy-Authenticate header in the
+		/// HTTPResponse.
+
+	void updateProxyAuthInfo(HTTPRequest& request);
+		/// Updates internal state (in case of digest authentication) and
+		/// replaces proxy authentication information in the request accordingly.
+
+	static bool isBasicCredentials(const std::string& header);
+		/// Returns true if authentication header is for Basic authentication.
+
+	static bool isDigestCredentials(const std::string& header);
+		/// Returns true if authentication header is for Digest authentication.
+
+	static bool hasBasicCredentials(const HTTPRequest& request);
+		/// Returns true if an Authorization header with Basic credentials is present in the request.
+
+	static bool hasDigestCredentials(const HTTPRequest& request);
+		/// Returns true if an Authorization header with Digest credentials is present in the request.
+
+	static bool hasNTLMCredentials(const HTTPRequest& request);
+		/// Returns true if an Authorization header with NTLM credentials is present in the request.
+
+	static bool hasProxyBasicCredentials(const HTTPRequest& request);
+		/// Returns true if a Proxy-Authorization header with Basic credentials is present in the request.
+
+	static bool hasProxyDigestCredentials(const HTTPRequest& request);
+		/// Returns true if a Proxy-Authorization header with Digest credentials is present in the request.
+
+	static void extractCredentials(const std::string& userInfo, std::string& username, std::string& password);
+		/// Extracts username and password from user:password information string.
+
+	static void extractCredentials(const Poco::URI& uri, std::string& username, std::string& password);
+		/// Extracts username and password from the given URI (e.g.: "http://user:pass@sample.com/secret").
+
+private:
+	HTTPCredentials(const HTTPCredentials&);
+	HTTPCredentials& operator = (const HTTPCredentials&);
+
+	HTTPDigestCredentials _digest;
+};
+
+
+//
+// inlines
+//
+inline void HTTPCredentials::setUsername(const std::string& username)
+{
+	_digest.setUsername(username);
+}
+
+
+inline const std::string& HTTPCredentials::getUsername() const
+{
+	return _digest.getUsername();
+}
+
+
+inline void HTTPCredentials::setPassword(const std::string& password)
+{
+	_digest.setPassword(password);
+}
+
+
+inline const std::string& HTTPCredentials::getPassword() const
+{
+	return _digest.getPassword();
+}
+
+
+inline bool HTTPCredentials::empty() const
+{
+	return _digest.empty();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPCredentials_INCLUDED
diff --git a/Poco/Net/HTTPDigestCredentials.h b/Poco/Net/HTTPDigestCredentials.h
new file mode 100644
index 0000000..c321c9f
--- /dev/null
+++ b/Poco/Net/HTTPDigestCredentials.h
@@ -0,0 +1,186 @@
+//
+// HTTPDigestCredentials.h
+//
+// Library: Net
+// Package: HTTP
+// Module:	HTTPDigestCredentials
+//
+// Definition of the HTTPDigestCredentials class.
+//
+// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPDigestCredentials_INCLUDED
+#define Net_HTTPDigestCredentials_INCLUDED
+
+
+#include "Poco/Net/HTTPAuthenticationParams.h"
+#include "Poco/Mutex.h"
+#include <map>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+class HTTPResponse;
+
+
+class Net_API HTTPDigestCredentials
+	/// This is a utility class for working with
+	/// HTTP Digest Authentication in HTTPRequest
+	/// objects.
+	///
+	/// Note: currently, no qop or qop=auth is
+	/// supported only.
+{
+public:
+	HTTPDigestCredentials();
+		/// Creates an empty HTTPDigestCredentials object.
+
+	HTTPDigestCredentials(const std::string& username, const std::string& password);
+		/// Creates a HTTPDigestCredentials object with the given username and password.
+
+	~HTTPDigestCredentials();
+		/// Destroys the HTTPDigestCredentials.
+
+	void reset();
+		/// Resets the HTTPDigestCredentials object to a clean state.
+		/// Does not clear username and password.
+
+	void clear();
+		/// Clears both username and password.
+
+	void setUsername(const std::string& username);
+		/// Sets the username.
+
+	const std::string& getUsername() const;
+		/// Returns the username.
+
+	void setPassword(const std::string& password);
+		/// Sets the password.
+
+	const std::string& getPassword() const;
+		/// Returns the password.
+
+	bool empty() const;
+		/// Returns true if both username and password are empty, otherwise false.
+
+	void authenticate(HTTPRequest& request, const HTTPResponse& response);
+		/// Parses WWW-Authenticate header of the HTTPResponse, initializes
+		/// internal state, and adds authentication information to the given HTTPRequest.
+
+	void authenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams);
+		/// Initializes internal state according to information from the
+		/// HTTPAuthenticationParams of the response, and adds authentication
+		/// information to the given HTTPRequest.
+		///
+		/// Throws InvalidArgumentException if HTTPAuthenticationParams is
+		/// invalid or some required parameter is missing.
+		/// Throws NotImplementedException in case of unsupported digest
+		/// algorithm or quality of protection method.
+
+	void updateAuthInfo(HTTPRequest& request);
+		/// Updates internal state and adds authentication information to
+		/// the given HTTPRequest.
+
+	void proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response);
+		/// Parses Proxy-Authenticate header of the HTTPResponse, initializes
+		/// internal state, and adds proxy authentication information to the given HTTPRequest.
+
+	void proxyAuthenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams);
+		/// Initializes internal state according to information from the
+		/// HTTPAuthenticationParams of the response, and adds proxy authentication
+		/// information to the given HTTPRequest.
+		///
+		/// Throws InvalidArgumentException if HTTPAuthenticationParams is
+		/// invalid or some required parameter is missing.
+		/// Throws NotImplementedException in case of unsupported digest
+		/// algorithm or quality of protection method.
+
+	void updateProxyAuthInfo(HTTPRequest& request);
+		/// Updates internal state and adds proxy authentication information to
+		/// the given HTTPRequest.
+
+	bool verifyAuthInfo(const HTTPRequest& request) const;
+		/// Verifies the digest authentication information in the given HTTPRequest
+		/// by recomputing the response and comparing it with what's in the request.
+		///
+		/// Note: This method creates a HTTPAuthenticationParams object from the request
+		/// and calls verifyAuthParams() with request and params.
+
+	bool verifyAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& params) const;
+		/// Verifies the digest authentication information in the given HTTPRequest
+		/// and HTTPAuthenticationParams by recomputing the response and comparing
+		/// it with what's in the request.
+
+	static std::string createNonce();
+		/// Creates a random nonce string.
+
+	static const std::string SCHEME;
+
+private:
+	HTTPDigestCredentials(const HTTPDigestCredentials&);
+	HTTPDigestCredentials& operator = (const HTTPDigestCredentials&);
+
+	void createAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams);
+	void updateAuthParams(const HTTPRequest& request);
+	int updateNonceCounter(const std::string& nonce);
+
+	static const std::string DEFAULT_ALGORITHM;
+	static const std::string DEFAULT_QOP;
+	static const std::string NONCE_PARAM;
+	static const std::string REALM_PARAM;
+	static const std::string QOP_PARAM;
+	static const std::string ALGORITHM_PARAM;
+	static const std::string USERNAME_PARAM;
+	static const std::string OPAQUE_PARAM;
+	static const std::string URI_PARAM;
+	static const std::string RESPONSE_PARAM;
+	static const std::string AUTH_PARAM;
+	static const std::string CNONCE_PARAM;
+	static const std::string NC_PARAM;
+
+	typedef std::map<std::string, int> NonceCounterMap;
+
+	std::string _username;
+	std::string _password;
+	HTTPAuthenticationParams _requestAuthParams;
+	NonceCounterMap _nc;
+
+	static int _nonceCounter;
+	static Poco::FastMutex _nonceMutex;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPDigestCredentials::getUsername() const
+{
+	return _username;
+}
+
+
+inline const std::string& HTTPDigestCredentials::getPassword() const
+{
+	return _password;
+}
+
+
+inline bool HTTPDigestCredentials::empty() const
+{
+	return _username.empty() && _password.empty();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPDigestCredentials_INCLUDED
diff --git a/Poco/Net/HTTPFixedLengthStream.h b/Poco/Net/HTTPFixedLengthStream.h
new file mode 100644
index 0000000..ad781e4
--- /dev/null
+++ b/Poco/Net/HTTPFixedLengthStream.h
@@ -0,0 +1,110 @@
+//
+// HTTPFixedLengthStream.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPFixedLengthStream
+//
+// Definition of the HTTPFixedLengthStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPFixedLengthStream_INCLUDED
+#define Net_HTTPFixedLengthStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPBasicStreamBuf.h"
+#include <cstddef>
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPSession;
+
+
+class Net_API HTTPFixedLengthStreamBuf: public HTTPBasicStreamBuf
+	/// This is the streambuf class used for reading and writing fixed-size
+	/// HTTP message bodies.
+	///
+	/// At most a given number of bytes are read or written.
+{
+public:
+	typedef HTTPBasicStreamBuf::openmode openmode;
+
+#if defined(POCO_HAVE_INT64)
+	typedef Poco::Int64 ContentLength;
+#else
+	typedef std::streamsize ContentLength;
+#endif
+
+	HTTPFixedLengthStreamBuf(HTTPSession& session, ContentLength length, openmode mode);
+	~HTTPFixedLengthStreamBuf();
+	
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	HTTPSession&    _session;
+	ContentLength _length;
+	ContentLength _count;
+};
+
+
+class Net_API HTTPFixedLengthIOS: public virtual std::ios
+	/// The base class for HTTPFixedLengthInputStream.
+{
+public:
+	HTTPFixedLengthIOS(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length, HTTPFixedLengthStreamBuf::openmode mode);
+	~HTTPFixedLengthIOS();
+	HTTPFixedLengthStreamBuf* rdbuf();
+
+protected:
+	HTTPFixedLengthStreamBuf _buf;
+};
+
+
+class Net_API HTTPFixedLengthInputStream: public HTTPFixedLengthIOS, public std::istream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPFixedLengthInputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length);
+	~HTTPFixedLengthInputStream();
+	
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+class Net_API HTTPFixedLengthOutputStream: public HTTPFixedLengthIOS, public std::ostream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPFixedLengthOutputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length);
+	~HTTPFixedLengthOutputStream();
+
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPFixedLengthStream_INCLUDED
diff --git a/Poco/Net/HTTPHeaderStream.h b/Poco/Net/HTTPHeaderStream.h
new file mode 100644
index 0000000..1d67003
--- /dev/null
+++ b/Poco/Net/HTTPHeaderStream.h
@@ -0,0 +1,102 @@
+//
+// HTTPHeaderStream.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPHeaderStream
+//
+// Definition of the HTTPHeaderStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPHeaderStream_INCLUDED
+#define Net_HTTPHeaderStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPBasicStreamBuf.h"
+#include "Poco/MemoryPool.h"
+#include <cstddef>
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPSession;
+
+
+class Net_API HTTPHeaderStreamBuf: public HTTPBasicStreamBuf
+	/// This is the streambuf class used for reading from a HTTP header
+	/// in a HTTPSession.
+{
+public:
+	typedef HTTPBasicStreamBuf::openmode openmode;
+
+	HTTPHeaderStreamBuf(HTTPSession& session, openmode mode);
+	~HTTPHeaderStreamBuf();
+	
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	HTTPSession& _session;
+	bool         _end;
+};
+
+
+class Net_API HTTPHeaderIOS: public virtual std::ios
+	/// The base class for HTTPHeaderInputStream.
+{
+public:
+	HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode);
+	~HTTPHeaderIOS();
+	HTTPHeaderStreamBuf* rdbuf();
+
+protected:
+	HTTPHeaderStreamBuf _buf;
+};
+
+
+class Net_API HTTPHeaderInputStream: public HTTPHeaderIOS, public std::istream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPHeaderInputStream(HTTPSession& session);
+	~HTTPHeaderInputStream();
+
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+class Net_API HTTPHeaderOutputStream: public HTTPHeaderIOS, public std::ostream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPHeaderOutputStream(HTTPSession& session);
+	~HTTPHeaderOutputStream();
+
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPHeaderStream_INCLUDED
diff --git a/Poco/Net/HTTPIOStream.h b/Poco/Net/HTTPIOStream.h
new file mode 100644
index 0000000..2c45812
--- /dev/null
+++ b/Poco/Net/HTTPIOStream.h
@@ -0,0 +1,88 @@
+//
+// HTTPIOStream.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPIOStream
+//
+// Definition of the HTTPIOStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPIOStream_INCLUDED
+#define Net_HTTPIOStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPResponse.h"
+#include "Poco/UnbufferedStreamBuf.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPClientSession;
+
+
+class Net_API HTTPResponseStreamBuf: public Poco::UnbufferedStreamBuf
+{
+public:
+	HTTPResponseStreamBuf(std::istream& istr);
+	
+	~HTTPResponseStreamBuf();
+		
+private:
+	int readFromDevice();
+	
+	std::istream& _istr;
+};
+
+
+inline int HTTPResponseStreamBuf::readFromDevice()
+{
+	return _istr.get();
+}
+
+
+class Net_API HTTPResponseIOS: public virtual std::ios
+{
+public:
+	HTTPResponseIOS(std::istream& istr);
+	
+	~HTTPResponseIOS();
+	
+	HTTPResponseStreamBuf* rdbuf();
+
+protected:
+	HTTPResponseStreamBuf _buf;
+};
+
+
+inline HTTPResponseStreamBuf* HTTPResponseIOS::rdbuf()
+{
+	return &_buf;
+}
+
+
+class Net_API HTTPResponseStream: public HTTPResponseIOS, public std::istream
+{
+public:
+	HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession);
+		
+	~HTTPResponseStream();
+	
+private:
+	HTTPClientSession* _pSession;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPIOStream_INCLUDED
diff --git a/Poco/Net/HTTPMessage.h b/Poco/Net/HTTPMessage.h
new file mode 100644
index 0000000..345543d
--- /dev/null
+++ b/Poco/Net/HTTPMessage.h
@@ -0,0 +1,185 @@
+//
+// HTTPMessage.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPMessage
+//
+// Definition of the HTTPMessage class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPMessage_INCLUDED
+#define Net_HTTPMessage_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/MessageHeader.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class MediaType;
+
+
+class Net_API HTTPMessage: public MessageHeader
+	/// The base class for HTTPRequest and HTTPResponse.
+	///
+	/// Defines the common properties of all HTTP messages.
+	/// These are version, content length, content type
+	/// and transfer encoding.
+{
+public:
+	void setVersion(const std::string& version);
+		/// Sets the HTTP version for this message.
+		
+	const std::string& getVersion() const;
+		/// Returns the HTTP version for this message.
+		
+	void setContentLength(std::streamsize length);
+		/// Sets the Content-Length header.
+		///
+		/// If length is UNKNOWN_CONTENT_LENGTH, removes
+		/// the Content-Length header.
+		
+	std::streamsize getContentLength() const;
+		/// Returns the content length for this message,
+		/// which may be UNKNOWN_CONTENT_LENGTH if
+		/// no Content-Length header is present.
+
+#if defined(POCO_HAVE_INT64)	
+	void setContentLength64(Poco::Int64 length);
+		/// Sets the Content-Length header.
+		///
+		/// If length is UNKNOWN_CONTENT_LENGTH, removes
+		/// the Content-Length header.
+		///
+		/// In contrast to setContentLength(), this method takes
+		/// a 64-bit integer as content length.
+
+	Poco::Int64 getContentLength64() const;
+		/// Returns the content length for this message,
+		/// which may be UNKNOWN_CONTENT_LENGTH if
+		/// no Content-Length header is present.
+		///
+		/// In contrast to getContentLength(), this method
+		/// always returns a 64-bit integer for content length.
+#endif // defined(POCO_HAVE_INT64)
+
+	bool hasContentLength() const;
+		/// Returns true iff a Content-Length header is present.
+
+	void setTransferEncoding(const std::string& transferEncoding);
+		/// Sets the transfer encoding for this message.
+		///
+		/// The value should be either IDENTITY_TRANSFER_CODING
+		/// or CHUNKED_TRANSFER_CODING.
+
+	const std::string& getTransferEncoding() const;
+		/// Returns the transfer encoding used for this
+		/// message.
+		///
+		/// Normally, this is the value of the Transfer-Encoding
+		/// header field. If no such field is present,
+		/// returns IDENTITY_TRANSFER_CODING.
+		
+	void setChunkedTransferEncoding(bool flag);
+		/// If flag is true, sets the Transfer-Encoding header to
+		/// chunked. Otherwise, removes the Transfer-Encoding
+		/// header.
+		
+	bool getChunkedTransferEncoding() const;
+		/// Returns true if the Transfer-Encoding header is set
+		/// and its value is chunked.
+		
+	void setContentType(const std::string& mediaType);
+		/// Sets the content type for this message.
+		///
+		/// Specify NO_CONTENT_TYPE to remove the
+		/// Content-Type header.
+		
+	void setContentType(const MediaType& mediaType);	
+		/// Sets the content type for this message.
+		
+	const std::string& getContentType() const;
+		/// Returns the content type for this message.
+		///
+		/// If no Content-Type header is present, 
+		/// returns UNKNOWN_CONTENT_TYPE.	
+
+	void setKeepAlive(bool keepAlive);
+		/// Sets the value of the Connection header field.
+		///
+		/// The value is set to "Keep-Alive" if keepAlive is
+		/// true, or to "Close" otherwise.
+
+	bool getKeepAlive() const;
+		/// Returns true if
+		///   * the message has a Connection header field and its value is "Keep-Alive"
+		///   * the message is a HTTP/1.1 message and not Connection header is set
+		/// Returns false otherwise.
+
+	static const std::string HTTP_1_0;
+	static const std::string HTTP_1_1;
+
+	static const std::string IDENTITY_TRANSFER_ENCODING;
+	static const std::string CHUNKED_TRANSFER_ENCODING;
+
+	static const int         UNKNOWN_CONTENT_LENGTH;
+	static const std::string UNKNOWN_CONTENT_TYPE;
+	
+	static const std::string CONTENT_LENGTH;
+	static const std::string CONTENT_TYPE;
+	static const std::string TRANSFER_ENCODING;
+	static const std::string CONNECTION;
+	
+	static const std::string CONNECTION_KEEP_ALIVE;
+	static const std::string CONNECTION_CLOSE;
+
+	static const std::string EMPTY;
+
+protected:
+	HTTPMessage();
+		/// Creates the HTTPMessage with version HTTP/1.0.
+
+	HTTPMessage(const std::string& version);
+		/// Creates the HTTPMessage and sets
+		/// the version.
+
+	virtual ~HTTPMessage();
+		/// Destroys the HTTPMessage.
+	
+private:
+	HTTPMessage(const HTTPMessage&);
+	HTTPMessage& operator = (const HTTPMessage&);
+	
+	std::string _version;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPMessage::getVersion() const
+{
+	return _version;
+}
+
+
+inline bool HTTPMessage::hasContentLength() const
+{
+	return has(CONTENT_LENGTH);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPMessage_INCLUDED
diff --git a/Poco/Net/HTTPRequest.h b/Poco/Net/HTTPRequest.h
new file mode 100644
index 0000000..817a74d
--- /dev/null
+++ b/Poco/Net/HTTPRequest.h
@@ -0,0 +1,200 @@
+//
+// HTTPRequest.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPRequest
+//
+// Definition of the HTTPRequest class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPRequest_INCLUDED
+#define Net_HTTPRequest_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPMessage.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPRequest: public HTTPMessage
+	/// This class encapsulates an HTTP request
+	/// message.
+	///
+	/// In addition to the properties common to
+	/// all HTTP messages, a HTTP request has
+	/// a method (e.g. GET, HEAD, POST, etc.) and
+	/// a request URI.
+{
+public:
+	HTTPRequest();
+		/// Creates a GET / HTTP/1.0 HTTP request.
+		
+	HTTPRequest(const std::string& version);
+		/// Creates a GET / HTTP/1.x request with
+		/// the given version (HTTP/1.0 or HTTP/1.1).
+		
+	HTTPRequest(const std::string& method, const std::string& uri);
+		/// Creates a HTTP/1.0 request with the given method and URI.
+
+	HTTPRequest(const std::string& method, const std::string& uri, const std::string& version);
+		/// Creates a HTTP request with the given method, URI and version.
+
+	virtual ~HTTPRequest();
+		/// Destroys the HTTPRequest.
+
+	void setMethod(const std::string& method);
+		/// Sets the method.
+
+	const std::string& getMethod() const;
+		/// Returns the method.
+
+	void setURI(const std::string& uri);
+		/// Sets the request URI.
+		
+	const std::string& getURI() const;
+		/// Returns the request URI.
+		
+	void setHost(const std::string& host);
+		/// Sets the value of the Host header field.
+		
+	void setHost(const std::string& host, Poco::UInt16 port);
+		/// Sets the value of the Host header field.
+		///
+		/// If the given port number is a non-standard
+		/// port number (other than 80 or 443), it is
+		/// included in the Host header field.
+		
+	const std::string& getHost() const;
+		/// Returns the value of the Host header field.
+		///
+		/// Throws a NotFoundException if the request
+		/// does not have a Host header field.
+
+	void setCookies(const NameValueCollection& cookies);
+		/// Adds a Cookie header with the names and
+		/// values from cookies.
+		
+	void getCookies(NameValueCollection& cookies) const;
+		/// Fills cookies with the cookies extracted
+		/// from the Cookie headers in the request.
+
+	bool hasCredentials() const;
+		/// Returns true iff the request contains authentication
+		/// information in the form of an Authorization header.
+		
+	void getCredentials(std::string& scheme, std::string& authInfo) const;
+		/// Returns the authentication scheme and additional authentication
+		/// information contained in this request.
+		///
+		/// Throws a NotAuthenticatedException if no authentication information
+		/// is contained in the request.
+		
+	void setCredentials(const std::string& scheme, const std::string& authInfo);
+		/// Sets the authentication scheme and information for
+		/// this request.
+
+	bool getExpectContinue() const;
+		/// Returns true if the request contains an
+		/// "Expect: 100-continue" header.
+
+	void setExpectContinue(bool expectContinue);
+		/// Adds a "Expect: 100-continue" header to the request if
+		/// expectContinue is true, otherwise removes the Expect header.
+		
+	bool hasProxyCredentials() const;
+		/// Returns true iff the request contains proxy authentication
+		/// information in the form of an Proxy-Authorization header.
+		
+	void getProxyCredentials(std::string& scheme, std::string& authInfo) const;
+		/// Returns the proxy authentication scheme and additional proxy authentication
+		/// information contained in this request.
+		///
+		/// Throws a NotAuthenticatedException if no proxy authentication information
+		/// is contained in the request.
+		
+	void setProxyCredentials(const std::string& scheme, const std::string& authInfo);
+		/// Sets the proxy authentication scheme and information for
+		/// this request.
+
+	void write(std::ostream& ostr) const;
+		/// Writes the HTTP request to the given
+		/// output stream.
+
+	void read(std::istream& istr);
+		/// Reads the HTTP request from the
+		/// given input stream.
+		
+	static const std::string HTTP_GET;
+	static const std::string HTTP_HEAD;
+	static const std::string HTTP_PUT;
+	static const std::string HTTP_POST;
+	static const std::string HTTP_OPTIONS;
+	static const std::string HTTP_DELETE;
+	static const std::string HTTP_TRACE;
+	static const std::string HTTP_CONNECT;
+	static const std::string HTTP_PATCH;
+	
+	static const std::string HOST;
+	static const std::string COOKIE;
+	static const std::string AUTHORIZATION;
+	static const std::string PROXY_AUTHORIZATION;
+	static const std::string UPGRADE;
+	static const std::string EXPECT;
+
+protected:
+	void getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const;
+		/// Returns the authentication scheme and additional authentication
+		/// information contained in the given header of request.
+		///
+		/// Throws a NotAuthenticatedException if no authentication information
+		/// is contained in the request.
+		
+	void setCredentials(const std::string& header, const std::string& scheme, const std::string& authInfo);
+		/// Writes the authentication scheme and information for
+		/// this request to the given header.
+
+private:
+	enum Limits
+	{
+		MAX_METHOD_LENGTH  = 32,
+		MAX_URI_LENGTH     = 16384,
+		MAX_VERSION_LENGTH = 8
+	};
+	
+	std::string _method;
+	std::string _uri;
+	
+	HTTPRequest(const HTTPRequest&);
+	HTTPRequest& operator = (const HTTPRequest&);
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPRequest::getMethod() const
+{
+	return _method;
+}
+
+
+inline const std::string& HTTPRequest::getURI() const
+{
+	return _uri;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPRequest_INCLUDED
diff --git a/Poco/Net/HTTPRequestHandler.h b/Poco/Net/HTTPRequestHandler.h
new file mode 100644
index 0000000..8a62712
--- /dev/null
+++ b/Poco/Net/HTTPRequestHandler.h
@@ -0,0 +1,67 @@
+//
+// HTTPRequestHandler.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPRequestHandler
+//
+// Definition of the HTTPRequestHandler class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPRequestHandler_INCLUDED
+#define Net_HTTPRequestHandler_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerRequest;
+class HTTPServerResponse;
+
+
+class Net_API HTTPRequestHandler
+	/// The abstract base class for HTTPRequestHandlers 
+	/// created by HTTPServer.
+	///
+	/// Derived classes must override the handleRequest() method.
+	/// Furthermore, a HTTPRequestHandlerFactory must be provided.
+	///
+	/// The handleRequest() method must perform the complete handling
+	/// of the HTTP request connection. As soon as the handleRequest() 
+	/// method returns, the request handler object is destroyed.
+	///
+	/// A new HTTPRequestHandler object will be created for
+	/// each new HTTP request that is received by the HTTPServer.
+{
+public:
+	HTTPRequestHandler();
+		/// Creates the HTTPRequestHandler.
+
+	virtual ~HTTPRequestHandler();
+		/// Destroys the HTTPRequestHandler.
+
+	virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) = 0;
+		/// Must be overridden by subclasses.
+		///
+		/// Handles the given request.
+
+private:
+	HTTPRequestHandler(const HTTPRequestHandler&);
+	HTTPRequestHandler& operator = (const HTTPRequestHandler&);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPRequestHandler_INCLUDED
diff --git a/Poco/Net/HTTPRequestHandlerFactory.h b/Poco/Net/HTTPRequestHandlerFactory.h
new file mode 100644
index 0000000..421c465
--- /dev/null
+++ b/Poco/Net/HTTPRequestHandlerFactory.h
@@ -0,0 +1,78 @@
+//
+// HTTPRequestHandlerFactory.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPRequestHandlerFactory
+//
+// Definition of the HTTPRequestHandlerFactory class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPRequestHandlerFactory_INCLUDED
+#define Net_HTTPRequestHandlerFactory_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/BasicEvent.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerRequest;
+class HTTPServerResponse;
+class HTTPRequestHandler;
+
+
+class Net_API HTTPRequestHandlerFactory
+	/// A factory for HTTPRequestHandler objects.
+	/// Subclasses must override the createRequestHandler()
+	/// method.
+{
+public:
+	typedef Poco::SharedPtr<HTTPRequestHandlerFactory> Ptr;
+	
+	HTTPRequestHandlerFactory();
+		/// Creates the HTTPRequestHandlerFactory.
+
+	virtual ~HTTPRequestHandlerFactory();
+		/// Destroys the HTTPRequestHandlerFactory.
+
+	virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) = 0;
+		/// Must be overridden by subclasses.
+		///
+		/// Creates a new request handler for the given HTTP request.
+		///
+		/// The method should inspect the given HTTPServerRequest object (e.g., method
+		/// and URI) and create an appropriate HTTPRequestHandler object to handle the
+		/// request.
+		///
+		/// If the request contains a "Expect: 100-continue" header, it's possible
+		/// to prevent the server from sending the default 100 Continue response 
+		/// by setting the status of the response object that can be obtained through 
+		/// the request object (request.response()) to something other than 200 OK.
+
+protected:
+	Poco::BasicEvent<const bool> serverStopped;
+
+private:
+	HTTPRequestHandlerFactory(const HTTPRequestHandlerFactory&);
+	HTTPRequestHandlerFactory& operator = (const HTTPRequestHandlerFactory&);
+	
+	friend class HTTPServer;
+	friend class HTTPServerConnection;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPRequestHandlerFactory_INCLUDED
diff --git a/Poco/Net/HTTPResponse.h b/Poco/Net/HTTPResponse.h
new file mode 100644
index 0000000..fd6eb81
--- /dev/null
+++ b/Poco/Net/HTTPResponse.h
@@ -0,0 +1,295 @@
+//
+// HTTPResponse.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPResponse
+//
+// Definition of the HTTPResponse class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPResponse_INCLUDED
+#define Net_HTTPResponse_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPMessage.h"
+#include "Poco/Net/HTTPCookie.h"
+#include "Poco/Timestamp.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPCookie;
+
+
+class Net_API HTTPResponse: public HTTPMessage
+	/// This class encapsulates an HTTP response
+	/// message.
+	///
+	/// In addition to the properties common to
+	/// all HTTP messages, a HTTP response has
+	/// status code and a reason phrase.
+{
+public:
+	enum HTTPStatus
+	{
+		HTTP_CONTINUE                        = 100,
+		HTTP_SWITCHING_PROTOCOLS             = 101,
+		HTTP_PROCESSING                      = 102,
+		HTTP_OK                              = 200,
+		HTTP_CREATED                         = 201,
+		HTTP_ACCEPTED                        = 202,
+		HTTP_NONAUTHORITATIVE                = 203,
+		HTTP_NO_CONTENT                      = 204,
+		HTTP_RESET_CONTENT                   = 205,
+		HTTP_PARTIAL_CONTENT                 = 206,
+		HTTP_MULTI_STATUS                    = 207,
+		HTTP_ALREADY_REPORTED                = 208,
+		HTTP_IM_USED                         = 226,
+		HTTP_MULTIPLE_CHOICES                = 300,
+		HTTP_MOVED_PERMANENTLY               = 301,
+		HTTP_FOUND                           = 302,
+		HTTP_SEE_OTHER                       = 303,
+		HTTP_NOT_MODIFIED                    = 304,
+		HTTP_USE_PROXY                       = 305,
+		HTTP_USEPROXY                        = 305, /// @deprecated
+		// UNUSED: 306
+		HTTP_TEMPORARY_REDIRECT              = 307,
+		HTTP_PERMANENT_REDIRECT              = 308,
+		HTTP_BAD_REQUEST                     = 400,
+		HTTP_UNAUTHORIZED                    = 401,
+		HTTP_PAYMENT_REQUIRED                = 402,
+		HTTP_FORBIDDEN                       = 403,
+		HTTP_NOT_FOUND                       = 404,
+		HTTP_METHOD_NOT_ALLOWED              = 405,
+		HTTP_NOT_ACCEPTABLE                  = 406,
+		HTTP_PROXY_AUTHENTICATION_REQUIRED   = 407,
+		HTTP_REQUEST_TIMEOUT                 = 408,
+		HTTP_CONFLICT                        = 409,
+		HTTP_GONE                            = 410,
+		HTTP_LENGTH_REQUIRED                 = 411,
+		HTTP_PRECONDITION_FAILED             = 412,
+		HTTP_REQUEST_ENTITY_TOO_LARGE        = 413,
+		HTTP_REQUESTENTITYTOOLARGE           = 413, /// @deprecated
+		HTTP_REQUEST_URI_TOO_LONG            = 414,
+		HTTP_REQUESTURITOOLONG               = 414, /// @deprecated
+		HTTP_UNSUPPORTED_MEDIA_TYPE          = 415,
+		HTTP_UNSUPPORTEDMEDIATYPE            = 415, /// @deprecated
+		HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
+		HTTP_EXPECTATION_FAILED              = 417,
+		HTTP_IM_A_TEAPOT                     = 418,
+		HTTP_ENCHANCE_YOUR_CALM              = 420,
+		HTTP_MISDIRECTED_REQUEST             = 421,
+		HTTP_UNPROCESSABLE_ENTITY            = 422,
+		HTTP_LOCKED                          = 423,
+		HTTP_FAILED_DEPENDENCY               = 424,
+		HTTP_UPGRADE_REQUIRED                = 426,
+		HTTP_PRECONDITION_REQUIRED           = 428,
+		HTTP_TOO_MANY_REQUESTS               = 429,
+		HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
+		HTTP_UNAVAILABLE_FOR_LEGAL_REASONS   = 451,
+		HTTP_INTERNAL_SERVER_ERROR           = 500,
+		HTTP_NOT_IMPLEMENTED                 = 501,
+		HTTP_BAD_GATEWAY                     = 502,
+		HTTP_SERVICE_UNAVAILABLE             = 503,
+		HTTP_GATEWAY_TIMEOUT                 = 504,
+		HTTP_VERSION_NOT_SUPPORTED           = 505,
+		HTTP_VARIANT_ALSO_NEGOTIATES         = 506,
+		HTTP_INSUFFICIENT_STORAGE            = 507,
+		HTTP_LOOP_DETECTED                   = 508,
+		HTTP_NOT_EXTENDED                    = 510,
+		HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511
+	};
+
+	HTTPResponse();
+		/// Creates the HTTPResponse with OK status.
+		
+	HTTPResponse(HTTPStatus status, const std::string& reason);
+		/// Creates the HTTPResponse with the given status
+		/// and reason phrase.
+
+	HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason);
+		/// Creates the HTTPResponse with the given version, status
+		/// and reason phrase.
+		
+	HTTPResponse(HTTPStatus status);
+		/// Creates the HTTPResponse with the given status
+		/// an an appropriate reason phrase.
+
+	HTTPResponse(const std::string& version, HTTPStatus status);
+		/// Creates the HTTPResponse with the given version, status
+		/// an an appropriate reason phrase.
+
+	virtual ~HTTPResponse();
+		/// Destroys the HTTPResponse.
+
+	void setStatus(HTTPStatus status);
+		/// Sets the HTTP status code.
+		///
+		/// Does not change the reason phrase.
+		
+	HTTPStatus getStatus() const;
+		/// Returns the HTTP status code.
+		
+	void setStatus(const std::string& status);
+		/// Sets the HTTP status code.
+		///
+		/// The string must contain a valid
+		/// HTTP numerical status code.
+		
+	void setReason(const std::string& reason);
+		/// Sets the HTTP reason phrase.
+		
+	const std::string& getReason() const;
+		/// Returns the HTTP reason phrase.
+
+	void setStatusAndReason(HTTPStatus status, const std::string& reason);
+		/// Sets the HTTP status code and reason phrase.
+		
+	void setStatusAndReason(HTTPStatus status);
+		/// Sets the HTTP status code and reason phrase.
+		///
+		/// The reason phrase is set according to the status code.
+
+	void setDate(const Poco::Timestamp& dateTime);
+		/// Sets the Date header to the given date/time value.
+		
+	Poco::Timestamp getDate() const;
+		/// Returns the value of the Date header.
+
+	void addCookie(const HTTPCookie& cookie);
+		/// Adds the cookie to the response by
+		/// adding a Set-Cookie header.
+
+	void getCookies(std::vector<HTTPCookie>& cookies) const;
+		/// Returns a vector with all the cookies
+		/// set in the response header.
+		///
+		/// May throw an exception in case of a malformed
+		/// Set-Cookie header.
+
+	void write(std::ostream& ostr) const;
+		/// Writes the HTTP response to the given
+		/// output stream.
+
+	void read(std::istream& istr);
+		/// Reads the HTTP response from the
+		/// given input stream.
+		///
+		/// 100 Continue responses are ignored.
+	
+	static const std::string& getReasonForStatus(HTTPStatus status);
+		/// Returns an appropriate reason phrase
+		/// for the given status code.
+
+	static const std::string HTTP_REASON_CONTINUE;
+	static const std::string HTTP_REASON_SWITCHING_PROTOCOLS;
+	static const std::string HTTP_REASON_PROCESSING;
+	static const std::string HTTP_REASON_OK;
+	static const std::string HTTP_REASON_CREATED;
+	static const std::string HTTP_REASON_ACCEPTED;
+	static const std::string HTTP_REASON_NONAUTHORITATIVE;
+	static const std::string HTTP_REASON_NO_CONTENT;
+	static const std::string HTTP_REASON_RESET_CONTENT;
+	static const std::string HTTP_REASON_PARTIAL_CONTENT;
+	static const std::string HTTP_REASON_MULTI_STATUS;
+	static const std::string HTTP_REASON_ALREADY_REPORTED;
+	static const std::string HTTP_REASON_IM_USED;
+	static const std::string HTTP_REASON_MULTIPLE_CHOICES;
+	static const std::string HTTP_REASON_MOVED_PERMANENTLY;
+	static const std::string HTTP_REASON_FOUND;
+	static const std::string HTTP_REASON_SEE_OTHER;
+	static const std::string HTTP_REASON_NOT_MODIFIED;
+	static const std::string HTTP_REASON_USE_PROXY;
+	static const std::string HTTP_REASON_TEMPORARY_REDIRECT;
+	static const std::string HTTP_REASON_PERMANENT_REDIRECT;
+	static const std::string HTTP_REASON_BAD_REQUEST;
+	static const std::string HTTP_REASON_UNAUTHORIZED;
+	static const std::string HTTP_REASON_PAYMENT_REQUIRED;
+	static const std::string HTTP_REASON_FORBIDDEN;
+	static const std::string HTTP_REASON_NOT_FOUND;
+	static const std::string HTTP_REASON_METHOD_NOT_ALLOWED;
+	static const std::string HTTP_REASON_NOT_ACCEPTABLE;
+	static const std::string HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED;
+	static const std::string HTTP_REASON_REQUEST_TIMEOUT;
+	static const std::string HTTP_REASON_CONFLICT;
+	static const std::string HTTP_REASON_GONE;
+	static const std::string HTTP_REASON_LENGTH_REQUIRED;
+	static const std::string HTTP_REASON_PRECONDITION_FAILED;
+	static const std::string HTTP_REASON_REQUEST_ENTITY_TOO_LARGE;
+	static const std::string HTTP_REASON_REQUEST_URI_TOO_LONG;
+	static const std::string HTTP_REASON_UNSUPPORTED_MEDIA_TYPE;
+	static const std::string HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE;
+	static const std::string HTTP_REASON_EXPECTATION_FAILED;
+	static const std::string HTTP_REASON_IM_A_TEAPOT;
+	static const std::string HTTP_REASON_ENCHANCE_YOUR_CALM;
+	static const std::string HTTP_REASON_MISDIRECTED_REQUEST;
+	static const std::string HTTP_REASON_UNPROCESSABLE_ENTITY;
+	static const std::string HTTP_REASON_LOCKED;
+	static const std::string HTTP_REASON_FAILED_DEPENDENCY;
+	static const std::string HTTP_REASON_UPGRADE_REQUIRED;
+	static const std::string HTTP_REASON_PRECONDITION_REQUIRED;
+	static const std::string HTTP_REASON_TOO_MANY_REQUESTS;
+	static const std::string HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE;
+	static const std::string HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS;
+	static const std::string HTTP_REASON_INTERNAL_SERVER_ERROR;
+	static const std::string HTTP_REASON_NOT_IMPLEMENTED;
+	static const std::string HTTP_REASON_BAD_GATEWAY;
+	static const std::string HTTP_REASON_SERVICE_UNAVAILABLE;
+	static const std::string HTTP_REASON_GATEWAY_TIMEOUT;
+	static const std::string HTTP_REASON_VERSION_NOT_SUPPORTED;
+	static const std::string HTTP_REASON_VARIANT_ALSO_NEGOTIATES;
+	static const std::string HTTP_REASON_INSUFFICIENT_STORAGE;
+	static const std::string HTTP_REASON_LOOP_DETECTED;
+	static const std::string HTTP_REASON_NOT_EXTENDED;
+	static const std::string HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED;
+	static const std::string HTTP_REASON_UNKNOWN;
+	
+	static const std::string DATE;
+	static const std::string SET_COOKIE;
+
+private:
+	enum Limits
+	{
+		MAX_VERSION_LENGTH = 8,
+		MAX_STATUS_LENGTH  = 3,
+		MAX_REASON_LENGTH  = 512
+	};
+	
+	HTTPStatus  _status;
+	std::string _reason;
+	
+	HTTPResponse(const HTTPResponse&);
+	HTTPResponse& operator = (const HTTPResponse&);
+};
+
+
+//
+// inlines
+//
+inline HTTPResponse::HTTPStatus HTTPResponse::getStatus() const
+{
+	return _status;
+}
+
+
+inline const std::string& HTTPResponse::getReason() const
+{
+	return _reason;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPResponse_INCLUDED
diff --git a/Poco/Net/HTTPSClientSession.h b/Poco/Net/HTTPSClientSession.h
new file mode 100644
index 0000000..ff0d899
--- /dev/null
+++ b/Poco/Net/HTTPSClientSession.h
@@ -0,0 +1,165 @@
+//
+// HTTPSClientSession.h
+//
+// Library: NetSSL_OpenSSL
+// Package: HTTPSClient
+// Module:  HTTPSClientSession
+//
+// Definition of the HTTPSClientSession class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_HTTPSClientSession_INCLUDED
+#define NetSSL_HTTPSClientSession_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/Utility.h"
+#include "Poco/Net/HTTPClientSession.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Net/Session.h"
+#include "Poco/Net/X509Certificate.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class SecureStreamSocket;
+class HTTPRequest;
+class HTTPResponse;
+
+
+class NetSSL_API HTTPSClientSession: public HTTPClientSession
+	/// This class implements the client-side of
+	/// a HTTPS session.
+	///
+	/// To send a HTTPS request to a HTTPS server, first
+	/// instantiate a HTTPSClientSession object and
+	/// specify the server's host name and port number.
+	///
+	/// Then create a HTTPRequest object, fill it accordingly,
+	/// and pass it as argument to the sendRequest() method.
+	///
+	/// sendRequest() will return an output stream that can
+	/// be used to send the request body, if there is any.
+	///
+	/// After you are done sending the request body, create
+	/// a HTTPResponse object and pass it to receiveResponse().
+	///
+	/// This will return an input stream that can be used to
+	/// read the response body.
+	///
+	/// See RFC 2616 <http://www.faqs.org/rfcs/rfc2616.html> for more
+	/// information about the HTTP protocol.
+	///
+	/// Note that sending requests that neither contain a content length
+	/// field in the header nor are using chunked transfer encoding will
+	/// result in a SSL protocol violation, as the framework shuts down
+	/// the socket after sending the message body. No orderly SSL shutdown
+	/// will be performed in this case.
+	///
+	/// If session caching has been enabled for the Context object passed
+	/// to the HTTPSClientSession, the HTTPSClientSession class will
+	/// attempt to reuse a previously obtained Session object in
+	/// case of a reconnect.
+{
+public:
+	enum
+	{
+		HTTPS_PORT = 443
+	};
+	
+	HTTPSClientSession();
+		/// Creates an unconnected HTTPSClientSession.
+
+	explicit HTTPSClientSession(const SecureStreamSocket& socket);
+		/// Creates a HTTPSClientSession using the given socket.
+		/// The socket must not be connected. The session
+		/// takes ownership of the socket.
+
+	HTTPSClientSession(const SecureStreamSocket& socket, Session::Ptr pSession);
+		/// Creates a HTTPSClientSession using the given socket.
+		/// The socket must not be connected. The session
+		/// takes ownership of the socket.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	HTTPSClientSession(const std::string& host, Poco::UInt16 port = HTTPS_PORT);
+		/// Creates a HTTPSClientSession using the given host and port.
+
+	explicit HTTPSClientSession(Context::Ptr pContext);
+		/// Creates an unconnected HTTPSClientSession, using the
+		/// give SSL context.
+
+	HTTPSClientSession(Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates an unconnected HTTPSClientSession, using the
+		/// give SSL context.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext);
+		/// Creates a HTTPSClientSession using the given host and port,
+		/// using the given SSL context.
+
+	HTTPSClientSession(const std::string& host, Poco::UInt16 port, Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates a HTTPSClientSession using the given host and port,
+		/// using the given SSL context.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	~HTTPSClientSession();
+		/// Destroys the HTTPSClientSession and closes
+		/// the underlying socket.
+	
+	bool secure() const;
+		/// Return true iff the session uses SSL or TLS,
+		/// or false otherwise.
+		
+	X509Certificate serverCertificate();
+		/// Returns the server's certificate.
+		///
+		/// The certificate is available after the first request has been sent.
+		
+	Session::Ptr sslSession();
+		/// Returns the SSL Session object for the current 
+		/// connection, if session caching has been enabled for
+		/// the HTTPSClientSession's Context. A null pointer is 
+		/// returned otherwise.
+		///
+		/// The Session object can be obtained after the first request has
+		/// been sent.
+		
+	// HTTPSession
+	void abort();
+
+protected:
+	void connect(const SocketAddress& address);
+	std::string proxyRequestPrefix() const;
+	void proxyAuthenticate(HTTPRequest& request);
+	int read(char* buffer, std::streamsize length);
+
+private:
+	HTTPSClientSession(const HTTPSClientSession&);
+	HTTPSClientSession& operator = (const HTTPSClientSession&);
+	
+	Context::Ptr _pContext;
+	Session::Ptr _pSession;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPSClientSession_INCLUDED
diff --git a/Poco/Net/HTTPSSessionInstantiator.h b/Poco/Net/HTTPSSessionInstantiator.h
new file mode 100644
index 0000000..214e281
--- /dev/null
+++ b/Poco/Net/HTTPSSessionInstantiator.h
@@ -0,0 +1,65 @@
+//
+// HTTPSSessionInstantiator.h
+//
+// Library: NetSSL_OpenSSL
+// Package: HTTPSClient
+// Module:  HTTPSSessionInstantiator
+//
+// Definition of the HTTPSSessionInstantiator class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPSSessionInstantiator_INCLUDED
+#define Net_HTTPSSessionInstantiator_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Net/Utility.h"
+#include "Poco/Net/HTTPSessionInstantiator.h"
+#include "Poco/URI.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API HTTPSSessionInstantiator: public HTTPSessionInstantiator
+	/// The HTTPSessionInstantiator for HTTPSClientSession.
+{
+public:
+	HTTPSSessionInstantiator();
+		/// Creates the HTTPSSessionInstantiator.
+
+	HTTPSSessionInstantiator(Context::Ptr pContext);
+		/// Creates the HTTPSSessionInstantiator using the given SSL context.
+
+	~HTTPSSessionInstantiator();
+		/// Destroys the HTTPSSessionInstantiator.
+
+	HTTPClientSession* createClientSession(const Poco::URI& uri);
+		/// Creates a HTTPSClientSession for the given URI.
+
+	static void registerInstantiator();
+		/// Registers the instantiator with the global HTTPSessionFactory.
+
+	static void registerInstantiator(Context::Ptr pContext);
+		/// Registers the instantiator with the global HTTPSessionFactory using the given SSL context.
+
+	static void unregisterInstantiator();
+		/// Unregisters the factory with the global HTTPSessionFactory.
+
+private:
+	Context::Ptr _pContext;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPSSessionInstantiator_INCLUDED
diff --git a/Poco/Net/HTTPSStreamFactory.h b/Poco/Net/HTTPSStreamFactory.h
new file mode 100644
index 0000000..2fd3515
--- /dev/null
+++ b/Poco/Net/HTTPSStreamFactory.h
@@ -0,0 +1,83 @@
+//
+// HTTPSStreamFactory.h
+//
+// Library: NetSSL_OpenSSL
+// Package: HTTPSClient
+// Module:  HTTPSStreamFactory
+//
+// Definition of the HTTPSStreamFactory class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_HTTPSStreamFactory_INCLUDED
+#define NetSSL_HTTPSStreamFactory_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/HTTPSession.h"
+#include "Poco/URIStreamFactory.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API HTTPSStreamFactory: public Poco::URIStreamFactory
+	/// An implementation of the URIStreamFactory interface
+	/// that handles secure Hyper-Text Transfer Protocol (https) URIs.
+{
+public:
+	HTTPSStreamFactory();
+		/// Creates the HTTPSStreamFactory.
+
+	HTTPSStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort = HTTPSession::HTTP_PORT);
+		/// Creates the HTTPSStreamFactory.
+		///
+		/// HTTPS connections will use the given proxy.
+
+	HTTPSStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword);
+		/// Creates the HTTPSStreamFactory.
+		///
+		/// HTTPS connections will use the given proxy and
+		/// will be authorized against the proxy using Basic authentication
+		/// with the given proxyUsername and proxyPassword.
+
+	~HTTPSStreamFactory();
+		/// Destroys the HTTPSStreamFactory.
+		
+	std::istream* open(const Poco::URI& uri);
+		/// Creates and opens a HTTPS stream for the given URI.
+		/// The URI must be a https://... URI.
+		///
+		/// Throws a NetException if anything goes wrong.
+		
+	static void registerFactory();
+		/// Registers the HTTPSStreamFactory with the
+		/// default URIStreamOpener instance.	
+
+	static void unregisterFactory();
+		/// Unregisters the HTTPSStreamFactory with the
+		/// default URIStreamOpener instance.	
+		
+private:
+	enum
+	{
+		MAX_REDIRECTS = 10
+	};
+	
+	std::string  _proxyHost;
+	Poco::UInt16 _proxyPort;
+	std::string  _proxyUsername;
+	std::string  _proxyPassword;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPSStreamFactory_INCLUDED
diff --git a/Poco/Net/HTTPServer.h b/Poco/Net/HTTPServer.h
new file mode 100644
index 0000000..69f092a
--- /dev/null
+++ b/Poco/Net/HTTPServer.h
@@ -0,0 +1,103 @@
+//
+// HTTPServer.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServer
+//
+// Definition of the HTTPServer class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServer_INCLUDED
+#define Net_HTTPServer_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/TCPServer.h"
+#include "Poco/Net/HTTPRequestHandlerFactory.h"
+#include "Poco/Net/HTTPServerParams.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPServer: public TCPServer
+	/// A subclass of TCPServer that implements a
+	/// full-featured multithreaded HTTP server.
+	///
+	/// A HTTPRequestHandlerFactory must be supplied.
+	/// The ServerSocket must be bound and in listening state.
+	///
+	/// To configure various aspects of the server, a HTTPServerParams
+	/// object can be passed to the constructor.
+	///
+	/// The server supports:
+	///   - HTTP/1.0 and HTTP/1.1
+	///   - automatic handling of persistent connections.
+	///   - automatic decoding/encoding of request/response message bodies
+	///     using chunked transfer encoding.
+	///
+	/// Please see the TCPServer class for information about
+	/// connection and thread handling.
+	///
+	/// See RFC 2616 <http://www.faqs.org/rfcs/rfc2616.html> for more
+	/// information about the HTTP protocol.
+{
+public:
+	HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::UInt16 portNumber = 80, HTTPServerParams::Ptr pParams = new HTTPServerParams);
+		/// Creates HTTPServer listening on the given port (default 80).
+		///
+		/// The server takes ownership of the HTTPRequstHandlerFactory
+		/// and deletes it when it's no longer needed.
+		///
+		/// New threads are taken from the default thread pool.
+
+	HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, const ServerSocket& socket, HTTPServerParams::Ptr pParams);
+		/// Creates the HTTPServer, using the given ServerSocket.
+		///
+		/// The server takes ownership of the HTTPRequstHandlerFactory
+		/// and deletes it when it's no longer needed.
+		///
+		/// The server also takes ownership of the HTTPServerParams object.
+		///
+		/// New threads are taken from the default thread pool.
+
+	HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams::Ptr pParams);
+		/// Creates the HTTPServer, using the given ServerSocket.
+		///
+		/// The server takes ownership of the HTTPRequstHandlerFactory
+		/// and deletes it when it's no longer needed.
+		///
+		/// The server also takes ownership of the HTTPServerParams object.
+		///
+		/// New threads are taken from the given thread pool.
+
+	~HTTPServer();
+		/// Destroys the HTTPServer and its HTTPRequestHandlerFactory.
+
+	void stopAll(bool abortCurrent = false);
+		/// Stops the server. In contrast to TCPServer::stop(), which also
+		/// stops the server, but allows all client connections to finish at
+		/// their pace, this allows finer control over client connections.
+		///
+		/// If abortCurrent is false, all current requests are allowed to
+		/// complete. If abortCurrent is true, the underlying sockets of
+		/// all client connections are shut down, causing all requests
+		/// to abort.
+
+private:
+	HTTPRequestHandlerFactory::Ptr _pFactory;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServer_INCLUDED
diff --git a/Poco/Net/HTTPServerConnection.h b/Poco/Net/HTTPServerConnection.h
new file mode 100644
index 0000000..536889c
--- /dev/null
+++ b/Poco/Net/HTTPServerConnection.h
@@ -0,0 +1,65 @@
+//
+// HTTPServerConnection.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerConnection
+//
+// Definition of the HTTPServerConnection class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerConnection_INCLUDED
+#define Net_HTTPServerConnection_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/TCPServerConnection.h"
+#include "Poco/Net/HTTPResponse.h"
+#include "Poco/Net/HTTPRequestHandlerFactory.h"
+#include "Poco/Net/HTTPServerParams.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerSession;
+
+
+class Net_API HTTPServerConnection: public TCPServerConnection
+	/// This subclass of TCPServerConnection handles HTTP
+	/// connections.
+{
+public:
+	HTTPServerConnection(const StreamSocket& socket, HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory);
+		/// Creates the HTTPServerConnection.
+
+	virtual ~HTTPServerConnection();
+		/// Destroys the HTTPServerConnection.
+		
+	void run();
+		/// Handles all HTTP requests coming in.
+
+protected:
+	void sendErrorResponse(HTTPServerSession& session, HTTPResponse::HTTPStatus status);
+	void onServerStopped(const bool& abortCurrent);
+
+private:
+	HTTPServerParams::Ptr          _pParams;
+	HTTPRequestHandlerFactory::Ptr _pFactory;
+	bool _stopped;
+	Poco::FastMutex _mutex;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerConnection_INCLUDED
diff --git a/Poco/Net/HTTPServerConnectionFactory.h b/Poco/Net/HTTPServerConnectionFactory.h
new file mode 100644
index 0000000..fc44f91
--- /dev/null
+++ b/Poco/Net/HTTPServerConnectionFactory.h
@@ -0,0 +1,55 @@
+//
+// HTTPServerConnectionFactory.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerConnectionFactory
+//
+// Definition of the HTTPServerConnectionFactory class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerConnectionFactory_INCLUDED
+#define Net_HTTPServerConnectionFactory_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/TCPServerConnectionFactory.h"
+#include "Poco/Net/HTTPRequestHandlerFactory.h"
+#include "Poco/Net/HTTPServerParams.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPServerConnectionFactory: public TCPServerConnectionFactory
+	/// This implementation of a TCPServerConnectionFactory
+	/// is used by HTTPServer to create HTTPServerConnection objects.
+{
+public:
+	HTTPServerConnectionFactory(HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory);
+		/// Creates the HTTPServerConnectionFactory.
+
+	~HTTPServerConnectionFactory();
+		/// Destroys the HTTPServerConnectionFactory.
+
+	TCPServerConnection* createConnection(const StreamSocket& socket);
+		/// Creates an instance of HTTPServerConnection
+		/// using the given StreamSocket.
+	
+private:
+	HTTPServerParams::Ptr          _pParams;
+	HTTPRequestHandlerFactory::Ptr _pFactory;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerConnectionFactory_INCLUDED
diff --git a/Poco/Net/HTTPServerParams.h b/Poco/Net/HTTPServerParams.h
new file mode 100644
index 0000000..0fb86aa
--- /dev/null
+++ b/Poco/Net/HTTPServerParams.h
@@ -0,0 +1,154 @@
+//
+// HTTPServerParams.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerParams
+//
+// Definition of the HTTPServerParams class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerParams_INCLUDED
+#define Net_HTTPServerParams_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/TCPServerParams.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPServerParams: public TCPServerParams
+	/// This class is used to specify parameters to both the
+	/// HTTPServer, as well as to HTTPRequestHandler objects.
+	///
+	/// Subclasses may add new parameters to the class.
+{
+public:
+	typedef Poco::AutoPtr<HTTPServerParams> Ptr;
+	
+	HTTPServerParams();
+		/// Creates the HTTPServerParams.
+		///
+		/// Sets the following default values:
+		///   - timeout:              60 seconds
+		///   - keepAlive:            true
+		///   - maxKeepAliveRequests: 0
+		///   - keepAliveTimeout:     10 seconds
+		
+	void setServerName(const std::string& serverName);
+		/// Sets the name and port (name:port) that the server uses to identify itself.
+		///
+		/// If this is not set to valid DNS name for your host, server-generated
+		/// redirections will not work.
+		
+	const std::string& getServerName() const;
+		/// Returns the name and port (name:port) that the server uses to identify itself.
+
+	void setSoftwareVersion(const std::string& softwareVersion);
+		/// Sets the server software name and version that the server uses to identify
+		/// itself. If this is set to a non-empty string, the server will
+		/// automatically include a Server header field with the value given
+		/// here in every response it sends.
+		///
+		/// The format of the softwareVersion string should be name/version
+		/// (e.g. MyHTTPServer/1.0).
+
+	const std::string& getSoftwareVersion() const;
+		/// Returns the server software name and version that the server uses to
+		/// identify itself.
+
+	void setTimeout(const Poco::Timespan& timeout);
+		/// Sets the connection timeout for HTTP connections.
+		
+	const Poco::Timespan& getTimeout() const;
+		/// Returns the connection timeout for HTTP connections.
+		
+	void setKeepAlive(bool keepAlive);
+		/// Enables (keepAlive == true) or disables (keepAlive == false)
+		/// persistent connections.
+		
+	bool getKeepAlive() const;
+		/// Returns true iff persistent connections are enabled.
+		
+	void setKeepAliveTimeout(const Poco::Timespan& timeout);
+		/// Sets the connection timeout for HTTP connections.
+		
+	const Poco::Timespan& getKeepAliveTimeout() const;
+		/// Returns the connection timeout for HTTP connections.
+	
+	void setMaxKeepAliveRequests(int maxKeepAliveRequests);
+		/// Specifies the maximum number of requests allowed
+		/// during a persistent connection. 0 means unlimited
+		/// connections.
+		
+	int getMaxKeepAliveRequests() const;
+		/// Returns the maximum number of requests allowed
+		/// during a persistent connection, or 0 if
+		/// unlimited connections are allowed.
+
+protected:
+	virtual ~HTTPServerParams();
+		/// Destroys the HTTPServerParams.
+
+private:
+	std::string    _serverName;
+	std::string    _softwareVersion;
+	Poco::Timespan _timeout;
+	bool           _keepAlive;
+	int            _maxKeepAliveRequests;
+	Poco::Timespan _keepAliveTimeout;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPServerParams::getServerName() const
+{
+	return _serverName;
+}
+
+
+inline const std::string& HTTPServerParams::getSoftwareVersion() const
+{
+	return _softwareVersion;
+}
+
+
+inline const Poco::Timespan& HTTPServerParams::getTimeout() const
+{
+	return _timeout;
+}
+
+
+inline bool HTTPServerParams::getKeepAlive() const
+{
+	return _keepAlive;
+}
+
+
+inline int HTTPServerParams::getMaxKeepAliveRequests() const
+{
+	return _maxKeepAliveRequests;
+}
+
+
+inline const Poco::Timespan& HTTPServerParams::getKeepAliveTimeout() const
+{
+	return _keepAliveTimeout;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerParams_INCLUDED
diff --git a/Poco/Net/HTTPServerRequest.h b/Poco/Net/HTTPServerRequest.h
new file mode 100644
index 0000000..69ffeae
--- /dev/null
+++ b/Poco/Net/HTTPServerRequest.h
@@ -0,0 +1,80 @@
+//
+// HTTPServerRequest.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerRequest
+//
+// Definition of the HTTPServerRequest class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerRequest_INCLUDED
+#define Net_HTTPServerRequest_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPRequest.h"
+#include "Poco/Net/SocketAddress.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerSession;
+class HTTPServerResponse;
+class HTTPServerParams;
+
+
+class Net_API HTTPServerRequest: public HTTPRequest
+	/// This abstract subclass of HTTPRequest is used for
+	/// representing server-side HTTP requests.
+	///
+	/// A HTTPServerRequest is passed to the
+	/// handleRequest() method of HTTPRequestHandler.
+{
+public:
+	HTTPServerRequest();
+		/// Creates the HTTPServerRequest
+
+	~HTTPServerRequest();
+		/// Destroys the HTTPServerRequest.
+		
+	virtual std::istream& stream() = 0;
+		/// Returns the input stream for reading
+		/// the request body.
+		///
+		/// The stream must be valid until the HTTPServerRequest
+		/// object is destroyed.
+		
+	virtual const SocketAddress& clientAddress() const = 0;
+		/// Returns the client's address.
+
+	virtual const SocketAddress& serverAddress() const = 0;
+		/// Returns the server's address.
+		
+	virtual const HTTPServerParams& serverParams() const = 0;
+		/// Returns a reference to the server parameters.
+
+	virtual HTTPServerResponse& response() const = 0;
+		/// Returns a reference to the associated response.
+		
+	virtual bool secure() const = 0;
+		/// Returns true if the request is using a secure
+		/// connection. Returns false if no secure connection
+		/// is used, or if it is not known whether a secure
+		/// connection is used.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerRequest_INCLUDED
diff --git a/Poco/Net/HTTPServerRequestImpl.h b/Poco/Net/HTTPServerRequestImpl.h
new file mode 100644
index 0000000..419adbb
--- /dev/null
+++ b/Poco/Net/HTTPServerRequestImpl.h
@@ -0,0 +1,142 @@
+//
+// HTTPServerRequestImpl.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerRequestImpl
+//
+// Definition of the HTTPServerRequestImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerRequestImpl_INCLUDED
+#define Net_HTTPServerRequestImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPServerRequest.h"
+#include "Poco/Net/HTTPServerResponseImpl.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/AutoPtr.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerSession;
+class HTTPServerParams;
+class StreamSocket;
+
+
+class Net_API HTTPServerRequestImpl: public HTTPServerRequest
+	/// This subclass of HTTPServerRequest is used for
+	/// representing server-side HTTP requests.
+	///
+	/// A HTTPServerRequest is passed to the
+	/// handleRequest() method of HTTPRequestHandler.
+{
+public:
+	HTTPServerRequestImpl(HTTPServerResponseImpl& response, HTTPServerSession& session, HTTPServerParams* pParams);
+		/// Creates the HTTPServerRequestImpl, using the
+		/// given HTTPServerSession.
+
+	~HTTPServerRequestImpl();
+		/// Destroys the HTTPServerRequestImpl.
+		
+	std::istream& stream();
+		/// Returns the input stream for reading
+		/// the request body.
+		///
+		/// The stream is valid until the HTTPServerRequestImpl
+		/// object is destroyed.
+		
+	const SocketAddress& clientAddress() const;
+		/// Returns the client's address.
+
+	const SocketAddress& serverAddress() const;
+		/// Returns the server's address.
+		
+	const HTTPServerParams& serverParams() const;
+		/// Returns a reference to the server parameters.
+
+	HTTPServerResponse& response() const;
+		/// Returns a reference to the associated response.
+		
+	bool secure() const;
+		/// Returns true if the request is using a secure
+		/// connection. Returns false if no secure connection
+		/// is used, or if it is not known whether a secure
+		/// connection is used.		
+		
+	StreamSocket& socket();
+		/// Returns a reference to the underlying socket.
+		
+	StreamSocket detachSocket();
+		/// Returns the underlying socket after detaching
+		/// it from the server session.
+		
+	HTTPServerSession& session();
+		/// Returns the underlying HTTPServerSession.
+
+private:
+	HTTPServerResponseImpl&         _response;
+	HTTPServerSession&              _session;
+	std::istream*                   _pStream;
+	Poco::AutoPtr<HTTPServerParams> _pParams;
+	SocketAddress                   _clientAddress;
+	SocketAddress                   _serverAddress;
+};
+
+
+//
+// inlines
+//
+inline std::istream& HTTPServerRequestImpl::stream()
+{
+	poco_check_ptr (_pStream);
+	
+	return *_pStream;
+}
+
+
+inline const SocketAddress& HTTPServerRequestImpl::clientAddress() const
+{
+	return _clientAddress;
+}
+
+
+inline const SocketAddress& HTTPServerRequestImpl::serverAddress() const
+{
+	return _serverAddress;
+}
+
+
+inline const HTTPServerParams& HTTPServerRequestImpl::serverParams() const
+{
+	return *_pParams;
+}
+
+
+inline HTTPServerResponse& HTTPServerRequestImpl::response() const
+{
+	return _response;
+}
+
+
+inline HTTPServerSession& HTTPServerRequestImpl::session()
+{
+	return _session;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerRequestImpl_INCLUDED
diff --git a/Poco/Net/HTTPServerResponse.h b/Poco/Net/HTTPServerResponse.h
new file mode 100644
index 0000000..0eefe5c
--- /dev/null
+++ b/Poco/Net/HTTPServerResponse.h
@@ -0,0 +1,116 @@
+//
+// HTTPServerResponse.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerResponse
+//
+// Definition of the HTTPServerResponse class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerResponse_INCLUDED
+#define Net_HTTPServerResponse_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPResponse.h"
+#include <cstddef>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerSession;
+class HTTPCookie;
+
+
+class Net_API HTTPServerResponse: public HTTPResponse
+	/// This subclass of HTTPResponse is used for
+	/// representing server-side HTTP responses.
+	///
+	/// A HTTPServerResponse is passed to the
+	/// handleRequest() method of HTTPRequestHandler.
+	///
+	/// handleRequest() must set a status code
+	/// and optional reason phrase, set headers
+	/// as necessary, and provide a message body.
+{
+public:
+	HTTPServerResponse();
+		/// Creates the HTTPServerResponse.
+
+	~HTTPServerResponse();
+		/// Destroys the HTTPServerResponse.
+
+	virtual void sendContinue() = 0;
+		/// Sends a 100 Continue response to the
+		/// client.
+		
+	virtual std::ostream& send() = 0;
+		/// Sends the response header to the client and
+		/// returns an output stream for sending the
+		/// response body.
+		///
+		/// The returned stream is valid until the response
+		/// object is destroyed.
+		///
+		/// Must not be called after sendFile(), sendBuffer() 
+		/// or redirect() has been called.
+		
+	virtual void sendFile(const std::string& path, const std::string& mediaType) = 0;
+		/// Sends the response header to the client, followed
+		/// by the content of the given file.
+		///
+		/// Must not be called after send(), sendBuffer() 
+		/// or redirect() has been called.
+		///
+		/// Throws a FileNotFoundException if the file
+		/// cannot be found, or an OpenFileException if
+		/// the file cannot be opened.
+		
+	virtual void sendBuffer(const void* pBuffer, std::size_t length) = 0;
+		/// Sends the response header to the client, followed
+		/// by the contents of the given buffer.
+		///
+		/// The Content-Length header of the response is set
+		/// to length and chunked transfer encoding is disabled.
+		///
+		/// If both the HTTP message header and body (from the
+		/// given buffer) fit into one single network packet, the 
+		/// complete response can be sent in one network packet.
+		///
+		/// Must not be called after send(), sendFile()  
+		/// or redirect() has been called.
+		
+	virtual void redirect(const std::string& uri, HTTPStatus status = HTTP_FOUND) = 0;
+		/// Sets the status code, which must be one of
+		/// HTTP_MOVED_PERMANENTLY (301), HTTP_FOUND (302),
+		/// or HTTP_SEE_OTHER (303),
+		/// and sets the "Location" header field
+		/// to the given URI, which according to
+		/// the HTTP specification, must be absolute.
+		///
+		/// Must not be called after send() has been called.
+		
+	virtual void requireAuthentication(const std::string& realm) = 0;
+		/// Sets the status code to 401 (Unauthorized)
+		/// and sets the "WWW-Authenticate" header field
+		/// according to the given realm.
+		
+	virtual bool sent() const = 0;
+		/// Returns true if the response (header) has been sent.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerResponse_INCLUDED
diff --git a/Poco/Net/HTTPServerResponseImpl.h b/Poco/Net/HTTPServerResponseImpl.h
new file mode 100644
index 0000000..c5d121d
--- /dev/null
+++ b/Poco/Net/HTTPServerResponseImpl.h
@@ -0,0 +1,139 @@
+//
+// HTTPServerResponseImpl.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerResponseImpl
+//
+// Definition of the HTTPServerResponseImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerResponseImpl_INCLUDED
+#define Net_HTTPServerResponseImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPServerResponse.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPServerSession;
+class HTTPServerRequestImpl;
+
+
+class Net_API HTTPServerResponseImpl: public HTTPServerResponse
+	/// This subclass of HTTPServerResponse is used for
+	/// representing server-side HTTP responses.
+	///
+	/// A HTTPServerResponse is passed to the
+	/// handleRequest() method of HTTPRequestHandler.
+	///
+	/// handleRequest() must set a status code
+	/// and optional reason phrase, set headers
+	/// as necessary, and provide a message body.
+{
+public:
+	HTTPServerResponseImpl(HTTPServerSession& session);
+		/// Creates the HTTPServerResponseImpl.
+
+	~HTTPServerResponseImpl();
+		/// Destroys the HTTPServerResponseImpl.
+
+	void sendContinue();
+		/// Sends a 100 Continue response to the
+		/// client.
+		
+	std::ostream& send();
+		/// Sends the response header to the client and
+		/// returns an output stream for sending the
+		/// response body.
+		///
+		/// The returned stream is valid until the response
+		/// object is destroyed.
+		///
+		/// Must not be called after sendFile(), sendBuffer() 
+		/// or redirect() has been called.
+		
+	void sendFile(const std::string& path, const std::string& mediaType);
+		/// Sends the response header to the client, followed
+		/// by the content of the given file.
+		///
+		/// Must not be called after send(), sendBuffer() 
+		/// or redirect() has been called.
+		///
+		/// Throws a FileNotFoundException if the file
+		/// cannot be found, or an OpenFileException if
+		/// the file cannot be opened.
+		
+	void sendBuffer(const void* pBuffer, std::size_t length);
+		/// Sends the response header to the client, followed
+		/// by the contents of the given buffer.
+		///
+		/// The Content-Length header of the response is set
+		/// to length and chunked transfer encoding is disabled.
+		///
+		/// If both the HTTP message header and body (from the
+		/// given buffer) fit into one single network packet, the 
+		/// complete response can be sent in one network packet.
+		///
+		/// Must not be called after send(), sendFile()  
+		/// or redirect() has been called.
+		
+	void redirect(const std::string& uri, HTTPStatus status = HTTP_FOUND);
+		/// Sets the status code, which must be one of
+		/// HTTP_MOVED_PERMANENTLY (301), HTTP_FOUND (302),
+		/// or HTTP_SEE_OTHER (303),
+		/// and sets the "Location" header field
+		/// to the given URI, which according to
+		/// the HTTP specification, must be absolute.
+		///
+		/// Must not be called after send() has been called.
+		
+	void requireAuthentication(const std::string& realm);
+		/// Sets the status code to 401 (Unauthorized)
+		/// and sets the "WWW-Authenticate" header field
+		/// according to the given realm.
+		
+	bool sent() const;
+		/// Returns true if the response (header) has been sent.
+
+protected:
+	void attachRequest(HTTPServerRequestImpl* pRequest);
+	
+private:
+	HTTPServerSession& _session;
+	HTTPServerRequestImpl* _pRequest;
+	std::ostream*      _pStream;
+	
+	friend class HTTPServerRequestImpl;
+};
+
+
+//
+// inlines
+//
+inline bool HTTPServerResponseImpl::sent() const
+{
+	return _pStream != 0;
+}
+
+
+inline void HTTPServerResponseImpl::attachRequest(HTTPServerRequestImpl* pRequest)
+{
+	_pRequest = pRequest;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerResponseImpl_INCLUDED
diff --git a/Poco/Net/HTTPServerSession.h b/Poco/Net/HTTPServerSession.h
new file mode 100644
index 0000000..8b169bf
--- /dev/null
+++ b/Poco/Net/HTTPServerSession.h
@@ -0,0 +1,76 @@
+//
+// HTTPServerSession.h
+//
+// Library: Net
+// Package: HTTPServer
+// Module:  HTTPServerSession
+//
+// Definition of the HTTPServerSession class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPServerSession_INCLUDED
+#define Net_HTTPServerSession_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPSession.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/Net/HTTPServerSession.h"
+#include "Poco/Net/HTTPServerParams.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPServerSession: public HTTPSession
+	/// This class handles the server side of a
+	/// HTTP session. It is used internally by
+	/// HTTPServer.
+{
+public:
+	HTTPServerSession(const StreamSocket& socket, HTTPServerParams::Ptr pParams);
+		/// Creates the HTTPServerSession.
+
+	virtual ~HTTPServerSession();
+		/// Destroys the HTTPServerSession.
+				
+	bool hasMoreRequests();
+		/// Returns true if there are requests available.
+	
+	bool canKeepAlive() const;
+		/// Returns true if the session can be kept alive.
+	
+	SocketAddress clientAddress();
+		/// Returns the client's address.
+		
+	SocketAddress serverAddress();
+		/// Returns the server's address.
+		
+private:
+	bool           _firstRequest;
+	Poco::Timespan _keepAliveTimeout;
+	int            _maxKeepAliveRequests;
+};
+
+
+//
+// inlines
+//
+inline bool HTTPServerSession::canKeepAlive() const
+{
+	return _maxKeepAliveRequests != 0;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPServerSession_INCLUDED
diff --git a/Poco/Net/HTTPSession.h b/Poco/Net/HTTPSession.h
new file mode 100644
index 0000000..666f6f6
--- /dev/null
+++ b/Poco/Net/HTTPSession.h
@@ -0,0 +1,251 @@
+//
+// HTTPSession.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPSession
+//
+// Definition of the HTTPSession class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPSession_INCLUDED
+#define Net_HTTPSession_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Timespan.h"
+#include "Poco/Exception.h"
+#include "Poco/Any.h"
+#include "Poco/Buffer.h"
+#include <ios>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPSession
+	/// HTTPSession implements basic HTTP session management
+	/// for both HTTP clients and HTTP servers.
+	///
+	/// HTTPSession implements buffering for HTTP connections, as well
+	/// as specific support for the various HTTP stream classes.
+	///
+	/// This class can not be instantiated. HTTPClientSession or
+	/// HTTPServerSession must be used instead.
+{
+public:
+	void setKeepAlive(bool keepAlive);
+		/// Sets the keep-alive flag for this session.
+		///
+		/// If the keep-alive flag is enabled, persistent
+		/// HTTP/1.1 connections are supported.
+		
+	bool getKeepAlive() const;
+		/// Returns the value of the keep-alive flag for
+		/// this session.
+
+	void setTimeout(const Poco::Timespan& timeout);
+		/// Sets the timeout for the HTTP session.
+		
+	void setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout);
+		/// Sets different timeouts for the HTTP session.
+
+	Poco::Timespan getTimeout() const;
+		/// Returns the timeout for the HTTP session.
+
+	bool connected() const;
+		/// Returns true if the underlying socket is connected.
+
+	virtual void abort();
+		/// Aborts a session in progress by shutting down
+		/// and closing the underlying socket.
+		
+	const Poco::Exception* networkException() const;
+		/// If sending or receiving data over the underlying
+		/// socket connection resulted in an exception, a
+		/// pointer to this exception is returned.
+		/// 
+		/// Otherwise, NULL is returned.
+
+	void attachSessionData(const Poco::Any& data);
+		/// Allows to attach an application-specific data 
+		/// item to the session.
+		///
+		/// On the server side, this can be used to manage
+		/// data that must be maintained over the entire
+		/// lifetime of a persistent connection (that is,
+		/// multiple requests sent over the same connection).
+	
+	const Poco::Any& sessionData() const;
+		/// Returns the data attached with attachSessionData(),
+		/// or an empty Poco::Any if no user data has been
+		/// attached.
+
+	enum
+	{
+		HTTP_PORT = 80
+	};
+	
+	StreamSocket detachSocket();
+		/// Detaches the socket from the session.
+		///
+		/// The socket is returned, and a new, uninitialized socket is
+		/// attached to the session.
+
+	StreamSocket& socket();
+		/// Returns a reference to the underlying socket.
+		
+	void drainBuffer(Poco::Buffer<char>& buffer);
+		/// Copies all bytes remaining in the internal buffer to the
+		/// given Poco::Buffer, resizing it as necessary.
+		///
+		/// This is usually used together with detachSocket() to
+		/// obtain any data already read from the socket, but not
+		/// yet processed.
+
+protected:
+	HTTPSession();
+		/// Creates a HTTP session using an
+		/// unconnected stream socket.
+
+	HTTPSession(const StreamSocket& socket);
+		/// Creates a HTTP session using the
+		/// given socket. The session takes ownership
+		/// of the socket and closes it when it's no
+		/// longer used.
+
+	HTTPSession(const StreamSocket& socket, bool keepAlive);
+		/// Creates a HTTP session using the
+		/// given socket. The session takes ownership
+		/// of the socket and closes it when it's no
+		/// longer used.
+
+	virtual ~HTTPSession();
+		/// Destroys the HTTPSession and closes the
+		/// underlying socket.
+
+	int get();
+		/// Returns the next byte in the buffer.
+		/// Reads more data from the socket if there are
+		/// no bytes left in the buffer.
+		
+	int peek();
+		/// Peeks at the next character in the buffer.
+		/// Reads more data from the socket if there are
+		/// no bytes left in the buffer.
+		
+	virtual int read(char* buffer, std::streamsize length);
+		/// Reads up to length bytes.
+		///
+		/// If there is data in the buffer, this data
+		/// is returned. Otherwise, data is read from
+		/// the socket to avoid unnecessary buffering.
+	
+	virtual int write(const char* buffer, std::streamsize length);
+		/// Writes data to the socket.
+
+	int receive(char* buffer, int length);
+		/// Reads up to length bytes.
+		
+	int buffered() const;
+		/// Returns the number of bytes in the buffer.
+
+	void refill();
+		/// Refills the internal buffer.
+		
+	virtual void connect(const SocketAddress& address);
+		/// Connects the underlying socket to the given address
+		/// and sets the socket's receive timeout.	
+		
+	void attachSocket(const StreamSocket& socket);
+		/// Attaches a socket to the session, replacing the
+		/// previously attached socket.
+
+	void close();
+		/// Closes the underlying socket.
+		
+	void setException(const Poco::Exception& exc);
+		/// Stores a clone of the exception.
+
+	void clearException();
+		/// Clears the stored exception.
+
+private:
+	enum
+	{
+		HTTP_DEFAULT_TIMEOUT = 60000000,
+		HTTP_DEFAULT_CONNECTION_TIMEOUT = 30000000
+	};
+	
+	HTTPSession(const HTTPSession&);
+	HTTPSession& operator = (const HTTPSession&);
+	
+	StreamSocket     _socket;
+	char*            _pBuffer;
+	char*            _pCurrent;
+	char*            _pEnd;
+	bool             _keepAlive;
+	Poco::Timespan   _connectionTimeout;
+	Poco::Timespan   _receiveTimeout;
+	Poco::Timespan   _sendTimeout;
+	Poco::Exception* _pException;
+	Poco::Any        _data;
+	
+	friend class HTTPStreamBuf;
+	friend class HTTPHeaderStreamBuf;
+	friend class HTTPFixedLengthStreamBuf;
+	friend class HTTPChunkedStreamBuf;
+};
+
+
+//
+// inlines
+//
+inline bool HTTPSession::getKeepAlive() const
+{
+	return _keepAlive;
+}
+
+
+inline Poco::Timespan HTTPSession::getTimeout() const
+{
+	return _receiveTimeout;
+}
+
+
+inline StreamSocket& HTTPSession::socket()
+{
+	return _socket;
+}
+
+
+inline const Poco::Exception* HTTPSession::networkException() const
+{
+	return _pException;
+}
+
+
+inline int HTTPSession::buffered() const
+{
+	return static_cast<int>(_pEnd - _pCurrent);
+}
+
+
+inline const Poco::Any& HTTPSession::sessionData() const
+{
+	return _data;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPSession_INCLUDED
diff --git a/Poco/Net/HTTPSessionFactory.h b/Poco/Net/HTTPSessionFactory.h
new file mode 100644
index 0000000..3bc7d15
--- /dev/null
+++ b/Poco/Net/HTTPSessionFactory.h
@@ -0,0 +1,155 @@
+//
+// HTTPSessionFactory.h
+//
+// Library: Net
+// Package: HTTPClient
+// Module:  HTTPSessionFactory
+//
+// Definition of the HTTPSessionFactory class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPSessionFactoryMgr_INCLUDED
+#define Net_HTTPSessionFactoryMgr_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Mutex.h"
+#include "Poco/URI.h"
+#include "Poco/SingletonHolder.h"
+#include "Poco/SharedPtr.h"
+#include <map>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPSessionInstantiator;
+class HTTPClientSession;
+
+
+class Net_API HTTPSessionFactory
+	/// A factory for HTTPClientSession objects.
+	///
+	/// Given a URI, this class creates a HTTPClientSession
+	/// (for http) or a HTTPSClientSession (for https) for
+	/// accessing the URI.
+	///
+	/// The actual work of creating the session is done by
+	/// HTTPSessionInstantiator objects that must be registered
+	/// with a HTTPSessionFactory.
+{
+public:
+	HTTPSessionFactory();
+		/// Creates the HTTPSessionFactory.
+
+	HTTPSessionFactory(const std::string& proxyHost, Poco::UInt16 proxyPort);
+		/// Creates the HTTPSessionFactory and sets the proxy host and port.
+
+	~HTTPSessionFactory();
+		/// Destroys the HTTPSessionFactory.
+
+	void registerProtocol(const std::string& protocol, HTTPSessionInstantiator* pSessionInstantiator);
+		/// Registers the session instantiator for the given protocol.
+		/// The factory takes ownership of the SessionInstantiator.
+		///
+		/// A protocol can be registered more than once. However, only the instantiator
+		/// that has been registered first is used. Also, for each call to
+		/// registerProtocol(), a corresponding call to unregisterProtocol() must
+		/// be made.
+
+	void unregisterProtocol(const std::string& protocol);
+		/// Removes the registration of a protocol.
+		///
+		/// Throws a NotFoundException if no instantiator has been registered
+		/// for the given protocol.
+
+	bool supportsProtocol(const std::string& protocol);
+		/// Returns true if a session instantiator for the given protocol has been registered.
+
+	HTTPClientSession* createClientSession(const Poco::URI& uri);
+		/// Creates a client session for the given uri scheme. Throws exception if no factory is registered for the given scheme
+
+	const std::string& proxyHost() const;
+		/// Returns the proxy host, if one has been set, or an empty string otherwise.
+		
+	Poco::UInt16 proxyPort() const;
+		/// Returns the proxy port number, if one has been set, or zero otherwise.
+
+	void setProxy(const std::string& proxyHost, Poco::UInt16 proxyPort);
+		/// Sets the proxy host and port number.
+		
+	void setProxyCredentials(const std::string& username, const std::string& password);
+		/// Sets the username and password for proxy authorization (Basic auth only).
+
+	const std::string& proxyUsername() const;
+		/// Returns the username for proxy authorization.
+		
+	const std::string& proxyPassword() const;
+		/// Returns the password for proxy authorization.
+
+	static HTTPSessionFactory& defaultFactory();
+		/// Returns the default HTTPSessionFactory.
+
+private:
+	struct InstantiatorInfo
+	{
+		HTTPSessionInstantiator* pIn;
+		int cnt;
+		InstantiatorInfo(HTTPSessionInstantiator* pInst);
+			// no destructor!!! this is by purpose, don't add one!
+	};
+
+
+	HTTPSessionFactory(const HTTPSessionFactory&);
+	HTTPSessionFactory& operator = (const HTTPSessionFactory&);
+	
+	typedef std::map<std::string, InstantiatorInfo> Instantiators;
+
+	Instantiators _instantiators;
+	std::string   _proxyHost;
+	Poco::UInt16  _proxyPort;
+	std::string   _proxyUsername;
+	std::string   _proxyPassword;
+
+	mutable Poco::FastMutex _mutex;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPSessionFactory::proxyHost() const
+{
+	return _proxyHost;
+}
+
+
+inline Poco::UInt16 HTTPSessionFactory::proxyPort() const
+{
+	return _proxyPort;
+}
+
+
+inline const std::string& HTTPSessionFactory::proxyUsername() const
+{
+	return _proxyUsername;
+}
+
+
+inline const std::string& HTTPSessionFactory::proxyPassword() const
+{
+	return _proxyPassword;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPSessionFactoryMgr_INCLUDED
diff --git a/Poco/Net/HTTPSessionInstantiator.h b/Poco/Net/HTTPSessionInstantiator.h
new file mode 100644
index 0000000..cbb6ee8
--- /dev/null
+++ b/Poco/Net/HTTPSessionInstantiator.h
@@ -0,0 +1,117 @@
+//
+// HTTPSessionInstantiator.h
+//
+// Library: Net
+// Package: HTTPClient
+// Module:  HTTPSessionInstantiator
+//
+// Definition of the HTTPSessionInstantiator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPSessionInstantiator_INCLUDED
+#define Net_HTTPSessionInstantiator_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPSession.h"
+#include "Poco/URI.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPClientSession;
+
+
+class Net_API HTTPSessionInstantiator
+	/// A factory for HTTPClientSession objects.
+	///
+	/// Creates a HTTP session for a given URI.
+	/// A HTTPSessionInstantiator is not used directly.
+	/// Instances are registered with a HTTPSessionFactory,
+	/// and used through it.
+{
+public:
+	HTTPSessionInstantiator();
+		/// Creates the HTTPSessionInstantiator.
+
+	virtual ~HTTPSessionInstantiator();
+		/// Destroys the HTTPSessionInstantiator.
+
+	virtual HTTPClientSession* createClientSession(const Poco::URI& uri);
+		/// Creates a HTTPClientSession for the given URI.
+
+	static void registerInstantiator();
+		/// Registers the instantiator with the global HTTPSessionFactory.
+
+	static void unregisterInstantiator();
+		/// Unregisters the factory with the global HTTPSessionFactory.
+
+protected:
+	void setProxy(const std::string& host, Poco::UInt16 port);
+		/// Sets the proxy host and port.
+		/// Called by HTTPSessionFactory.
+			
+	const std::string& proxyHost() const;
+		/// Returns the proxy post.
+
+	Poco::UInt16 proxyPort() const;
+		/// Returns the proxy port.
+
+	void setProxyCredentials(const std::string& username, const std::string& password);
+		/// Sets the username and password for proxy authorization (Basic auth only).
+
+	const std::string& proxyUsername() const;
+		/// Returns the username for proxy authorization.
+		
+	const std::string& proxyPassword() const;
+		/// Returns the password for proxy authorization.
+
+private:
+	std::string  _proxyHost;
+	Poco::UInt16 _proxyPort;
+	std::string  _proxyUsername;
+	std::string  _proxyPassword;
+	
+	friend class HTTPSessionFactory;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HTTPSessionInstantiator::proxyHost() const
+{
+	return _proxyHost;
+}
+
+
+inline Poco::UInt16 HTTPSessionInstantiator::proxyPort() const
+{
+	return _proxyPort;
+}
+
+
+inline const std::string& HTTPSessionInstantiator::proxyUsername() const
+{
+	return _proxyUsername;
+}
+
+
+inline const std::string& HTTPSessionInstantiator::proxyPassword() const
+{
+	return _proxyPassword;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPSessionInstantiator_INCLUDED
diff --git a/Poco/Net/HTTPStream.h b/Poco/Net/HTTPStream.h
new file mode 100644
index 0000000..94d5209
--- /dev/null
+++ b/Poco/Net/HTTPStream.h
@@ -0,0 +1,103 @@
+//
+// HTTPStream.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPStream
+//
+// Definition of the HTTPStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPStream_INCLUDED
+#define Net_HTTPStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPBasicStreamBuf.h"
+#include "Poco/MemoryPool.h"
+#include <cstddef>
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPSession;
+
+
+class Net_API HTTPStreamBuf: public HTTPBasicStreamBuf
+	/// This is the streambuf class used for reading and writing
+	/// HTTP message bodies.
+{
+public:
+	typedef HTTPBasicStreamBuf::openmode openmode;
+
+	HTTPStreamBuf(HTTPSession& session, openmode mode);
+	~HTTPStreamBuf();
+	void close();
+	
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	HTTPSession& _session;
+	openmode     _mode;
+};
+
+
+class Net_API HTTPIOS: public virtual std::ios
+	/// The base class for HTTPInputStream.
+{
+public:
+	HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode);
+	~HTTPIOS();
+	HTTPStreamBuf* rdbuf();
+
+protected:
+	HTTPStreamBuf _buf;
+};
+
+
+class Net_API HTTPInputStream: public HTTPIOS, public std::istream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPInputStream(HTTPSession& session);
+	~HTTPInputStream();
+
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+class Net_API HTTPOutputStream: public HTTPIOS, public std::ostream
+	/// This class is for internal use by HTTPSession only.
+{
+public:
+	HTTPOutputStream(HTTPSession& session);
+	~HTTPOutputStream();
+
+	void* operator new(std::size_t size);
+	void operator delete(void* ptr);
+	
+private:
+	static Poco::MemoryPool _pool;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPStream_INCLUDED
diff --git a/Poco/Net/HTTPStreamFactory.h b/Poco/Net/HTTPStreamFactory.h
new file mode 100644
index 0000000..df4a5f3
--- /dev/null
+++ b/Poco/Net/HTTPStreamFactory.h
@@ -0,0 +1,92 @@
+//
+// HTTPStreamFactory.h
+//
+// Library: Net
+// Package: HTTP
+// Module:  HTTPStreamFactory
+//
+// Definition of the HTTPStreamFactory class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HTTPStreamFactory_INCLUDED
+#define Net_HTTPStreamFactory_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/HTTPSession.h"
+#include "Poco/URIStreamFactory.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HTTPStreamFactory: public Poco::URIStreamFactory
+	/// An implementation of the URIStreamFactory interface
+	/// that handles Hyper-Text Transfer Protocol (http) URIs.
+{
+public:
+	HTTPStreamFactory();
+		/// Creates the HTTPStreamFactory.
+
+	HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort = HTTPSession::HTTP_PORT);
+		/// Creates the HTTPStreamFactory.
+		///
+		/// HTTP connections will use the given proxy.
+
+	HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword);
+		/// Creates the HTTPStreamFactory.
+		///
+		/// HTTP connections will use the given proxy and
+		/// will be authorized against the proxy using Basic authentication
+		/// with the given proxyUsername and proxyPassword.
+
+	virtual ~HTTPStreamFactory();
+		/// Destroys the HTTPStreamFactory.
+		
+	virtual std::istream* open(const Poco::URI& uri);
+		/// Creates and opens a HTTP stream for the given URI.
+		/// The URI must be a http://... URI.
+		///
+		/// Throws a NetException if anything goes wrong.
+		///
+		/// Redirect responses are handled and the redirect
+		/// location is automatically resolved, as long
+		/// as the redirect location is still accessible
+		/// via the HTTP protocol. If a redirection to
+		/// a non http://... URI is received, a 
+		/// UnsupportedRedirectException exception is thrown.
+		/// The offending URI can then be obtained via the message()
+		/// method of UnsupportedRedirectException.
+		
+	static void registerFactory();
+		/// Registers the HTTPStreamFactory with the
+		/// default URIStreamOpener instance.	
+
+	static void unregisterFactory();
+		/// Unregisters the HTTPStreamFactory with the
+		/// default URIStreamOpener instance.	
+		
+private:
+	enum
+	{
+		MAX_REDIRECTS = 10
+	};
+	
+	std::string  _proxyHost;
+	Poco::UInt16 _proxyPort;
+	std::string  _proxyUsername;
+	std::string  _proxyPassword;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HTTPStreamFactory_INCLUDED
diff --git a/Poco/Net/HostEntry.h b/Poco/Net/HostEntry.h
new file mode 100644
index 0000000..23cccdf
--- /dev/null
+++ b/Poco/Net/HostEntry.h
@@ -0,0 +1,115 @@
+//
+// HostEntry.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  HostEntry
+//
+// Definition of the HostEntry class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_HostEntry_INCLUDED
+#define Net_HostEntry_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Net/IPAddress.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API HostEntry
+	/// This class stores information about a host
+	/// such as host name, alias names and a list
+	/// of IP addresses.
+{
+public:
+	typedef std::vector<std::string> AliasList;
+	typedef std::vector<IPAddress>   AddressList;
+	
+	HostEntry();
+		/// Creates an empty HostEntry.
+		
+	HostEntry(struct hostent* entry);
+		/// Creates the HostEntry from the data in a hostent structure.
+
+#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
+	HostEntry(struct addrinfo* info);
+		/// Creates the HostEntry from the data in an addrinfo structure.
+#endif
+
+#if defined(POCO_VXWORKS)
+	HostEntry(const std::string& name, const IPAddress& addr);
+#endif
+
+	HostEntry(const HostEntry& entry);
+		/// Creates the HostEntry by copying another one.
+
+	HostEntry& operator = (const HostEntry& entry);
+		/// Assigns another HostEntry.
+
+	void swap(HostEntry& hostEntry);
+		/// Swaps the HostEntry with another one.	
+
+	~HostEntry();
+		/// Destroys the HostEntry.
+
+	const std::string& name() const;
+		/// Returns the canonical host name.
+
+	const AliasList& aliases() const;
+		/// Returns a vector containing alias names for
+		/// the host name.
+
+	const AddressList& addresses() const;
+		/// Returns a vector containing the IPAddresses
+		/// for the host.
+
+private:
+	std::string _name;
+	AliasList   _aliases;
+	AddressList _addresses;
+};
+
+
+//
+// inlines
+//
+inline const std::string& HostEntry::name() const
+{
+	return _name;
+}
+
+
+inline const HostEntry::AliasList& HostEntry::aliases() const
+{
+	return _aliases;
+}
+
+
+inline const HostEntry::AddressList& HostEntry::addresses() const
+{
+	return _addresses;
+}
+
+
+inline void swap(HostEntry& h1, HostEntry& h2)
+{
+	h1.swap(h2);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_HostEntry_INCLUDED
diff --git a/Poco/Net/ICMPClient.h b/Poco/Net/ICMPClient.h
new file mode 100644
index 0000000..31fb520
--- /dev/null
+++ b/Poco/Net/ICMPClient.h
@@ -0,0 +1,97 @@
+//
+// ICMPClient.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPClient
+//
+// Definition of the ICMPClient class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPClient_INCLUDED
+#define Net_ICMPClient_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/ICMPSocket.h"
+#include "Poco/Net/ICMPEventArgs.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/BasicEvent.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPClient
+	/// This class provides ICMP Ping functionality.
+	///
+	/// The events are available when class is instantiated
+	///	and non-static member functions are called.
+	/// 
+	///	A "lightweight" alternative is direct (without instantiation)
+	///	use of static member functions.
+{
+public:
+	mutable Poco::BasicEvent<ICMPEventArgs> pingBegin;
+	mutable Poco::BasicEvent<ICMPEventArgs> pingReply;
+	mutable Poco::BasicEvent<ICMPEventArgs> pingError;
+	mutable Poco::BasicEvent<ICMPEventArgs> pingEnd;
+
+	explicit ICMPClient(SocketAddress::Family family, int dataSize = 48, int ttl = 128, int timeout = 50000);
+		/// Creates an ICMP client.
+
+	~ICMPClient();
+		/// Destroys the ICMP client.
+
+	int ping(SocketAddress& address, int repeat = 1) const;
+		/// Pings the specified address [repeat] times.
+		/// Notifications are posted for events.
+		/// 
+		/// Returns the number of valid replies.
+
+	int ping(const std::string& address, int repeat = 1) const;
+		/// Calls ICMPClient::ping(SocketAddress&, int) and
+		/// returns the result.
+		/// 
+		/// Returns the number of valid replies.
+
+	static int ping(SocketAddress& address,
+		SocketAddress::Family family,
+		int repeat = 1,
+		int dataSize = 48,
+		int ttl = 128,
+		int timeout = 50000);
+		/// Pings the specified address [repeat] times.
+		/// Notifications are not posted for events.
+		/// 
+		/// Returns the number of valid replies.
+
+	static int pingIPv4(const std::string& address,
+		int repeat = 1,
+		int dataSize = 48,
+		int ttl = 128,
+		int timeout = 50000);
+		/// Calls ICMPClient::ping(SocketAddress&, int) and
+		/// returns the result.
+		/// 
+		/// Returns the number of valid replies.
+
+private:
+	mutable SocketAddress::Family _family;
+	int _dataSize;
+	int _ttl;
+	int _timeout;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ICMPClient_INCLUDED
diff --git a/Poco/Net/ICMPEventArgs.h b/Poco/Net/ICMPEventArgs.h
new file mode 100644
index 0000000..2a663eb
--- /dev/null
+++ b/Poco/Net/ICMPEventArgs.h
@@ -0,0 +1,163 @@
+//
+// ICMPEventArgs.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPEventArgs
+//
+// Definition of ICMPEventArgs.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPEventArgs_INCLUDED
+#define Net_ICMPEventArgs_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketAddress.h"
+#include <vector>
+#include <algorithm>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPEventArgs
+	/// The purpose of the ICMPEventArgs class is to be used as template parameter
+	/// to instantiate event members in ICMPClient class.
+	/// When clients register for an event notification, the reference to the class is 
+	///	passed to the handler function to provide information about the event.
+{
+public:
+	ICMPEventArgs(const SocketAddress& address, int repetitions, int dataSize, int ttl);
+		/// Creates ICMPEventArgs.
+
+	virtual ~ICMPEventArgs();
+		/// Destroys ICMPEventArgs.
+
+	std::string hostName() const;
+		/// Tries to resolve the target IP address into host name.
+		/// If unsuccessful, all exceptions are silently ignored and 
+		///	the IP address is returned.
+
+	std::string hostAddress() const;
+		/// Returns the target IP address.
+
+	int repetitions() const;
+		/// Returns the number of repetitions for the ping operation.
+
+	int dataSize() const;
+		/// Returns the packet data size in bytes.
+
+	int ttl() const;
+		/// Returns time to live.
+
+	int sent() const;
+		/// Returns the number of packets sent.
+
+	int received() const;
+		/// Returns the number of packets received.
+
+	int replyTime(int index = -1) const;
+		/// Returns the reply time for the request specified with index.
+		/// If index == -1 (default), returns the most recent reply time.
+
+	const std::string& error(int index = -1) const;
+		/// Returns the error string for the request specified with index.
+		/// If index == -1 (default), returns the most recent error string.
+
+	int minRTT() const;
+		/// Returns the minimum round trip time for a sequence of requests.
+
+	int maxRTT() const;
+		/// Returns the maximum round trip time for a sequence of requests.
+
+	int avgRTT() const;
+		/// Returns the average round trip time for a sequence of requests.
+
+	float percent() const;
+		/// Returns the success percentage for a sequence of requests.
+
+private:
+	ICMPEventArgs();
+
+	void setRepetitions(int repetitions);
+	void setDataSize(int sz);
+	void setTTL(int timeToLive);
+	void setReplyTime(int index, int time);
+	void setError(int index, const std::string& text);
+	ICMPEventArgs& operator ++ ();
+	ICMPEventArgs operator ++ (int);
+
+	SocketAddress _address;
+	int _sent;
+	int _dataSize;
+	int _ttl;
+	std::vector<int> _rtt;
+	std::vector<std::string> _errors;
+
+	friend class ICMPClient;
+};
+
+
+//
+// inlines
+//
+inline int ICMPEventArgs::repetitions() const
+{
+	return (int) _rtt.size();
+}
+
+
+inline void ICMPEventArgs::setDataSize(int sz)
+{
+	_dataSize = sz;
+}
+
+
+inline int ICMPEventArgs::dataSize() const
+{
+	return _dataSize;
+}
+
+
+inline void ICMPEventArgs::setTTL(int timeToLive)
+{
+	_ttl = timeToLive;
+}
+
+
+inline int ICMPEventArgs::ttl() const
+{
+	return _ttl;
+}
+
+
+inline int ICMPEventArgs::sent() const
+{
+	return _sent;
+}
+
+
+inline int ICMPEventArgs::minRTT() const
+{
+	return *std::min_element(_rtt.begin(), _rtt.end());
+}
+
+
+inline int ICMPEventArgs::maxRTT() const
+{
+	return *std::max_element(_rtt.begin(), _rtt.end());
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif
diff --git a/Poco/Net/ICMPPacket.h b/Poco/Net/ICMPPacket.h
new file mode 100644
index 0000000..52d0e87
--- /dev/null
+++ b/Poco/Net/ICMPPacket.h
@@ -0,0 +1,89 @@
+//
+// ICMPPacket.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPPacket
+//
+// Definition of the ICMPPacket class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPPacket_INCLUDED
+#define Net_ICMPPacket_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/Net/ICMPPacketImpl.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPPacket
+	/// This class is the ICMP packet abstraction. 
+{
+public:
+	ICMPPacket(SocketAddress::Family family, int dataSize = 48);
+		/// Creates an ICMPPacket of specified family.
+
+	~ICMPPacket();
+		/// Destroys the ICMPPacket.
+
+	const Poco::UInt8* packet();
+		/// Returns raw ICMP packet. ICMP header and data are included in the returned packet.
+
+	int packetSize() const;
+		/// Returns the total length of packet (header + data);
+
+	Poco::UInt16 sequence() const;
+		/// Returns the most recent sequence number generated.
+
+	void setDataSize(int dataSize);
+		/// Sets data size.
+
+	int getDataSize() const;
+		/// Returns data size.
+
+	int maxPacketSize() const;
+		/// Returns the total length of packet (header + data);
+
+	struct timeval time(Poco::UInt8* buffer = 0, int length = 0) const;
+		/// Returns current epoch time if either buffer or length are equal to zero.
+		/// Otherwise, it extracts the time value from the supplied buffer and 
+		/// returns the extracted value.
+		/// 
+		/// Supplied buffer includes IP header, ICMP header and data.
+
+	bool validReplyID(Poco::UInt8* buffer, int length) const;
+		/// Returns true if the extracted id is recognized 
+		/// (equals the process id).
+		///	
+		/// Supplied buffer includes IP header, ICMP header and data.
+
+	std::string errorDescription(Poco::UInt8* buffer, int length);
+		/// Returns error description string.
+		/// If supplied buffer contains an ICMP echo reply packet, an
+		/// empty string is returned indicating the absence of error.
+		///	
+		/// Supplied buffer includes IP header, ICMP header and data.
+
+	std::string typeDescription(int typeId);
+		/// Returns the description of the packet type.
+
+private:
+	ICMPPacketImpl* _pImpl;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ICMPPacket_INCLUDED
diff --git a/Poco/Net/ICMPPacketImpl.h b/Poco/Net/ICMPPacketImpl.h
new file mode 100644
index 0000000..da6bf46
--- /dev/null
+++ b/Poco/Net/ICMPPacketImpl.h
@@ -0,0 +1,141 @@
+//
+// ICMPPacketImpl.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPPacketImpl
+//
+// Definition of the ICMPPacketImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPPacketImpl_INCLUDED
+#define Net_ICMPPacketImpl_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Net/Socket.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPPacketImpl
+	/// This is the abstract class for ICMP packet implementations.
+{
+public:
+	ICMPPacketImpl(int dataSize = 48);
+		/// Constructor. Creates an ICMPPacketImpl.
+
+	virtual ~ICMPPacketImpl();
+		/// Destructor.
+
+	const Poco::UInt8* packet(bool init = true);
+		/// Returns raw ICMP packet.
+		/// ICMP header and data are included in the packet.
+		/// If init is true, initPacket() is called.
+
+	virtual int packetSize() const = 0;
+		/// Returns the total size of packet (ICMP header + data) in number of octets.
+		/// Must be overriden.
+
+	virtual int maxPacketSize() const;
+		/// Returns the maximum permitted size of packet in number of octets.
+
+	Poco::UInt16 sequence() const;
+		/// Returns the most recent sequence number generated.
+
+	void setDataSize(int dataSize);
+		/// Sets data size.
+
+	int getDataSize() const;
+		/// Returns data size.
+
+	virtual struct timeval time(Poco::UInt8* buffer = 0, int length = 0) const = 0;
+		/// Returns current epoch time if either argument is equal to zero.
+		/// Otherwise, it extracts the time value from the supplied buffer.
+		/// 
+		/// Supplied buffer includes IP header, ICMP header and data.
+		/// Must be overriden.
+
+	virtual bool validReplyID(unsigned char* buffer, int length) const = 0;
+		/// Returns true if the extracted id is recognized 
+		/// (i.e. equals the process id).
+		///	
+		/// Supplied buffer includes IP header, ICMP header and data.
+		/// Must be overriden.
+
+	virtual std::string errorDescription(Poco::UInt8* buffer, int length) = 0;
+		/// Returns error description string.
+		/// If supplied buffer contains an ICMP echo reply packet, an
+		/// empty string is returned indicating the absence of error.
+		///	
+		/// Supplied buffer includes IP header, ICMP header and data.
+		/// Must be overriden.
+
+	virtual std::string typeDescription(int typeId) = 0;
+		/// Returns the description of the packet type.
+		/// Must be overriden.
+
+	static const Poco::UInt16 MAX_PACKET_SIZE;
+	static const Poco::UInt16 MAX_SEQ_VALUE;
+
+protected:
+	Poco::UInt16 nextSequence();
+		/// Increments sequence number and returns the new value.
+
+	void resetSequence();
+		/// Resets the sequence to zero.
+
+	virtual void initPacket() = 0;
+		/// (Re)assembles the packet.
+		/// Must be overriden.
+
+	Poco::UInt16 checksum(Poco::UInt16 *addr, Poco::Int32 len);
+		/// Calculates the checksum for supplied buffer.
+
+private:
+	Poco::UInt16 _seq;
+	Poco::UInt8* _pPacket;
+	int _dataSize;
+	
+};
+
+
+//
+// inlines
+//
+inline Poco::UInt16 ICMPPacketImpl::sequence() const
+{
+	return _seq;
+}
+
+
+inline Poco::UInt16 ICMPPacketImpl::nextSequence()
+{
+	return ++_seq;
+}
+
+
+inline void ICMPPacketImpl::resetSequence()
+{
+	_seq = 0;
+}
+
+
+inline int ICMPPacketImpl::maxPacketSize() const
+{
+	return MAX_PACKET_SIZE;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ICMPPacketImpl_INCLUDED
diff --git a/Poco/Net/ICMPSocket.h b/Poco/Net/ICMPSocket.h
new file mode 100644
index 0000000..75e049b
--- /dev/null
+++ b/Poco/Net/ICMPSocket.h
@@ -0,0 +1,91 @@
+//
+// ICMPSocket.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPSocket
+//
+// Definition of the ICMPSocket class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPSocket_INCLUDED
+#define Net_ICMPSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPSocket: public Socket
+	/// This class provides an interface to an
+	/// ICMP client socket.
+{
+public:
+	ICMPSocket(SocketAddress::Family family, int dataSize = 48, int ttl = 128, int timeout = 5000000);
+		/// Creates an unconnected ICMP socket.
+		///
+		/// The socket will be created for the
+		/// given address family.
+
+	ICMPSocket(const Socket& socket);
+		/// Creates the ICMPSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a ICMPSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	~ICMPSocket();
+		/// Destroys the ICMPSocket.
+
+	ICMPSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	int sendTo(const SocketAddress& address, int flags = 0);
+		/// Sends an ICMP request through
+		/// the socket to the given address.
+		///
+		/// Returns the number of bytes sent.
+
+	int receiveFrom(SocketAddress& address, int flags = 0);
+		/// Receives data from the socket.
+		/// Stores the address of the sender in address.
+		///
+		/// Returns the time elapsed since the originating 
+		/// request was sent.
+
+	int dataSize() const;
+		/// Returns the data size in bytes.
+
+	int ttl() const;
+		/// Returns the Time-To-Live value.
+
+	int timeout() const;
+		/// Returns the socket timeout value.
+
+protected:
+	ICMPSocket(SocketImpl* pImpl);
+		/// Creates the Socket and attaches the given SocketImpl.
+		/// The socket takes ownership of the SocketImpl.
+		///
+		/// The SocketImpl must be a ICMPSocketImpl, otherwise
+		/// an InvalidArgumentException will be thrown.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ICMPSocket_INCLUDED
diff --git a/Poco/Net/ICMPSocketImpl.h b/Poco/Net/ICMPSocketImpl.h
new file mode 100644
index 0000000..98ba9a2
--- /dev/null
+++ b/Poco/Net/ICMPSocketImpl.h
@@ -0,0 +1,94 @@
+//
+// ICMPSocketImpl.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPSocketImpl
+//
+// Definition of the ICMPSocketImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPSocketImpl_INCLUDED
+#define Net_ICMPSocketImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/RawSocketImpl.h"
+#include "Poco/Net/ICMPPacket.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPSocketImpl: public RawSocketImpl
+	/// This class implements an ICMP socket.
+{
+public:
+	ICMPSocketImpl(SocketAddress::Family family, int dataSize, int ttl, int timeout);
+		/// Creates an unconnected ICMP socket.
+		///
+		/// The socket will be created for the given address family.
+
+	int sendTo(const void*, int, const SocketAddress& address, int flags = 0);
+		/// Sends an ICMP request through the socket to the given address.
+		///
+		/// Returns the number of bytes sent.
+	
+	int receiveFrom(void*, int, SocketAddress& address, int flags = 0);
+		/// Receives data from the socket.
+		/// Stores the address of the sender in address.
+		///
+		/// Returns the time elapsed since the originating request was sent.
+
+	int dataSize() const;
+		/// Returns the data size in bytes.
+
+	int ttl() const;
+		/// Returns the Time-To-Live value.
+
+	int timeout() const;
+		/// Returns the socket timeout value.
+
+protected:
+	~ICMPSocketImpl();
+
+private:
+	ICMPPacket _icmpPacket;
+	int _ttl;
+	int _timeout;
+};
+
+
+//
+// inlines
+//
+inline int ICMPSocketImpl::dataSize() const
+{
+	return _icmpPacket.getDataSize();
+}
+
+
+inline int ICMPSocketImpl::ttl() const
+{
+	return _ttl;
+}
+
+
+inline int ICMPSocketImpl::timeout() const
+{
+	return _timeout;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ICMPSocketImpl_INCLUDED
diff --git a/Poco/Net/ICMPv4PacketImpl.h b/Poco/Net/ICMPv4PacketImpl.h
new file mode 100644
index 0000000..116f8c7
--- /dev/null
+++ b/Poco/Net/ICMPv4PacketImpl.h
@@ -0,0 +1,173 @@
+//
+// ICMPv4PacketImpl.h
+//
+// Library: Net
+// Package: ICMP
+// Module:  ICMPv4PacketImpl
+//
+// Definition of the ICMPv4PacketImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ICMPv4PacketImpl_INCLUDED
+#define Net_ICMPv4PacketImpl_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/Net/ICMPPacketImpl.h"
+#include <cstddef>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ICMPv4PacketImpl : public ICMPPacketImpl
+	/// This class implements the ICMPv4 packet.
+	/// Parts are based on original ICMP code by
+	/// Mike Muuss
+	/// U. S. Army Ballistic Research Laboratory
+ 	/// December, 1983
+{
+public:
+	// ICMPv4 header
+	struct Header
+	{
+		Poco::UInt8 type;          // ICMP packet type
+		Poco::UInt8 code;          // Type sub code
+		Poco::UInt16 checksum;
+		Poco::UInt16 id;
+		Poco::UInt16 seq;
+	};
+
+	// compile-time shield against misalignment
+#if POCO_OS != POCO_OS_ANDROID
+	poco_static_assert (offsetof(Header, code) == 0x01);
+	poco_static_assert (offsetof(Header, checksum) == 0x02);
+	poco_static_assert (offsetof(Header, id) == 0x04);
+	poco_static_assert (offsetof(Header, seq) == 0x06);
+#endif
+
+	enum MessageType
+	{
+		ECHO_REPLY,
+		ICMP_1,
+		ICMP_2,
+		DESTINATION_UNREACHABLE,
+		SOURCE_QUENCH,
+		REDIRECT,
+		ICMP_6,
+		ICMP_7,
+		ECHO_REQUEST,
+		ICMP_9,
+		ICMP_10,
+		TIME_EXCEEDED,
+		PARAMETER_PROBLEM,
+		TIMESTAMP_REQUEST,
+		TIMESTAMP_REPLY,
+		INFORMATION_REQUEST,
+		INFORMATION_REPLY,
+		MESSAGE_TYPE_UNKNOWN,  // non-standard default, must remain last but one
+		MESSAGE_TYPE_LENGTH    // length indicator, must remain last
+	};
+
+	enum DestinationUnreachableCode
+	{
+		NET_UNREACHABLE,
+		HOST_UNREACHABLE,
+		PROTOCOL_UNREACHABLE,
+		PORT_UNREACHABLE,
+		FRAGMENTATION_NEEDED_AND_DF_SET,
+		SOURCE_ROUTE_FAILED,
+		DESTINATION_UNREACHABLE_UNKNOWN, // non-standard default, must remain last but one
+		DESTINATION_UNREACHABLE_LENGTH   // length indicator, must remain last
+	};
+
+	enum RedirectMessageCode
+	{
+		REDIRECT_NETWORK,
+		REDIRECT_HOST,
+		REDIRECT_SERVICE_NETWORK,
+		REDIRECT_SERVICE_HOST,
+		REDIRECT_MESSAGE_UNKNOWN, // non-standard default, must remain last but one
+		REDIRECT_MESSAGE_LENGTH   // length indicator, must remain last
+	};
+
+	enum TimeExceededCode
+	{
+		TIME_TO_LIVE,
+		FRAGMENT_REASSEMBLY,
+		TIME_EXCEEDED_UNKNOWN, // non-standard default, must remain last but one
+		TIME_EXCEEDED_LENGTH   // length indicator, must remain last
+	};
+
+	enum ParameterProblemCode
+	{
+		POINTER_INDICATES_THE_ERROR,
+		PARAMETER_PROBLEM_UNKNOWN, // non-standard default, must remain last but one
+		PARAMETER_PROBLEM_LENGTH   // length indicator, must remain last
+	};
+
+	ICMPv4PacketImpl(int dataSize = 48);
+		/// Constructor. Creates an ICMPv4PacketImpl.
+
+	~ICMPv4PacketImpl();
+		/// Destructor.
+
+	int packetSize() const;
+		/// Returns the total length of packet (header + data);
+
+	struct timeval time(Poco::UInt8* buffer = 0, int length = 0) const;
+		/// Returns current epoch time if either buffer or length are equal to zero.
+		/// Otherwise, it extracts the time value from the supplied buffer.
+		///
+		/// Buffer includes IP header, ICMP header and data.
+
+	bool validReplyID(Poco::UInt8* buffer, int length) const;
+		/// Returns true if the extracted id is recognized
+		/// (i.e. equals the process id).
+		///
+		/// Buffer includes IP header, ICMP header and data.
+
+	virtual std::string errorDescription(Poco::UInt8* buffer, int length);
+		/// Returns error description string.
+		/// If supplied buffer contains ICMPv4 echo reply packet, an
+		/// empty string is returned indicating the absence of error.
+		///
+		/// Buffer includes IP header, ICMP header and data.
+
+	virtual std::string typeDescription(int typeId);
+		/// Returns the description of the packet type.
+
+	static const Poco::UInt16 MAX_PACKET_SIZE;
+	static const std::string MESSAGE_TYPE[MESSAGE_TYPE_LENGTH];
+	static const Poco::UInt8 DESTINATION_UNREACHABLE_TYPE; // 3
+	static const Poco::UInt8 SOURCE_QUENCH_TYPE;           // 4
+	static const Poco::UInt8 REDIRECT_MESSAGE_TYPE;        // 5
+	static const Poco::UInt8 TIME_EXCEEDED_TYPE;           // 11
+	static const Poco::UInt8 PARAMETER_PROBLEM_TYPE;       // 12
+
+private:
+	void initPacket();
+	Header* header(Poco::UInt8* buffer, int length) const;
+	Poco::UInt8* data(Poco::UInt8* buffer, int length) const;
+
+	static const std::string DESTINATION_UNREACHABLE_CODE[DESTINATION_UNREACHABLE_LENGTH];
+	static const std::string REDIRECT_MESSAGE_CODE[REDIRECT_MESSAGE_LENGTH];
+	static const std::string TIME_EXCEEDED_CODE[TIME_EXCEEDED_LENGTH];
+	static const std::string PARAMETER_PROBLEM_CODE[PARAMETER_PROBLEM_LENGTH];
+
+	Poco::UInt16 _seq;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ICMPv4PacketImpl_INCLUDED
diff --git a/Poco/Net/IPAddress.h b/Poco/Net/IPAddress.h
new file mode 100644
index 0000000..7d9cb6f
--- /dev/null
+++ b/Poco/Net/IPAddress.h
@@ -0,0 +1,450 @@
+//
+// IPAddress.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  IPAddress
+//
+// Definition of the IPAddress class.
+//
+// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_IPAddress_INCLUDED
+#define Net_IPAddress_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Net/IPAddressImpl.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Exception.h"
+#include <vector>
+#include <ostream>
+
+
+namespace Poco {
+
+class BinaryReader;
+class BinaryWriter;
+
+namespace Net {
+
+
+class Net_API IPAddress
+	/// This class represents an internet (IP) host
+	/// address. The address can belong either to the
+	/// IPv4 or the IPv6 address family.
+	///
+	/// Relational operators (==, !=, <, <=, >, >=) are
+	/// supported. However, you must not interpret any
+	/// special meaning into the result of these 
+	/// operations, other than that the results are
+	/// consistent.
+	///
+	/// Especially, an IPv4 address is never equal to
+	/// an IPv6 address, even if the IPv6 address is
+	/// IPv4 compatible and the addresses are the same.
+	///
+	/// IPv6 addresses are supported only if the target platform
+	/// supports IPv6.
+{
+public:
+	typedef std::vector<IPAddress> List;
+
+	// The following declarations keep the Family type
+	// backwards compatible with the previously used
+	// enum declaration.
+	typedef AddressFamily::Family Family;
+	static const Family IPv4 = AddressFamily::IPv4;
+#if defined(POCO_HAVE_IPv6)
+	static const Family IPv6 = AddressFamily::IPv6;
+#endif
+	
+	IPAddress();
+		/// Creates a wildcard (zero) IPv4 IPAddress.
+
+	IPAddress(const IPAddress& addr);
+		/// Creates an IPAddress by copying another one.
+
+	explicit IPAddress(Family family);
+		/// Creates a wildcard (zero) IPAddress for the
+		/// given address family.
+
+	explicit IPAddress(const std::string& addr);
+		/// Creates an IPAddress from the string containing
+		/// an IP address in presentation format (dotted decimal
+		/// for IPv4, hex string for IPv6).
+		/// 
+		/// Depending on the format of addr, either an IPv4 or
+		/// an IPv6 address is created.
+		///
+		/// See toString() for details on the supported formats.
+		///
+		/// Throws an InvalidAddressException if the address cannot be parsed.
+
+	IPAddress(const std::string& addr, Family family);
+		/// Creates an IPAddress from the string containing
+		/// an IP address in presentation format (dotted decimal
+		/// for IPv4, hex string for IPv6).
+
+	IPAddress(const void* addr, poco_socklen_t length);
+		/// Creates an IPAddress from a native internet address.
+		/// A pointer to a in_addr or a in6_addr structure may be 
+		/// passed.
+
+	IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope);
+		/// Creates an IPAddress from a native internet address.
+		/// A pointer to a in_addr or a in6_addr structure may be 
+		/// passed. Additionally, for an IPv6 address, a scope ID
+		/// may be specified. The scope ID will be ignored if an IPv4
+		/// address is specified.
+
+	IPAddress(unsigned prefix, Family family);
+			/// Creates an IPAddress mask with the given length of prefix.
+
+#if defined(_WIN32)
+	IPAddress(const SOCKET_ADDRESS& socket_address);
+			/// Creates an IPAddress from Windows SOCKET_ADDRESS structure.
+#endif
+
+	IPAddress(const struct sockaddr& sockaddr);
+		/// Same for struct sock_addr on POSIX.
+
+
+	~IPAddress();
+		/// Destroys the IPAddress.
+
+	IPAddress& operator = (const IPAddress& addr);
+		/// Assigns an IPAddress.
+		
+	Family family() const;
+		/// Returns the address family (IPv4 or IPv6) of the address.
+
+	Poco::UInt32 scope() const;
+		/// Returns the IPv6 scope identifier of the address. Returns 0 if
+		/// the address is an IPv4 address, or the address is an
+		/// IPv6 address but does not have a scope identifier.
+
+	std::string toString() const;
+		/// Returns a string containing a representation of the address
+		/// in presentation format.
+		///
+		/// For IPv4 addresses the result will be in dotted-decimal
+		/// (d.d.d.d) notation.
+		///
+		/// Textual representation of IPv6 address is one of the following forms:
+		///
+		/// The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the hexadecimal 
+		/// values of the eight 16-bit pieces of the address. This is the full form.
+		/// Example: 1080:0:0:0:8:600:200A:425C
+		///
+		/// It is not necessary to write the leading zeros in an individual field. 
+		/// However, there must be at least one numeral in every field, except as described below.
+		/// 
+		/// It is common for IPv6 addresses to contain long strings of zero bits. 
+		/// In order to make writing addresses containing zero bits easier, a special syntax is 
+		/// available to compress the zeros. The use of "::" indicates multiple groups of 16-bits of zeros. 
+		/// The "::" can only appear once in an address. The "::" can also be used to compress the leading 
+		/// and/or trailing zeros in an address. Example: 1080::8:600:200A:425C
+		///
+		/// For dealing with IPv4 compatible addresses in a mixed environment,
+		/// a special syntax is available: x:x:x:x:x:x:d.d.d.d, where the 'x's are the 
+		/// hexadecimal values of the six high-order 16-bit pieces of the address, 
+		/// and the 'd's are the decimal values of the four low-order 8-bit pieces of the 
+		/// standard IPv4 representation address. Example: ::FFFF:192.168.1.120
+		///
+		/// If an IPv6 address contains a non-zero scope identifier, it is added
+		/// to the string, delimited by a percent character. On Windows platforms,
+		/// the numeric value (which specifies an interface index) is directly
+		/// appended. On Unix platforms, the name of the interface corresponding
+		/// to the index (interpretation of the scope identifier) is added.
+	
+	bool isWildcard() const;
+		/// Returns true iff the address is a wildcard (all zero)
+		/// address.
+		
+	bool isBroadcast() const;
+		/// Returns true iff the address is a broadcast address.
+		///
+		/// Only IPv4 addresses can be broadcast addresses. In a broadcast
+		/// address, all bits are one.
+		///
+		/// For an IPv6 address, returns always false.
+	
+	bool isLoopback() const;
+		/// Returns true iff the address is a loopback address.
+		///
+		/// For IPv4, the loopback address is 127.0.0.1.
+		///
+		/// For IPv6, the loopback address is ::1.
+	
+	bool isMulticast() const;
+		/// Returns true iff the address is a multicast address.
+		///
+		/// IPv4 multicast addresses are in the
+		/// 224.0.0.0 to 239.255.255.255 range
+		/// (the first four bits have the value 1110).
+		///
+		/// IPv6 multicast addresses are in the
+		/// FFxx:x:x:x:x:x:x:x range.
+		
+	bool isUnicast() const;
+		/// Returns true iff the address is a unicast address.
+		///
+		/// An address is unicast if it is neither a wildcard,
+		/// broadcast or multicast address.
+		
+	bool isLinkLocal() const;
+		/// Returns true iff the address is a link local unicast address.
+		///
+		/// IPv4 link local addresses are in the 169.254.0.0/16 range,
+		/// according to RFC 3927.
+		///
+		/// IPv6 link local addresses have 1111 1110 10 as the first
+		/// 10 bits, followed by 54 zeros.
+		
+	bool isSiteLocal() const;
+		/// Returns true iff the address is a site local unicast address.
+		///
+		/// IPv4 site local addresses are in on of the 10.0.0.0/24,
+		/// 192.168.0.0/16 or 172.16.0.0 to 172.31.255.255 ranges.
+		///
+		/// Originally, IPv6 site-local addresses had FEC0/10 (1111 1110 11) 
+		/// prefix (RFC 4291), followed by 38 zeros. Interfaces using  
+		/// this mask are supported, but obsolete; RFC 4193 prescribes
+		/// fc00::/7 (1111 110) as local unicast prefix.
+		
+	bool isIPv4Compatible() const;
+		/// Returns true iff the address is IPv4 compatible.
+		///
+		/// For IPv4 addresses, this is always true.
+		///
+		/// For IPv6, the address must be in the ::x:x range (the
+		/// first 96 bits are zero).
+
+	bool isIPv4Mapped() const;
+		/// Returns true iff the address is an IPv4 mapped IPv6 address.
+		///
+		/// For IPv4 addresses, this is always true.
+		///
+		/// For IPv6, the address must be in the ::FFFF:x:x range.
+	
+	bool isWellKnownMC() const;
+		/// Returns true iff the address is a well-known multicast address.
+		///
+		/// For IPv4, well-known multicast addresses are in the 
+		/// 224.0.0.0/8 range.
+		///
+		/// For IPv6, well-known multicast addresses are in the 
+		/// FF0x:x:x:x:x:x:x:x range.
+	
+	bool isNodeLocalMC() const;
+		/// Returns true iff the address is a node-local multicast address.
+		///
+		/// IPv4 does not support node-local addresses, thus the result is
+		/// always false for an IPv4 address.
+		///
+		/// For IPv6, node-local multicast addresses are in the
+		/// FFx1:x:x:x:x:x:x:x range.
+	
+	bool isLinkLocalMC() const;
+		/// Returns true iff the address is a link-local multicast address.
+		///
+		/// For IPv4, link-local multicast addresses are in the
+		/// 224.0.0.0/24 range. Note that this overlaps with the range for well-known
+		/// multicast addresses.
+		///
+		/// For IPv6, link-local multicast addresses are in the
+		/// FFx2:x:x:x:x:x:x:x range.
+
+	bool isSiteLocalMC() const;
+		/// Returns true iff the address is a site-local multicast address.
+		///
+		/// For IPv4, site local multicast addresses are in the
+		/// 239.255.0.0/16 range.
+		///
+		/// For IPv6, site-local multicast addresses are in the
+		/// FFx5:x:x:x:x:x:x:x range.
+
+	bool isOrgLocalMC() const;
+		/// Returns true iff the address is a organization-local multicast address.
+		///
+		/// For IPv4, organization-local multicast addresses are in the
+		/// 239.192.0.0/16 range.
+		///
+		/// For IPv6, organization-local multicast addresses are in the
+		/// FFx8:x:x:x:x:x:x:x range.
+
+	bool isGlobalMC() const;
+		/// Returns true iff the address is a global multicast address.
+		///
+		/// For IPv4, global multicast addresses are in the 
+		/// 224.0.1.0 to 238.255.255.255 range.
+		///
+		/// For IPv6, global multicast addresses are in the
+		/// FFxF:x:x:x:x:x:x:x range.
+	
+	bool operator == (const IPAddress& addr) const;	
+	bool operator != (const IPAddress& addr) const;
+	bool operator <  (const IPAddress& addr) const;
+	bool operator <= (const IPAddress& addr) const;
+	bool operator >  (const IPAddress& addr) const;
+	bool operator >= (const IPAddress& addr) const;
+	IPAddress operator & (const IPAddress& addr) const;
+	IPAddress operator | (const IPAddress& addr) const;
+	IPAddress operator ^ (const IPAddress& addr) const;
+	IPAddress operator ~ () const;
+		
+	poco_socklen_t length() const;
+		/// Returns the length in bytes of the internal socket address structure.	
+		
+	const void* addr() const;
+		/// Returns the internal address structure.
+		
+	int af() const;
+		/// Returns the address family (AF_INET or AF_INET6) of the address.
+
+	unsigned prefixLength() const;
+		/// Returns the prefix length.
+		
+	void mask(const IPAddress& mask);
+		/// Masks the IP address using the given netmask, which is usually
+		/// a IPv4 subnet mask. Only supported for IPv4 addresses.
+		///
+		/// The new address is (address & mask).
+		
+	void mask(const IPAddress& mask, const IPAddress& set);
+		/// Masks the IP address using the given netmask, which is usually
+		/// a IPv4 subnet mask. Only supported for IPv4 addresses.
+		///
+		/// The new address is (address & mask) | (set & ~mask).
+		
+	static IPAddress parse(const std::string& addr);
+		/// Creates an IPAddress from the string containing
+		/// an IP address in presentation format (dotted decimal
+		/// for IPv4, hex string for IPv6).
+		/// 
+		/// Depending on the format of addr, either an IPv4 or
+		/// an IPv6 address is created.
+		///
+		/// See toString() for details on the supported formats.
+		///
+		/// Throws an InvalidAddressException if the address cannot be parsed.
+
+	static bool tryParse(const std::string& addr, IPAddress& result);
+		/// Tries to interpret the given address string as an
+		/// IP address in presentation format (dotted decimal
+		/// for IPv4, hex string for IPv6).
+		///
+		/// Returns true and stores the IPAddress in result if the
+		/// string contains a valid address.
+		///
+		/// Returns false and leaves result unchanged otherwise.
+
+	static IPAddress wildcard(Family family = IPv4);
+		/// Returns a wildcard IPv4 or IPv6 address (0.0.0.0).
+		
+	static IPAddress broadcast();
+		/// Returns a broadcast IPv4 address (255.255.255.255).
+
+	enum
+	{
+		MAX_ADDRESS_LENGTH = 
+#if defined(POCO_HAVE_IPv6)
+			sizeof(struct in6_addr)
+#else
+			sizeof(struct in_addr)
+#endif
+			/// Maximum length in bytes of a socket address.
+	};
+
+private:
+	typedef Poco::Net::Impl::IPAddressImpl Impl;
+	typedef Poco::AutoPtr<Impl> Ptr;
+
+	Ptr pImpl() const;
+	void newIPv4();
+	void newIPv4(const void* hostAddr);
+	void newIPv4(unsigned prefix);
+#if defined(POCO_HAVE_IPv6)
+	void newIPv6();
+	void newIPv6(const void* hostAddr);
+	void newIPv6(const void* hostAddr, Poco::UInt32 scope);
+	void newIPv6(unsigned prefix);
+#endif
+	Ptr _pImpl;
+};
+
+
+//
+// inlines
+//
+inline IPAddress::Ptr IPAddress::pImpl() const
+{
+	if (_pImpl) return _pImpl;
+	throw NullPointerException("IPaddress implementation pointer is NULL.");
+}
+
+
+inline void IPAddress::newIPv4()
+{
+	_pImpl = new Poco::Net::Impl::IPv4AddressImpl;
+}
+
+
+inline void IPAddress::newIPv4(const void* hostAddr)
+{
+	_pImpl = new Poco::Net::Impl::IPv4AddressImpl(hostAddr);
+}
+
+
+inline void IPAddress::newIPv4(unsigned prefix)
+{
+	_pImpl = new Poco::Net::Impl::IPv4AddressImpl(prefix);
+}
+
+
+#if defined(POCO_HAVE_IPv6)
+
+
+inline void IPAddress::newIPv6()
+{
+	_pImpl = new Poco::Net::Impl::IPv6AddressImpl;
+}
+
+
+inline void IPAddress::newIPv6(const void* hostAddr)
+{
+	_pImpl = new Poco::Net::Impl::IPv6AddressImpl(hostAddr);
+}
+
+
+inline void IPAddress::newIPv6(const void* hostAddr, Poco::UInt32 scope)
+{
+	_pImpl = new Poco::Net::Impl::IPv6AddressImpl(hostAddr, scope);
+}
+
+
+inline void IPAddress::newIPv6(unsigned prefix)
+{
+	_pImpl = new Poco::Net::Impl::IPv6AddressImpl(prefix);
+}
+
+
+#endif // POCO_HAVE_IPv6
+
+
+} } // namespace Poco::Net
+
+
+Net_API Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value);
+Net_API Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value);
+Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr);
+
+
+#endif // Net_IPAddress_INCLUDED
diff --git a/Poco/Net/IPAddressImpl.h b/Poco/Net/IPAddressImpl.h
new file mode 100644
index 0000000..e43d685
--- /dev/null
+++ b/Poco/Net/IPAddressImpl.h
@@ -0,0 +1,179 @@
+//
+// IPAddressImpl.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  IPAddressImpl
+//
+// Definition of the IPAddressImpl class.
+//
+// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_IPAddressImpl_INCLUDED
+#define Net_IPAddressImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/RefCountedObject.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+namespace Impl {
+
+
+class IPAddressImpl : public Poco::RefCountedObject
+{
+public:
+	typedef AddressFamily::Family Family;
+	
+	virtual ~IPAddressImpl();
+
+	virtual IPAddressImpl* clone() const = 0;
+	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;
+
+protected:
+	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;
+};
+
+
+#if defined(POCO_HAVE_IPv6)
+
+
+//
+// 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;
+};
+
+
+#endif // POCO_HAVE_IPv6
+
+
+} } } // namespace Poco::Net::Impl
+
+
+#endif // Net_IPAddressImpl_INCLUDED
diff --git a/Poco/Net/InvalidCertificateHandler.h b/Poco/Net/InvalidCertificateHandler.h
new file mode 100644
index 0000000..e10faf3
--- /dev/null
+++ b/Poco/Net/InvalidCertificateHandler.h
@@ -0,0 +1,80 @@
+//
+// InvalidCertificateHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  InvalidCertificateHandler
+//
+// Definition of the InvalidCertificateHandler class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_InvalidCertificateHandler_INCLUDED
+#define NetSSL_InvalidCertificateHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/VerificationErrorArgs.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API InvalidCertificateHandler
+	/// A InvalidCertificateHandler is invoked whenever an error occurs verifying the certificate. It allows the user
+	/// to inspect and accept/reject the certificate.
+	/// One can install one's own InvalidCertificateHandler by implementing this interface. Note that
+	/// in the implementation file of the subclass the following code must be present (assuming you use the namespace My_API 
+	/// and the name of your handler class is MyGuiHandler):
+	///    
+	///    #include "Poco/Net/CertificateHandlerFactory.h"
+	///    ...
+	///    POCO_REGISTER_CHFACTORY(My_API, MyGuiHandler)
+	///
+	/// One can either set the handler directly in the startup code of the main method of ones application by calling
+	///
+	///    SSLManager::instance().initialize(mypassphraseHandler, myguiHandler, mySSLContext)
+	///
+	/// or in case one uses Poco::Util::Application one can rely on an XML configuration and put the following entry
+	/// under the path openSSL.invalidCertificateHandler:
+	///    
+	///    <invalidCertificateHandler>
+	///        <name>MyGuiHandler<name>
+	///        <options>
+	///            [...] // Put optional config params for the handler here
+	///        </options>
+	///    </invalidCertificateHandler>
+	///
+	/// Note that the name of the InvalidCertificateHandler must be same as the one provided to the POCO_REGISTER_CHFACTORY macro.
+{
+public:
+	InvalidCertificateHandler(bool handleErrorsOnServerSide);
+		/// Creates the InvalidCertificateHandler.
+		/// 
+		/// Set handleErrorsOnServerSide to true if the certificate handler is used on the server side.
+		/// Automatically registers at one of the SSLManager::VerificationError events.
+
+	virtual ~InvalidCertificateHandler();
+		/// Destroys the InvalidCertificateHandler.
+
+	virtual void onInvalidCertificate(const void* pSender, VerificationErrorArgs& errorCert) = 0;
+		/// Receives the questionable certificate in parameter errorCert. If one wants to accept the
+		/// certificate, call errorCert.setIgnoreError(true).
+
+protected:
+	bool _handleErrorsOnServerSide;
+		/// Stores if the certificate handler gets invoked by the server (i.e. a client certificate is wrong)
+		/// or the client (a server certificate is wrong)
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_InvalidCertificateHandler_INCLUDED
diff --git a/Poco/Net/KeyConsoleHandler.h b/Poco/Net/KeyConsoleHandler.h
new file mode 100644
index 0000000..d9483d7
--- /dev/null
+++ b/Poco/Net/KeyConsoleHandler.h
@@ -0,0 +1,47 @@
+//
+// KeyConsoleHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  KeyConsoleHandler
+//
+// Definition of the KeyConsoleHandler class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_KeyConsoleHandler_INCLUDED
+#define NetSSL_KeyConsoleHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/PrivateKeyPassphraseHandler.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API KeyConsoleHandler: public PrivateKeyPassphraseHandler
+	/// An implementation of PrivateKeyPassphraseHandler that
+	/// reads the key for a certificate from the console.
+{
+public:
+	KeyConsoleHandler(bool server);
+		/// Creates the KeyConsoleHandler.
+
+	~KeyConsoleHandler();
+		/// Destroys the KeyConsoleHandler.
+
+	void onPrivateKeyRequested(const void* pSender, std::string& privateKey);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_KeyConsoleHandler_INCLUDED
diff --git a/Poco/Net/KeyFileHandler.h b/Poco/Net/KeyFileHandler.h
new file mode 100644
index 0000000..274cdbf
--- /dev/null
+++ b/Poco/Net/KeyFileHandler.h
@@ -0,0 +1,51 @@
+//
+// KeyFileHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  KeyFileHandler
+//
+// Definition of the KeyFileHandler class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_KeyFileHandler_INCLUDED
+#define NetSSL_KeyFileHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/PrivateKeyPassphraseHandler.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API KeyFileHandler: public PrivateKeyPassphraseHandler
+	/// An implementation of PrivateKeyPassphraseHandler that 
+	/// reads the key for a certificate from a configuration file
+	/// under the path "openSSL.privateKeyPassphraseHandler.options.password".
+{
+public:
+	KeyFileHandler(bool server);
+		/// Creates the KeyFileHandler.
+
+	virtual ~KeyFileHandler();
+		/// Destroys the KeyFileHandler.
+
+	void onPrivateKeyRequested(const void* pSender, std::string& privateKey);
+
+private:
+	static const std::string CFG_PRIV_KEY_FILE;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_KeyFileHandler_INCLUDED
diff --git a/Poco/Net/MailMessage.h b/Poco/Net/MailMessage.h
new file mode 100644
index 0000000..4741860
--- /dev/null
+++ b/Poco/Net/MailMessage.h
@@ -0,0 +1,314 @@
+//
+// MailMessage.h
+//
+// Library: Net
+// Package: Mail
+// Module:  MailMessage
+//
+// Definition of the MailMessage class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MailMessage_INCLUDED
+#define Net_MailMessage_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/MessageHeader.h"
+#include "Poco/Net/MailRecipient.h"
+#include "Poco/Net/PartStore.h"
+#include "Poco/Timestamp.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class MediaType;
+class PartSource;
+class PartHandler;
+class MultipartWriter;
+
+
+class Net_API MailMessage: public MessageHeader
+	/// This class represents an e-mail message for
+	/// use with the SMTPClientSession and POPClientSession
+	/// classes.
+	///
+	/// MailMessage supports both old-style plain text messages,
+	/// as well as MIME multipart mail messages with attachments.
+	///
+	/// For multi-part messages, the following content transfer
+	/// encodings are supported: 7bit, 8bit, quoted-printable
+	/// and base64.
+{
+public:
+	typedef std::vector<MailRecipient> Recipients;
+
+	enum ContentDisposition
+	{
+		CONTENT_INLINE,
+		CONTENT_ATTACHMENT
+	};
+
+	enum ContentTransferEncoding
+	{
+		ENCODING_7BIT,
+		ENCODING_8BIT,
+		ENCODING_QUOTED_PRINTABLE,
+		ENCODING_BASE64
+	};
+
+	struct Part
+	{
+		std::string             name;
+		PartSource*             pSource;
+		ContentDisposition      disposition;
+		ContentTransferEncoding encoding;
+	};
+
+	typedef std::vector<Part> PartVec;
+
+	MailMessage(PartStoreFactory* pStoreFactory = 0);
+		/// Creates an empty MailMessage.
+		///
+		/// If pStoreFactory is not null, message attachments will be
+		/// handled by the object created by the factory. Most
+		/// common reason is to temporarily save attachments to
+		/// the file system in order to avoid potential memory
+		/// exhaustion when attachment files are very large.
+
+	virtual ~MailMessage();
+		/// Destroys the MailMessage.
+
+	void addRecipient(const MailRecipient& recipient);
+		/// Adds a recipient for the message.
+
+	void setRecipients(const Recipients& recipient);
+		/// Clears existing and sets new recipient list for the message.
+
+	const Recipients& recipients() const;
+		/// Returns the recipients of the message.
+
+	void setSubject(const std::string& subject);
+		/// Sets the subject of the message.
+		///
+		/// The subject must not contain any non-ASCII
+		/// characters. To include non-ASCII characters
+		/// in the subject, use RFC 2047 word encoding
+		/// (see encodeWord()).
+
+	const std::string& getSubject() const;
+		/// Returns the subject of the message.
+
+	void setSender(const std::string& sender);
+		/// Sets the sender of the message (which
+		/// ends up in the From header field).
+		///
+		/// The sender must either be a valid email
+		/// address, or a real name followed by
+		/// an email address enclosed in < and >.
+		///
+		/// The sender must not contain any non-ASCII
+		/// characters. To include non-ASCII characters
+		/// in the sender, use RFC 2047 word encoding
+		/// (see encodeWord()).
+
+	const std::string& getSender() const;
+		/// Returns the sender of the message (taken
+		/// from the From header field).
+
+	void setContent(const std::string& content, ContentTransferEncoding encoding = ENCODING_QUOTED_PRINTABLE);
+		/// Sets the content of the mail message.
+		///
+		/// If the content transfer encoding is ENCODING_7BIT or
+		/// ENCODING_8BIT, the content string must be formatted
+		/// according to the rules of an internet email message.
+		///
+		/// The message will be sent as a single-part
+		/// message.
+		///
+		/// Note that single CR or LF characters as line delimiters must
+		/// not be used. Content lines always should be terminated with a
+		/// proper CRLF sequence.
+
+	const std::string& getContent() const;
+		/// Returns the content of the mail message.
+		///
+		/// A content will only be returned for single-part
+		/// messages. The content of multi-part mail messages
+		/// will be reported through the registered PartHandler.
+
+	void setContentType(const std::string& mediaType);
+		/// Sets the content type for the message.
+
+	void setContentType(const MediaType& mediaType);
+		/// Sets the content type for the message.
+
+	const std::string& getContentType() const;
+		/// Returns the content type for the message.
+
+	void setDate(const Poco::Timestamp& dateTime);
+		/// Sets the Date header to the given date/time value.
+
+	Poco::Timestamp getDate() const;
+		/// Returns the value of the Date header.
+
+	bool isMultipart() const;
+		/// Returns true iff the message is a multipart message.
+
+	void addPart(const std::string& name,
+		PartSource* pSource,
+		ContentDisposition disposition,
+		ContentTransferEncoding encoding);
+		/// Adds a part/attachment to the mail message.
+		///
+		/// The MailMessage takes ownership of the PartSource and deletes it
+		/// when it is no longer needed.
+		///
+		/// The MailMessage will be converted to a multipart message
+		/// if it is not already one.
+		///
+		/// The part name, and the filename specified in the part source
+		/// must not contain any non-ASCII characters.
+		/// To include non-ASCII characters in the part name or filename,
+		/// use RFC 2047 word encoding (see encodeWord()).
+
+	void addContent(PartSource* pSource,
+		ContentTransferEncoding encoding = ENCODING_QUOTED_PRINTABLE);
+		/// Adds a part to the mail message by calling
+		/// addPart("", pSource, CONTENT_INLINE, encoding);
+		///
+		/// The part name, and the filename specified in the part source
+		/// must not contain any non-ASCII characters.
+		/// To include non-ASCII characters in the part name or filename,
+		/// use RFC 2047 word encoding (see encodeWord()).
+
+	void addAttachment(const std::string& name,
+		PartSource* pSource,
+		ContentTransferEncoding encoding = ENCODING_BASE64);
+		/// Adds an attachment to the mail message by calling
+		/// addPart(name, pSource, CONTENT_ATTACHMENT, encoding);
+		///
+		/// The part name, and the filename specified in the part source
+		/// must not contain any non-ASCII characters.
+		/// To include non-ASCII characters in the part name or filename,
+		/// use RFC 2047 word encoding (see encodeWord()).
+
+	PartSource* createPartStore(const std::string& content,
+		const std::string& mediaType,
+		const std::string& filename = "");
+		/// Returns either default StringPartSource part store or,
+		/// if the part store factory was provided during construction,
+		/// the one created by PartStoreFactory.
+		/// Returned part store is allocated on the heap; it is caller's
+		/// responsibility to delete it after use. Typical use is handler
+		/// passing it back to MailMessage, which takes care of the cleanup.
+
+	const PartVec& parts() const;
+		/// Returns const reference to the vector containing part stores.
+
+	void read(std::istream& istr, PartHandler& handler);
+		/// Reads the MailMessage from the given input stream.
+		///
+		/// If the message has multiple parts, the parts
+		/// are reported to the PartHandler. If the message
+		/// is not a multi-part message, the content is stored
+		/// in a string available by calling getContent().
+
+	void read(std::istream& istr);
+		/// Reads the MailMessage from the given input stream.
+		///
+		/// The raw message (including all MIME parts) is stored
+		/// in a string and available by calling getContent().
+
+	void write(std::ostream& ostr) const;
+		/// Writes the mail message to the given output stream.
+
+	static std::string encodeWord(const std::string& text, const std::string& charset = "UTF-8");
+		/// If the given string contains non-ASCII characters,
+		/// encodes the given string using RFC 2047 "Q" word encoding.
+		///
+		/// The given text must already be encoded in the character set
+		/// given in charset (default is UTF-8).
+		///
+		/// Returns the encoded string, or the original string if it
+		/// consists only of ASCII characters.
+
+	static const std::string HEADER_SUBJECT;
+	static const std::string HEADER_FROM;
+	static const std::string HEADER_TO;
+	static const std::string HEADER_CC;
+	static const std::string HEADER_BCC;
+	static const std::string HEADER_DATE;
+	static const std::string HEADER_CONTENT_TYPE;
+	static const std::string HEADER_CONTENT_TRANSFER_ENCODING;
+	static const std::string HEADER_CONTENT_DISPOSITION;
+	static const std::string HEADER_CONTENT_ID;
+	static const std::string HEADER_MIME_VERSION;
+	static const std::string EMPTY_HEADER;
+	static const std::string TEXT_PLAIN;
+	static const std::string CTE_7BIT;
+	static const std::string CTE_8BIT;
+	static const std::string CTE_QUOTED_PRINTABLE;
+	static const std::string CTE_BASE64;
+
+protected:
+	void makeMultipart();
+	void writeHeader(const MessageHeader& header, std::ostream& ostr) const;
+	void writeMultipart(MessageHeader& header, std::ostream& ostr) const;
+	void writePart(MultipartWriter& writer, const Part& part) const;
+	void writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const;
+	void setRecipientHeaders(MessageHeader& headers) const;
+	void readHeader(std::istream& istr);
+	void readMultipart(std::istream& istr, PartHandler& handler);
+	void readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler);
+	void handlePart(std::istream& istr, const MessageHeader& header, PartHandler& handler);
+	static const std::string& contentTransferEncodingToString(ContentTransferEncoding encoding);
+	static int lineLength(const std::string& str);
+	static void appendRecipient(const MailRecipient& recipient, std::string& str);
+
+private:
+	MailMessage(const MailMessage&);
+	MailMessage& operator = (const MailMessage&);
+
+	Recipients              _recipients;
+	PartVec                 _parts;
+	std::string             _content;
+	ContentTransferEncoding _encoding;
+	mutable std::string     _boundary;
+	PartStoreFactory*       _pStoreFactory;
+};
+
+
+//
+// inlines
+//
+inline const MailMessage::Recipients& MailMessage::recipients() const
+{
+	return _recipients;
+}
+
+
+inline const std::string& MailMessage::getContent() const
+{
+	return _content;
+}
+
+
+inline const MailMessage::PartVec& MailMessage::parts() const
+{
+	return _parts;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MailMessage_INCLUDED
diff --git a/Poco/Net/MailRecipient.h b/Poco/Net/MailRecipient.h
new file mode 100644
index 0000000..7b14614
--- /dev/null
+++ b/Poco/Net/MailRecipient.h
@@ -0,0 +1,120 @@
+//
+// MailRecipient.h
+//
+// Library: Net
+// Package: Mail
+// Module:  MailRecipient
+//
+// Definition of the MailRecipient class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MailRecipient_INCLUDED
+#define Net_MailRecipient_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API MailRecipient
+	/// The recipient of an e-mail message.
+	///
+	/// A recipient has a type (primary recipient,
+	/// carbon-copy recipient, blind-carbon-copy
+	/// recipient), an e-mail address and an optional
+	/// real name.
+{
+public:
+	enum RecipientType
+	{
+		PRIMARY_RECIPIENT,
+		CC_RECIPIENT,
+		BCC_RECIPIENT
+	};
+
+	MailRecipient();
+		/// Creates an empty MailRecipient.
+		
+	MailRecipient(const MailRecipient& recipient);
+		/// Creates a MailRecipient by copying another one.
+		
+	MailRecipient(RecipientType type, const std::string& address);
+		/// Creates a MailRecipient of the given type.
+
+	MailRecipient(RecipientType type, const std::string& address, const std::string& realName);
+		/// Creates a MailRecipient of the given type.
+
+	~MailRecipient();
+		/// Destroys the MailRecipient.
+		
+	MailRecipient& operator = (const MailRecipient& recipient);
+		/// Assigns another recipient.
+		
+	void swap(MailRecipient& recipient);
+		/// Exchanges the content of two recipients.
+
+	RecipientType getType() const;
+		/// Returns the type of the recipient.
+		
+	void setType(RecipientType type);
+		/// Sets the type of the recipient.
+		
+	const std::string& getAddress() const;
+		/// Returns the address of the recipient.
+		
+	void setAddress(const std::string& address);
+		/// Sets the address of the recipient.
+		
+	const std::string& getRealName() const;
+		/// Returns the real name of the recipient.
+		
+	void setRealName(const std::string& realName);
+		/// Sets the real name of the recipient.
+
+private:
+	std::string   _address;
+	std::string   _realName;
+	RecipientType _type;
+};
+
+
+//
+// inlines
+//
+inline MailRecipient::RecipientType MailRecipient::getType() const
+{
+	return _type;
+}
+
+
+inline const std::string& MailRecipient::getAddress() const
+{
+	return _address;
+}
+
+
+inline const std::string& MailRecipient::getRealName() const
+{
+	return _realName;
+}
+
+
+inline void swap(MailRecipient& r1, MailRecipient& r2)
+{
+	r1.swap(r2);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MailRecipient_INCLUDED
diff --git a/Poco/Net/MailStream.h b/Poco/Net/MailStream.h
new file mode 100644
index 0000000..bc674b0
--- /dev/null
+++ b/Poco/Net/MailStream.h
@@ -0,0 +1,146 @@
+//
+// MailStream.h
+//
+// Library: Net
+// Package: Mail
+// Module:  MailStream
+//
+// Definition of the MailStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MailStream_INCLUDED
+#define Net_MailStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API MailStreamBuf: public Poco::UnbufferedStreamBuf
+	/// The sole purpose of this stream buffer is to replace 
+	/// a "\r\n.\r\n" character sequence with a "\r\n..\r\n" sequence for
+	/// output streams and vice-versa for input streams.
+	///
+	/// This is used when sending mail messages to SMTP servers, or
+	/// receiving mail messages from POP servers.
+	///
+	/// See RFC 2181 (Simple Mail Transfer Protocol) and RFC 1939
+	/// (Post Office Protocol - Version 3) for more information.
+{
+public:
+	MailStreamBuf(std::istream& istr);
+		/// Creates the MailStreamBuf and connects it
+		/// to the given input stream.
+
+	MailStreamBuf(std::ostream& ostr);
+		/// Creates the MailStreamBuf and connects it
+		/// to the given output stream.
+
+	~MailStreamBuf();
+		/// Destroys the MailStreamBuf.
+		
+	void close();
+		/// Writes the terminating period, followed by
+		/// CR-LF.
+		
+protected:
+	int readFromDevice();
+	int writeToDevice(char c);
+	int readOne();
+
+private:
+	enum State
+	{
+		ST_DATA,
+		ST_CR,
+		ST_CR_LF,
+		ST_CR_LF_DOT,
+		ST_CR_LF_DOT_DOT,
+		ST_CR_LF_DOT_CR,
+		ST_CR_LF_DOT_CR_LF
+	};
+	
+	std::istream* _pIstr;
+	std::ostream* _pOstr;
+	std::string   _buffer;
+	State         _state;
+};
+
+
+class Net_API MailIOS: public virtual std::ios
+	/// The base class for MailInputStream and MailOutputStream.
+	///
+	/// This class provides common methods and is also needed to ensure 
+	/// the correct initialization order of the stream buffer and base classes.
+{
+public:
+	MailIOS(std::istream& istr);
+		/// Creates the MailIOS and connects it
+		/// to the given input stream.
+
+	MailIOS(std::ostream& ostr);
+		/// Creates the MailIOS and connects it
+		/// to the given output stream.
+
+	~MailIOS();
+		/// Destroys the stream.
+
+	void close();
+		/// Writes the terminating period, followed by
+		/// CR-LF.
+
+	MailStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	MailStreamBuf _buf;
+};
+
+
+class Net_API MailInputStream: public MailIOS, public std::istream
+	/// This class is used for reading E-Mail messages from a
+	/// POP3 server. All occurrences of "\r\n..\r\n" are replaced with
+	/// "\r\n.\r\n". The first occurrence of "\r\n.\r\n" denotes the end
+	/// of the stream.
+{
+public:
+	MailInputStream(std::istream& istr);
+		/// Creates the MailInputStream and connects it
+		/// to the given input stream.
+
+	~MailInputStream();
+		/// Destroys the MailInputStream.
+};
+
+
+class Net_API MailOutputStream: public MailIOS, public std::ostream
+	/// This class is used for writing E-Mail messages to a
+	/// SMTP server. All occurrences of "\r\n.\r\n" are replaced with
+	/// "\r\n..\r\n".
+{
+public:
+	MailOutputStream(std::ostream& ostr);
+		/// Creates the MailOutputStream and connects it
+		/// to the given input stream.
+
+	~MailOutputStream();
+		/// Destroys the MailOutputStream.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MailStream_INCLUDED
diff --git a/Poco/Net/MediaType.h b/Poco/Net/MediaType.h
new file mode 100644
index 0000000..8440cb6
--- /dev/null
+++ b/Poco/Net/MediaType.h
@@ -0,0 +1,169 @@
+//
+// MediaType.h
+//
+// Library: Net
+// Package: Messages
+// Module:  MediaType
+//
+// Definition of the MediaType class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MediaType_INCLUDED
+#define Net_MediaType_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/NameValueCollection.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API MediaType
+	/// This class represents a MIME media type, consisting of
+	/// a top-level type, a subtype and an optional set of
+	/// parameters.
+	///
+	/// The implementation conforms with RFC 2045 and RFC 2046.
+{
+public:
+	MediaType(const std::string& mediaType);
+		/// Creates the MediaType from the given string, which
+		/// must have the format <type>/<subtype>{;<parameter>=<value>}.
+		
+	MediaType(const std::string& type, const std::string& subType);
+		/// Creates the MediaType, using the given type and subtype.
+
+	MediaType(const MediaType& mediaType);
+		/// Creates a MediaType from another one.
+
+	~MediaType();
+		/// Destroys the MediaType.
+
+	MediaType& operator = (const MediaType& mediaType);
+		/// Assigns another media type.
+		
+	MediaType& operator = (const std::string& mediaType);
+		/// Assigns another media type.
+		
+	void swap(MediaType& mediaType);
+		/// Swaps the MediaType with another one.
+		
+	void setType(const std::string& type);
+		/// Sets the top-level type.
+		
+	const std::string& getType() const;
+		/// Returns the top-level type.
+		
+	void setSubType(const std::string& subType);
+		/// Sets the sub type.
+		
+	const std::string& getSubType() const;
+		/// Returns the sub type.
+		
+	void setParameter(const std::string& name, const std::string& value);
+		/// Sets the parameter with the given name.
+		
+	const std::string& getParameter(const std::string& name) const;
+		/// Returns the parameter with the given name.
+		///
+		/// Throws a NotFoundException if the parameter does not exist.
+		
+	bool hasParameter(const std::string& name) const;
+		/// Returns true iff a parameter with the given name exists.
+		
+	void removeParameter(const std::string& name);
+		/// Removes the parameter with the given name.	
+		
+	const NameValueCollection& parameters() const;
+		/// Returns the parameters.
+		
+	std::string toString() const;
+		/// Returns the string representation of the media type
+		/// which is <type>/<subtype>{;<parameter>=<value>}
+		
+	bool matches(const MediaType& mediaType) const;
+		/// Returns true iff the type and subtype match
+		/// the type and subtype of the given media type.
+		/// Matching is case insensitive.
+		
+	bool matches(const std::string& type, const std::string& subType) const;
+		/// Returns true iff the type and subtype match
+		/// the given type and subtype.
+		/// Matching is case insensitive.
+
+	bool matches(const std::string& type) const;
+		/// Returns true iff the type matches the given type.
+		/// Matching is case insensitive.
+
+	bool matchesRange(const MediaType& mediaType) const;
+		/// Returns true if the type and subtype match
+		/// the type and subtype of the given media type.
+		/// If the MIME type is a range of types it matches
+		/// any media type within the range (e.g. "image/*" matches
+		/// any image media type, "*/*" matches anything).
+		/// Matching is case insensitive.
+
+	bool matchesRange(const std::string& type, const std::string& subType) const;
+		/// Returns true if the type and subtype match
+		/// the given type and subtype.
+		/// If the MIME type is a range of types it matches
+		/// any media type within the range (e.g. "image/*" matches
+		/// any image media type, "*/*" matches anything).
+		/// Matching is case insensitive.
+
+	bool matchesRange(const std::string& type) const;
+		/// Returns true if the type matches the given type or
+		/// the type is a range of types denoted by "*".
+		/// Matching is case insensitive.
+
+protected:
+	void parse(const std::string& mediaType);
+		
+private:
+	MediaType();
+	
+	std::string         _type;
+	std::string         _subType;
+	NameValueCollection _parameters;
+};
+
+
+//
+// inlines
+//
+inline const std::string& MediaType::getType() const
+{
+	return _type;
+}
+
+
+inline const std::string& MediaType::getSubType() const
+{
+	return _subType;
+}
+
+
+inline const NameValueCollection& MediaType::parameters() const
+{
+	return _parameters;
+}
+
+
+inline void swap(MediaType& m1, MediaType& m2)
+{
+	m1.swap(m2);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MediaType_INCLUDED
diff --git a/Poco/Net/MessageHeader.h b/Poco/Net/MessageHeader.h
new file mode 100644
index 0000000..f36ad51
--- /dev/null
+++ b/Poco/Net/MessageHeader.h
@@ -0,0 +1,169 @@
+//
+// MessageHeader.h
+//
+// Library: Net
+// Package: Messages
+// Module:  MessageHeader
+//
+// Definition of the MessageHeader class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MessageHeader_INCLUDED
+#define Net_MessageHeader_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/NameValueCollection.h"
+#include <ostream>
+#include <istream>
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API MessageHeader: public NameValueCollection
+	/// A collection of name-value pairs that are used in
+	/// various internet protocols like HTTP and SMTP.
+	///
+	/// The name is case-insensitive.
+	///
+	/// There can be more than one name-value pair with the 
+	/// same name.
+	///
+	/// MessageHeader supports writing and reading the
+	/// header data in RFC 2822 format.
+	///
+	/// The maximum number of fields can be restricted
+	/// by calling setFieldLimit(). This is useful to
+	/// defend against certain kinds of denial-of-service
+	/// attacks. The limit is only enforced when parsing
+	/// header fields from a stream, not when programmatically
+	/// adding them. The default limit is 100.
+{
+public:
+	MessageHeader();
+		/// Creates the MessageHeader.
+
+	MessageHeader(const MessageHeader& messageHeader);
+		/// Creates the MessageHeader by copying
+		/// another one.
+
+	virtual ~MessageHeader();
+		/// Destroys the MessageHeader.
+
+	MessageHeader& operator = (const MessageHeader& messageHeader);
+		/// Assigns the content of another MessageHeader.
+
+	virtual void write(std::ostream& ostr) const;
+		/// Writes the message header to the given output stream.
+		///
+		/// The format is one name-value pair per line, with
+		/// name and value separated by a colon and lines
+		/// delimited by a carriage return and a linefeed 
+		/// character. See RFC 2822 for details.
+		
+	virtual void read(std::istream& istr);
+		/// Reads the message header from the given input stream.
+		///
+		/// See write() for the expected format.
+		/// Also supported is folding of field content, according
+		/// to section 2.2.3 of RFC 2822.
+		///
+		/// Reading stops at the first empty line (a line only
+		/// containing \r\n or \n), as well as at the end of
+		/// the stream.
+		///
+		/// Some basic sanity checking of the input stream is
+		/// performed.
+		///
+		/// Throws a MessageException if the input stream is
+		/// malformed.
+		
+	int getFieldLimit() const;
+		/// Returns the maximum number of header fields
+		/// allowed.
+		///
+		/// See setFieldLimit() for more information.
+		
+	void setFieldLimit(int limit);
+		/// Sets the maximum number of header fields
+		/// allowed. This limit is used to defend certain
+		/// kinds of denial-of-service attacks.
+		/// Specify 0 for unlimited (not recommended).
+		///
+		/// The default limit is 100.
+	
+	bool hasToken(const std::string& fieldName, const std::string& token) const;
+		/// Returns true iff the field with the given fieldName contains
+		/// the given token. Tokens in a header field are expected to be
+		/// comma-separated and are case insensitive.
+
+	static void splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty = true);
+		/// Splits the given string into separate elements. Elements are expected
+		/// to be separated by commas.
+		///
+		/// For example, the string 
+		///   text/plain; q=0.5, text/html, text/x-dvi; q=0.8
+		/// is split into the elements
+		///   text/plain; q=0.5
+		///   text/html
+		///   text/x-dvi; q=0.8
+		///
+		/// Commas enclosed in double quotes do not split elements.
+		///
+		/// If ignoreEmpty is true, empty elements are not returned.
+		
+	static void splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters);
+		/// Splits the given string into a value and a collection of parameters.
+		/// Parameters are expected to be separated by semicolons.
+		///
+		/// Enclosing quotes of parameter values are removed.
+		///
+		/// For example, the string
+		///   multipart/mixed; boundary="MIME_boundary_01234567"
+		/// is split into the value
+		///   multipart/mixed
+		/// and the parameter
+		///   boundary -> MIME_boundary_01234567
+
+	static void splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters);
+		/// Splits the given string into a collection of parameters.
+		/// Parameters are expected to be separated by semicolons.
+		///
+		/// Enclosing quotes of parameter values are removed.
+
+	static void quote(const std::string& value, std::string& result, bool allowSpace = false);
+		/// Checks if the value must be quoted. If so, the value is
+		/// appended to result, enclosed in double-quotes.
+		/// Otherwise, the value is appended to result as-is.
+		
+	static void decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset = "UTF-8");
+	static std::string decodeWord(const std::string& text, const std::string& charset = "UTF-8");
+	        /// Decode RFC2047 string.
+
+		
+private:
+	enum Limits
+		/// Limits for basic sanity checks when reading a header
+	{
+		MAX_NAME_LENGTH  = 256,
+		MAX_VALUE_LENGTH = 8192,
+		DFL_FIELD_LIMIT  = 100
+	};
+	
+	int _fieldLimit;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MessageHeader_INCLUDED
diff --git a/Poco/Net/MulticastSocket.h b/Poco/Net/MulticastSocket.h
new file mode 100644
index 0000000..6ae4657
--- /dev/null
+++ b/Poco/Net/MulticastSocket.h
@@ -0,0 +1,135 @@
+//
+// MulticastSocket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  MulticastSocket
+//
+// Definition of the MulticastSocket class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MulticastSocket_INCLUDED
+#define Net_MulticastSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+#ifdef POCO_NET_HAS_INTERFACE
+
+
+#include "Poco/Net/DatagramSocket.h"
+#include "Poco/Net/NetworkInterface.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API MulticastSocket: public DatagramSocket
+	/// A MulticastSocket is a special DatagramSocket
+	/// that can be used to send packets to and receive
+	/// packets from multicast groups.
+{
+public:
+	MulticastSocket();
+		/// Creates an unconnected, unbound multicast socket.
+		///
+		/// Before the multicast socket can be used, bind(),
+		/// bind6() or connect() must be called.
+		///
+		/// Notice: The behavior of this constructor has changed
+		/// in release 2.0. Previously, the constructor created
+		/// an unbound IPv4 multicast socket.
+		
+	explicit MulticastSocket(SocketAddress::Family family);
+		/// Creates an unconnected datagram socket.
+		///
+		/// The socket will be created for the
+		/// given address family.
+
+	MulticastSocket(const SocketAddress& address, bool reuseAddress = false);
+		/// Creates a datagram socket and binds it
+		/// to the given address.
+		///
+		/// Depending on the address family, the socket
+		/// will be either an IPv4 or an IPv6 socket.
+
+	MulticastSocket(const Socket& socket);
+		/// Creates the DatagramSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a DatagramSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	~MulticastSocket();
+		/// Destroys the DatagramSocket.
+
+	MulticastSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.
+
+	void setInterface(const NetworkInterface& interfc);
+		/// Sets the interface used for sending multicast packets.
+		///
+		/// To select the default interface, specify an empty
+		/// interface.
+		///
+		/// This is done by setting the IP_MULTICAST_IF/IPV6_MULTICAST_IF
+		/// socket option.
+
+	NetworkInterface getInterface() const;
+		/// Returns the interface used for sending multicast packets.
+
+	void setLoopback(bool flag);
+		/// Enable or disable loopback for multicast packets.
+		///
+		/// Sets the value of the IP_MULTICAST_LOOP/IPV6_MULTICAST_LOOP
+		/// socket option.
+
+	bool getLoopback() const;
+		/// Returns true iff loopback for multicast packets is enabled,
+		/// false otherwise.
+
+	void setTimeToLive(unsigned value);
+		/// Specifies the TTL/hop limit for outgoing packets.
+		///
+		/// Sets the value of the IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS
+		/// socket option.
+
+	unsigned getTimeToLive() const;
+		/// Returns the TTL/hop limit for outgoing packets.
+		
+	void joinGroup(const IPAddress& groupAddress);
+		/// Joins the specified multicast group at the default interface.
+
+	void joinGroup(const IPAddress& groupAddress, const NetworkInterface& interfc);
+		/// Joins the specified multicast group at the given interface.
+
+	void leaveGroup(const IPAddress& groupAddress);
+		/// Leaves the specified multicast group at the default interface.
+
+	void leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interfc);
+		/// Leaves the specified multicast group at the given interface.
+
+private:
+	static NetworkInterface findFirstInterface(const IPAddress& groupAddress);
+		/// Returns first multicast-eligible network interface.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // POCO_NET_HAS_INTERFACE
+
+
+#endif // Net_MulticastSocket_INCLUDED
diff --git a/Poco/Net/MultipartReader.h b/Poco/Net/MultipartReader.h
new file mode 100644
index 0000000..5f972dc
--- /dev/null
+++ b/Poco/Net/MultipartReader.h
@@ -0,0 +1,160 @@
+//
+// MultipartReader.h
+//
+// Library: Net
+// Package: Messages
+// Module:  MultipartReader
+//
+// Definition of the MultipartReader class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MultipartReader_INCLUDED
+#define Net_MultipartReader_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/BufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class MessageHeader;
+
+
+class Net_API MultipartStreamBuf: public Poco::BufferedStreamBuf
+	/// This is the streambuf class used for reading from a multipart message stream.
+{
+public:
+	MultipartStreamBuf(std::istream& istr, const std::string& boundary);
+	~MultipartStreamBuf();
+	bool lastPart() const;
+	
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE = 1024
+	};
+
+	std::istream& _istr;
+	std::string   _boundary;
+	bool          _lastPart;
+};
+
+
+class Net_API MultipartIOS: public virtual std::ios
+	/// The base class for MultipartInputStream.
+{
+public:
+	MultipartIOS(std::istream& istr, const std::string& boundary);
+	~MultipartIOS();
+	MultipartStreamBuf* rdbuf();
+	bool lastPart() const;
+
+protected:
+	MultipartStreamBuf _buf;
+};
+
+
+class Net_API MultipartInputStream: public MultipartIOS, public std::istream
+	/// This class is for internal use by MultipartReader only.
+{
+public:
+	MultipartInputStream(std::istream& istr, const std::string& boundary);
+	~MultipartInputStream();
+};
+
+
+
+class Net_API MultipartReader
+	/// This class is used to split a MIME multipart
+	/// message into its single parts.
+	///
+	/// The format of multipart messages is described
+	/// in section 5.1 of RFC 2046.
+	///
+	/// To split a multipart message into its parts,
+	/// do the following:
+	///   - Create a MultipartReader object, passing it
+	///     an input stream and optionally a boundary string.
+	///   - while hasNextPart() returns true, call nextPart()
+	///     and read the part from stream().
+	///
+	/// Always ensure that you read all data from the part
+	/// stream, otherwise the MultipartReader will fail to
+	/// find the next part.
+{
+public:
+	explicit MultipartReader(std::istream& istr);
+		/// Creates the MultipartReader and attaches it to the
+		/// given input stream. 
+		///
+		/// The boundary string is determined from the input
+		/// stream. The message must not contain a preamble
+		/// preceding the first encapsulation boundary.
+
+	MultipartReader(std::istream& istr, const std::string& boundary);
+		/// Creates the MultipartReader and attaches it to the
+		/// given input stream. The given boundary string is
+		/// used to find message boundaries.
+
+	~MultipartReader();
+		/// Destroys the MultipartReader.
+
+	void nextPart(MessageHeader& messageHeader);
+		/// Moves to the next part in the message and stores the
+		/// part's header fields in messageHeader.
+		///
+		/// Throws an MultipartException if there are no more parts
+		/// available, or if no boundary line can be found in
+		/// the input stream.
+		
+	bool hasNextPart();
+		/// Returns true iff more parts are available.
+		///
+		/// Before the first call to nextPart(), returns
+		/// always true.
+		
+	std::istream& stream() const;
+		/// Returns a reference to the reader's stream that
+		/// can be used to read the current part.
+		///
+		/// The returned reference will be valid until
+		/// nextPart() is called or the MultipartReader
+		/// object is destroyed.
+
+	const std::string& boundary() const;
+		/// Returns the multipart boundary used by this reader.
+
+protected:
+	void findFirstBoundary();
+	void guessBoundary();
+	void parseHeader(MessageHeader& messageHeader);
+	bool readLine(std::string& line, std::string::size_type n);
+	
+private:
+	MultipartReader();
+	MultipartReader(const MultipartReader&);
+	MultipartReader& operator = (const MultipartReader&);
+
+	std::istream&         _istr;
+	std::string           _boundary;
+	MultipartInputStream* _pMPI;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MultipartReader_INCLUDED
diff --git a/Poco/Net/MultipartWriter.h b/Poco/Net/MultipartWriter.h
new file mode 100644
index 0000000..97b3fd2
--- /dev/null
+++ b/Poco/Net/MultipartWriter.h
@@ -0,0 +1,109 @@
+//
+// MultipartWriter.h
+//
+// Library: Net
+// Package: Messages
+// Module:  MultipartWriter
+//
+// Definition of the MultipartWriter class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_MultipartWriter_INCLUDED
+#define Net_MultipartWriter_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class MessageHeader;
+
+
+class Net_API MultipartWriter
+	/// This class is used to write MIME multipart
+	/// messages to an output stream.
+	///
+	/// The format of multipart messages is described
+	/// in section 5.1 of RFC 2046.
+	///
+	/// To create a multipart message, first create
+	/// a MultipartWriter object.
+	/// Then, for each part, call nextPart() and
+	/// write the content to the output stream.
+	/// Repeat for all parts. 
+	/// After the last part has been written,
+	/// call close() to finish the multipart message.
+{
+public:
+	explicit MultipartWriter(std::ostream& ostr);
+		/// Creates the MultipartWriter, using the
+		/// given output stream.
+		///
+		/// Creates a random boundary string.
+
+	MultipartWriter(std::ostream& ostr, const std::string& boundary);
+		/// Creates the MultipartWriter, using the
+		/// given output stream and boundary string.
+
+	~MultipartWriter();
+		/// Destroys the MultipartWriter.
+		
+	void nextPart(const MessageHeader& header);
+		/// Opens a new message part and writes
+		/// the message boundary string, followed
+		/// by the message header to the stream.
+		
+	void close();
+		/// Closes the multipart message and writes
+		/// the terminating boundary string.
+		///
+		/// Does not close the underlying stream.
+
+	std::ostream& stream();
+		/// Returns the writer's stream.
+
+	const std::string& boundary() const;
+		/// Returns the multipart boundary used by this writer.
+
+	static std::string createBoundary();
+		/// Creates a random boundary string.
+		///
+		/// The string always has the form
+		/// MIME_boundary_XXXXXXXXXXXX, where
+		/// XXXXXXXXXXXX is a random hexadecimal
+		/// number.
+		
+private:
+	MultipartWriter();
+	MultipartWriter(const MultipartWriter&);
+	MultipartWriter& operator = (const MultipartWriter&);
+
+	std::ostream& _ostr;
+	std::string   _boundary;
+	bool          _firstPart;
+};
+
+
+//
+// inlines
+//
+inline std::ostream& MultipartWriter::stream()
+{
+	return _ostr;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_MultipartWriter_INCLUDED
diff --git a/Poco/Net/NTPClient.h b/Poco/Net/NTPClient.h
new file mode 100644
index 0000000..044a486
--- /dev/null
+++ b/Poco/Net/NTPClient.h
@@ -0,0 +1,64 @@
+//
+// NTPClient.h
+//
+// Library: Net
+// Package: NTP
+// Module:  NTPClient
+//
+// Definition of the NTPClient class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NTPClient_INCLUDED
+#define Net_NTPClient_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/NTPEventArgs.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/BasicEvent.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API NTPClient
+	/// This class provides NTP (Network Time Protocol) client functionality.
+{
+public:
+	mutable Poco::BasicEvent<NTPEventArgs> response;
+
+	explicit NTPClient(SocketAddress::Family family, int timeout = 3000000);
+		/// Creates an NTP client.
+
+	~NTPClient();
+		/// Destroys the NTP client.
+
+	int request(SocketAddress& address) const;
+		/// Request the time from the server at address.
+		/// Notifications are posted for events.
+		/// 
+		/// Returns the number of valid replies.
+
+	int request(const std::string& address) const;
+		/// Request the time from the server at address.
+		/// Notifications are posted for events.
+		/// 
+		/// Returns the number of valid replies.
+
+private:
+	mutable SocketAddress::Family _family;
+	int _timeout;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_NTPClient_INCLUDED
diff --git a/Poco/Net/NTPEventArgs.h b/Poco/Net/NTPEventArgs.h
new file mode 100644
index 0000000..89c1275
--- /dev/null
+++ b/Poco/Net/NTPEventArgs.h
@@ -0,0 +1,84 @@
+//
+// NTPEventArgs.h
+//
+// Library: Net
+// Package: NTP
+// Module:  NTPEventArgs
+//
+// Definition of NTPEventArgs.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NTPEventArgs_INCLUDED
+#define Net_NTPEventArgs_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/Net/NTPPacket.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API NTPEventArgs
+	/// The purpose of the NTPEventArgs class is to be used as template parameter
+	/// to instantiate event members in NTPClient class.
+	/// When clients register for an event notification, the reference to the class is 
+	///	passed to the handler function to provide information about the event.
+{
+public:
+	NTPEventArgs(const SocketAddress& address);
+		/// Creates NTPEventArgs.
+
+	virtual ~NTPEventArgs();
+		/// Destroys NTPEventArgs.
+
+	std::string hostName() const;
+		/// Tries to resolve the target IP address into host name.
+		/// If unsuccessful, all exceptions are silently ignored and 
+		///	the IP address is returned.
+
+	std::string hostAddress() const;
+		/// Returns the target IP address.
+
+	const NTPPacket &packet();
+		/// Returns the NTP packet.
+
+private:
+	NTPEventArgs();
+
+	void setPacket(NTPPacket &packet);
+
+	SocketAddress _address;
+	NTPPacket _packet;
+
+	friend class NTPClient;
+};
+
+
+//
+// inlines
+//
+inline const NTPPacket &NTPEventArgs::packet()
+{
+	return _packet;
+}
+
+
+inline void NTPEventArgs::setPacket(NTPPacket &packet)
+{
+	_packet = packet;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif
diff --git a/Poco/Net/NTPPacket.h b/Poco/Net/NTPPacket.h
new file mode 100644
index 0000000..4dae347
--- /dev/null
+++ b/Poco/Net/NTPPacket.h
@@ -0,0 +1,207 @@
+//
+// NTPPacket.h
+//
+// Library: Net
+// Package: NTP
+// Module:  NTPPacket
+//
+// Definition of the NTPPacket class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NTPPacket_INCLUDED
+#define Net_NTPPacket_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Net/Net.h"
+#include "Poco/Timestamp.h"
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API NTPPacket
+	/// This class is the NTP packet abstraction. 
+{
+public:
+	NTPPacket();
+		/// Creates an NTPPacket.
+
+	NTPPacket(Poco::UInt8 *packet);
+		/// Creates an NTPPacket.
+		///
+		/// Assumed to have at least 48 bytes.
+
+	~NTPPacket();
+		/// Destroys the NTPPacket.
+
+	void packet(Poco::UInt8 *packet) const;
+		/// Returns the NTP packet.
+		///
+		/// Assumed to have at least 48 bytes.
+
+	void setPacket(Poco::UInt8 *packet);
+		/// Returns the NTP packet.
+		///
+		/// Assumed to have exactly 48 bytes.
+
+	Poco::Int8 leapIndicator() const;
+		/// Returns the leap indicator.
+
+	Poco::Int8 version() const;
+		/// Returns the version.
+
+	Poco::Int8 mode() const;
+		/// Returns the mode.
+
+	Poco::Int8 stratum() const;
+		/// Returns the stratum.
+
+	Poco::Int8 pool() const;
+		/// Returns the pool.
+
+	Poco::Int8 precision() const;
+		/// Returns the precision
+
+	Poco::Int32 rootDelay() const;
+		/// Returns the root delay
+
+	Poco::Int32 rootDispersion() const;
+		/// Returns the root dispersion
+
+	Poco::Int32 referenceId() const;
+		/// Returns the reference id
+
+	Poco::Int64 referenceTimestamp() const;
+		/// Returns the reference timestamp
+
+	Poco::Int64 originateTimestamp() const;
+		/// Returns the originate timestamp
+
+	Poco::Int64 receiveTimestamp() const;
+		/// Returns the receive timestamp
+
+	Poco::Int64 transmitTimestamp() const;
+		/// Returns the transmit timestamp
+
+	Poco::Timestamp referenceTime() const;
+		/// Returns the reference time
+
+	Poco::Timestamp originateTime() const;
+		/// Returns the originate time
+
+	Poco::Timestamp receiveTime() const;
+		/// Returns the receive time
+
+	Poco::Timestamp transmitTime() const;
+		/// Returns the transmit time
+private:
+	Poco::Timestamp convertTime(Poco::Int64 tm) const;
+
+	Poco::Int8 _leapIndicator;
+	Poco::Int8 _version;
+	Poco::Int8 _mode;
+	Poco::Int8 _stratum;
+	Poco::Int8 _pool;
+	Poco::Int8 _precision;
+	Poco::Int32 _rootDelay;
+	Poco::Int32 _rootDispersion;
+	Poco::Int32 _referenceId;
+	Poco::Int64 _referenceTimestamp;
+	Poco::Int64 _originateTimestamp;
+	Poco::Int64 _receiveTimestamp;
+	Poco::Int64 _transmitTimestamp;
+};
+
+
+//
+// inlines
+//
+inline Poco::Int8 NTPPacket::leapIndicator() const
+{
+	return _leapIndicator;
+}
+
+
+inline Poco::Int8 NTPPacket::version() const
+{
+	return _version;
+}
+
+
+inline Poco::Int8 NTPPacket::mode() const
+{
+	return _mode;
+}
+
+
+inline Poco::Int8 NTPPacket::stratum() const
+{
+	return _stratum;
+}
+
+
+inline Poco::Int8 NTPPacket::pool() const
+{
+	return _pool;
+}
+
+
+inline Poco::Int8 NTPPacket::precision() const
+{
+	return _precision;
+}
+
+
+inline Poco::Int32 NTPPacket::rootDelay() const
+{
+	return _rootDelay;
+}
+
+
+inline Poco::Int32 NTPPacket::rootDispersion() const
+{
+	return _rootDispersion;
+}
+
+
+inline Poco::Int32 NTPPacket::referenceId() const
+{
+	return _referenceId;
+}
+
+
+inline Poco::Int64 NTPPacket::referenceTimestamp() const
+{
+	return _referenceTimestamp;
+}
+
+
+inline Poco::Int64 NTPPacket::originateTimestamp() const
+{
+	return _originateTimestamp;
+}
+
+
+inline Poco::Int64 NTPPacket::receiveTimestamp() const
+{
+	return _receiveTimestamp;
+}
+
+
+inline Poco::Int64 NTPPacket::transmitTimestamp() const
+{
+	return _transmitTimestamp;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_NTPPacket_INCLUDED
diff --git a/Poco/Net/NameValueCollection.h b/Poco/Net/NameValueCollection.h
new file mode 100644
index 0000000..e2edce3
--- /dev/null
+++ b/Poco/Net/NameValueCollection.h
@@ -0,0 +1,126 @@
+//
+// NameValueCollection.h
+//
+// Library: Net
+// Package: Messages
+// Module:  NameValueCollection
+//
+// Definition of the NameValueCollection class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NameValueCollection_INCLUDED
+#define Net_NameValueCollection_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/String.h"
+#include "Poco/ListMap.h"
+#include <cstddef>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API NameValueCollection
+	/// A collection of name-value pairs that are used in
+	/// various internet protocols like HTTP and SMTP.
+	///
+	/// The name is case-insensitive.
+	///
+	/// There can be more than one name-value pair with the 
+	/// same name.
+{
+public:
+	typedef Poco::ListMap<std::string, std::string> HeaderMap;
+	typedef HeaderMap::Iterator Iterator;
+	typedef HeaderMap::ConstIterator ConstIterator;
+	
+	NameValueCollection();
+		/// Creates an empty NameValueCollection.
+
+	NameValueCollection(const NameValueCollection& nvc);
+		/// Creates a NameValueCollection by copying another one.
+
+	virtual ~NameValueCollection();
+		/// Destroys the NameValueCollection.
+
+	NameValueCollection& operator = (const NameValueCollection& nvc);
+		/// Assigns the name-value pairs of another NameValueCollection to this one.
+		
+	void swap(NameValueCollection& nvc);
+		/// Swaps the NameValueCollection with another one.
+		
+	const std::string& operator [] (const std::string& name) const;
+		/// Returns the value of the (first) name-value pair with the given name.
+		///
+		/// Throws a NotFoundException if the name-value pair does not exist.
+		
+	void set(const std::string& name, const std::string& value);	
+		/// Sets the value of the (first) name-value pair with the given name.
+		
+	void add(const std::string& name, const std::string& value);
+		/// Adds a new name-value pair with the given name and value.
+		
+	const std::string& get(const std::string& name) const;
+		/// Returns the value of the first name-value pair with the given name.
+		///
+		/// Throws a NotFoundException if the name-value pair does not exist.
+
+	const std::string& get(const std::string& name, const std::string& defaultValue) const;
+		/// Returns the value of the first name-value pair with the given name.
+		/// If no value with the given name has been found, the defaultValue is returned.
+
+	bool has(const std::string& name) const;
+		/// Returns true if there is at least one name-value pair
+		/// with the given name.
+
+	ConstIterator find(const std::string& name) const;
+		/// Returns an iterator pointing to the first name-value pair
+		/// with the given name.
+		
+	ConstIterator begin() const;
+		/// Returns an iterator pointing to the begin of
+		/// the name-value pair collection.
+		
+	ConstIterator end() const;
+		/// Returns an iterator pointing to the end of 
+		/// the name-value pair collection.
+		
+	bool empty() const;
+		/// Returns true iff the header does not have any content.
+
+	std::size_t size() const;
+		/// Returns the number of name-value pairs in the
+		/// collection.
+
+	void erase(const std::string& name);
+		/// Removes all name-value pairs with the given name.
+
+	void clear();
+		/// Removes all name-value pairs and their values.
+
+private:
+	HeaderMap _map;
+};
+
+
+//
+// inlines
+//
+inline void swap(NameValueCollection& nvc1, NameValueCollection& nvc2)
+{
+	nvc1.swap(nvc2);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_NameValueCollection_INCLUDED
diff --git a/Poco/Net/Net.h b/Poco/Net/Net.h
new file mode 100644
index 0000000..4ec0203
--- /dev/null
+++ b/Poco/Net/Net.h
@@ -0,0 +1,122 @@
+//
+// Net.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  Net
+//
+// Basic definitions for the Poco Net library.
+// This file must be the first file included by every other Net
+// header file.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_Net_INCLUDED
+#define Net_Net_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Net_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Net_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(Net_EXPORTS)
+		#define Net_API __declspec(dllexport)
+	#else
+		#define Net_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Net_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Net_API __attribute__ ((visibility ("default")))
+	#else
+		#define Net_API
+	#endif
+#endif
+
+
+//
+// Automatically link Net library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Net_EXPORTS)
+		#pragma comment(lib, "PocoNet" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+// Default to enabled IPv6 support if not explicitly disabled
+#if !defined(POCO_NET_NO_IPv6) && !defined (POCO_HAVE_IPv6)
+	#define POCO_HAVE_IPv6
+#elif defined(POCO_NET_NO_IPv6) && defined (POCO_HAVE_IPv6)
+	#undef POCO_HAVE_IPv6
+#endif // POCO_NET_NO_IPv6, POCO_HAVE_IPv6
+
+
+namespace Poco {
+namespace Net {
+
+
+void Net_API initializeNetwork();
+	/// Initialize the network subsystem.
+	/// (Windows only, no-op elsewhere)
+
+
+void Net_API uninitializeNetwork();
+	/// Uninitialize the network subsystem.
+	/// (Windows only, no-op elsewhere)
+
+
+}} // namespace Poco::Net
+
+
+//
+// Automate network initialization (only relevant on Windows).
+//
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_NO_AUTOMATIC_LIB_INIT) && !defined(__GNUC__)
+
+extern "C" const struct Net_API NetworkInitializer pocoNetworkInitializer;
+
+#if defined(Net_EXPORTS)
+	#if defined(_WIN64) || defined(_WIN32_WCE)
+		#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) || defined(_WIN32_WCE)
+		#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
+
+
+//
+// Define POCO_NET_HAS_INTERFACE for platforms that have network interface detection implemented.
+//
+#if defined(POCO_OS_FAMILY_WINDOWS) || (POCO_OS == POCO_OS_LINUX) || (POCO_OS == POCO_OS_ANDROID) || defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_QNX)
+	#define POCO_NET_HAS_INTERFACE
+#endif
+
+
+#endif // Net_Net_INCLUDED
diff --git a/Poco/Net/NetException.h b/Poco/Net/NetException.h
new file mode 100644
index 0000000..92bb3ed
--- /dev/null
+++ b/Poco/Net/NetException.h
@@ -0,0 +1,60 @@
+//
+// NetException.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  NetException
+//
+// Definition of the NetException class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NetException_INCLUDED
+#define Net_NetException_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+POCO_DECLARE_EXCEPTION(Net_API, NetException, Poco::IOException)
+POCO_DECLARE_EXCEPTION(Net_API, InvalidAddressException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, InvalidSocketException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, ServiceNotFoundException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, ConnectionAbortedException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, ConnectionResetException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, ConnectionRefusedException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, DNSException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, HostNotFoundException, DNSException)
+POCO_DECLARE_EXCEPTION(Net_API, NoAddressFoundException, DNSException)
+POCO_DECLARE_EXCEPTION(Net_API, InterfaceNotFoundException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, NoMessageException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, MessageException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, MultipartException, MessageException)
+POCO_DECLARE_EXCEPTION(Net_API, HTTPException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, NotAuthenticatedException, HTTPException)
+POCO_DECLARE_EXCEPTION(Net_API, UnsupportedRedirectException, HTTPException)
+POCO_DECLARE_EXCEPTION(Net_API, FTPException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, SMTPException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, POP3Exception, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, ICMPException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, NTPException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, HTMLFormException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, WebSocketException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, UnsupportedFamilyException, NetException)
+POCO_DECLARE_EXCEPTION(Net_API, AddressFamilyMismatchException, NetException)
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_NetException_INCLUDED
diff --git a/Poco/Net/NetSSL.h b/Poco/Net/NetSSL.h
new file mode 100644
index 0000000..ae793fd
--- /dev/null
+++ b/Poco/Net/NetSSL.h
@@ -0,0 +1,94 @@
+//
+// NetSSL.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  OpenSSL
+//
+// Basic definitions for the Poco OpenSSL library.
+// This file must be the first file included by every other OpenSSL
+// header file.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_NetSSL_INCLUDED
+#define NetSSL_NetSSL_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Crypto/Crypto.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the NetSSL_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// NetSSL_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(POCO_DLL)
+	#if defined(NetSSL_EXPORTS)
+		#define NetSSL_API __declspec(dllexport)
+	#else
+		#define NetSSL_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(NetSSL_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define NetSSL_API __attribute__ ((visibility ("default")))
+	#else
+		#define NetSSL_API
+	#endif
+#endif
+
+
+//
+// Automatically link NetSSL and OpenSSL libraries.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS)
+		#if !defined(NetSSL_EXPORTS)
+			#pragma comment(lib, "PocoNetSSL" POCO_LIB_SUFFIX)
+		#endif
+	#endif // POCO_NO_AUTOMATIC_LIBS
+#endif
+
+
+namespace Poco {
+namespace Net {
+
+
+void NetSSL_API initializeSSL();
+	/// Initialize the NetSSL library, as well as the underlying OpenSSL
+	/// libraries, by calling Poco::Crypto::OpenSSLInitializer::initialize().
+	///
+	/// Should be called before using any class from the NetSSL library.
+	/// The NetSSL will be initialized automatically, through 
+	/// Poco::Crypto::OpenSSLInitializer instances or similar mechanisms
+	/// when creating Context or SSLManager instances.
+	/// However, it is recommended to call initializeSSL()
+	/// in any case at application startup.
+	///
+	/// Can be called multiple times; however, for every call to
+	/// initializeSSL(), a matching call to uninitializeSSL()
+	/// must be performed.
+	
+
+void NetSSL_API uninitializeSSL();
+	/// Uninitializes the NetSSL library by calling 
+	/// Poco::Crypto::OpenSSLInitializer::uninitialize() and
+	/// shutting down the SSLManager.
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_NetSSL_INCLUDED
diff --git a/Poco/Net/NetworkInterface.h b/Poco/Net/NetworkInterface.h
new file mode 100644
index 0000000..17e10fd
--- /dev/null
+++ b/Poco/Net/NetworkInterface.h
@@ -0,0 +1,352 @@
+//
+// NetworkInterface.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  NetworkInterface
+//
+// Definition of the NetworkInterface class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NetworkInterface_INCLUDED
+#define Net_NetworkInterface_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+#ifdef POCO_NET_HAS_INTERFACE
+
+
+#include "Poco/Net/IPAddress.h"
+#include "Poco/Mutex.h"
+#include "Poco/Tuple.h"
+#include <map>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetworkInterfaceImpl;
+
+
+class Net_API NetworkInterface
+	/// This class represents a network interface.
+	/// 
+	/// NetworkInterface is used with MulticastSocket to specify
+	/// multicast interfaces for sending and receiving multicast
+	/// messages.
+	/// 
+	/// The class also provides static member functions for
+	/// enumerating or searching network interfaces and their
+	/// respective configuration values.
+	///
+	/// On Windows, detection capabilities vary depending on the
+	/// OS version/service pack. Although the best effort is made
+	/// not to attempt access to non-existent features through a 
+	/// combination of compile/runtime checks, when running binaries
+	/// compiled on a newer version of the OS on an older one
+	/// problems may occur; if possible, it is best to run
+	/// binaries on the OS version where they were compiled.
+	/// This particularly applies to OS versions older than Vista
+	/// and XP.
+{
+public:
+	typedef std::vector<NetworkInterface>                List;
+	typedef List                                         NetworkInterfaceList;//@deprecated
+	typedef std::map<unsigned, NetworkInterface>         Map;
+	typedef Poco::Tuple<IPAddress, IPAddress, IPAddress> AddressTuple;
+	typedef std::vector<AddressTuple>                    AddressList;
+	typedef AddressList::iterator                        AddressIterator;
+	typedef AddressList::const_iterator                  ConstAddressIterator;
+	typedef std::vector<unsigned char>                   MACAddress;
+
+	enum AddressType
+	{
+		IP_ADDRESS,
+		SUBNET_MASK,
+		BROADCAST_ADDRESS
+	};
+
+	enum Type
+	{
+		NI_TYPE_ETHERNET_CSMACD,
+		NI_TYPE_ISO88025_TOKENRING,
+		NI_TYPE_FRAMERELAY,
+		NI_TYPE_PPP,
+		NI_TYPE_SOFTWARE_LOOPBACK,
+		NI_TYPE_ATM,
+		NI_TYPE_IEEE80211,
+		NI_TYPE_TUNNEL,
+		NI_TYPE_IEEE1394,
+		NI_TYPE_OTHER
+	};
+
+	enum IPVersion
+	{
+		IPv4_ONLY,    /// Return interfaces with IPv4 address only
+		IPv6_ONLY,    /// Return interfaces with IPv6 address only
+		IPv4_OR_IPv6  /// Return interfaces with IPv4 or IPv6 address
+	};
+
+	static const unsigned NO_INDEX = ~0;
+#if defined(POCO_OS_FAMILY_WINDOWS)
+	static const char MAC_SEPARATOR = '-';
+#else
+	static const char MAC_SEPARATOR = ':';
+#endif
+
+	NetworkInterface(unsigned index = NO_INDEX);
+		/// Creates a NetworkInterface representing the
+		/// default interface.
+		///
+		/// The name is empty, the IP address is the wildcard
+		/// address and the index is max value of unsigned integer.
+	
+	NetworkInterface(const NetworkInterface& interfc);
+		/// Creates the NetworkInterface by copying another one.
+
+	~NetworkInterface();
+		/// Destroys the NetworkInterface.
+
+	NetworkInterface& operator = (const NetworkInterface& interfc);
+		/// Assigns another NetworkInterface.
+	
+	bool operator < (const NetworkInterface& other) const;
+		/// Operator less-than.
+	
+	bool operator == (const NetworkInterface& other) const;
+		/// Operator equal. Compares interface indices.
+
+	void swap(NetworkInterface& other);
+		/// Swaps the NetworkInterface with another one.	
+		
+	unsigned index() const;
+		/// Returns the interface OS index.
+		
+	const std::string& name() const;
+		/// Returns the interface name.
+		
+	const std::string& displayName() const;
+		/// Returns the interface display name.
+		///
+		/// On Windows platforms, this is currently the network adapter
+		/// name. This may change to the "friendly name" of the network
+		/// connection in a future version, however. 
+		///
+		/// On other platforms this is the same as name().
+
+	const std::string& adapterName() const;
+		/// Returns the interface adapter name.
+		///
+		/// On Windows platforms, this is the network adapter LUID.
+		/// The adapter name is used by some Windows Net APIs like DHCP. 
+		///
+		/// On other platforms this is the same as name().
+
+	const IPAddress& firstAddress(IPAddress::Family family) const;
+		/// Returns the first IP address bound to the interface.
+		/// Throws NotFoundException if the address family is not
+		/// configured on the interface.
+
+	void firstAddress(IPAddress& addr, IPAddress::Family family = IPAddress::IPv4) const;
+		/// Returns the first IP address bound to the interface.
+		/// If the address family is not configured on the interface,
+		/// the address returned in addr will be unspecified (wildcard).
+
+	const IPAddress& address(unsigned index = 0) const;
+		/// Returns the IP address bound to the interface at index position.
+
+	void addAddress(const IPAddress& address);
+		/// Adds address to the interface.
+
+	void addAddress(const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress);
+		/// Adds address to the interface.
+
+	const AddressList& addressList() const;
+		/// Returns the list of IP addresses bound to the interface.
+
+	const IPAddress& subnetMask(unsigned index = 0) const;
+		/// Returns the subnet mask for this network interface.
+
+	const IPAddress& broadcastAddress(unsigned index = 0) const;
+		/// Returns the broadcast address for this network interface.
+
+	const IPAddress& destAddress(unsigned index = 0) const;
+		/// Returns the IPv4 point-to-point destination address for this network interface.
+
+	const MACAddress& macAddress() const;
+		/// Returns MAC (Media Access Control) address for the interface.
+
+	unsigned mtu() const;
+		/// Returns the MTU for this interface.
+
+	NetworkInterface::Type type() const;
+		/// returns the MIB IfType of the interface.
+
+	bool supportsIP() const;
+		/// Returns true if the interface supports IP.
+
+	bool supportsIPv4() const;
+		/// Returns true if the interface supports IPv4.
+
+	bool supportsIPv6() const;
+		/// Returns true if the interface supports IPv6.	
+
+	bool supportsBroadcast() const;
+		/// Returns true if the interface supports broadcast.
+
+	bool supportsMulticast() const;
+		/// Returns true if the interface supports multicast.
+
+	bool isLoopback() const;
+		/// Returns true if the interface is loopback.
+
+	bool isPointToPoint() const;
+		/// Returns true if the interface is point-to-point.
+
+	bool isRunning() const;
+		/// Returns true if the interface is running.
+
+	bool isUp() const;
+		/// Returns true if the interface is up.
+
+	static NetworkInterface forName(const std::string& name, bool requireIPv6 = false);
+		/// Returns the NetworkInterface for the given name.
+		/// 
+		/// If requireIPv6 is false, an IPv4 interface is returned.
+		/// Otherwise, an IPv6 interface is returned.
+		///
+		/// Throws an InterfaceNotFoundException if an interface
+		/// with the give name does not exist.
+
+	static NetworkInterface forName(const std::string& name, IPVersion ipVersion);
+		/// Returns the NetworkInterface for the given name.
+		/// 
+		/// The ipVersion argument can be used to specify whether
+		/// an IPv4 (IPv4_ONLY) or IPv6 (IPv6_ONLY) interface is required, 
+		/// or whether the caller does not care (IPv4_OR_IPv6).
+		///
+		/// Throws an InterfaceNotFoundException if an interface
+		/// with the give name does not exist.
+		
+	static NetworkInterface forAddress(const IPAddress& address);
+		/// Returns the NetworkInterface for the given IP address.
+		///
+		/// Throws an InterfaceNotFoundException if an interface
+		/// with the give address does not exist.
+
+	static NetworkInterface forIndex(unsigned index);
+		/// Returns the NetworkInterface for the given interface index.
+		///
+		/// Throws an InterfaceNotFoundException if an interface
+		/// with the given index does not exist.
+
+	static List list(bool ipOnly = true, bool upOnly = true);
+		/// Returns a list with all network interfaces
+		/// on the system.
+		///
+		/// If ipOnly is true, only interfaces supporting IP
+		/// are returned. Otherwise, all system network interfaces
+		/// are returned.
+		///
+		/// If upOnly is true, only interfaces being up are returned.
+		/// Otherwise, both interfaces being up and down are returned.
+		///
+		/// If there are multiple addresses bound to one interface,
+		/// multiple NetworkInterface entries are listed for
+		/// the same interface.
+
+	static Map map(bool ipOnly = true, bool upOnly = true);
+		/// Returns a map containing system network interfaces
+		/// Map is keyed by interface system indices.
+		///
+		/// If ipOnly is true, only interfaces supporting IP
+		/// are returned. Otherwise, all system network interfaces
+		/// are returned.
+		///
+		/// If upOnly is true, only interfaces being up are returned.
+		/// Otherwise, both interfaces being up and down are returned.
+		///
+		/// If there are multiple addresses bound to one interface,
+		/// they are contained within the NetworkInterface (second) 
+		/// member of the pair.
+
+protected:
+	NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, MACAddress* pMACAddress = 0);
+		/// Creates the NetworkInterface.
+
+	NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, MACAddress* pMACAddress = 0);
+		/// Creates the NetworkInterface.
+
+	NetworkInterface(const std::string& name, const IPAddress& address, unsigned index, MACAddress* pMACAddress = 0);
+		/// Creates the NetworkInterface.
+
+	NetworkInterface(const std::string& name,
+		const std::string& displayName,
+		const std::string& adapterName,
+		const IPAddress& address,
+		const IPAddress& subnetMask,
+		const IPAddress& broadcastAddress,
+		unsigned index,
+		MACAddress* pMACAddress = 0);
+		/// Creates the NetworkInterface.
+
+	NetworkInterface(const std::string& name,
+		const IPAddress& address,
+		const IPAddress& subnetMask,
+		const IPAddress& broadcastAddress,
+		unsigned index,
+		MACAddress* pMACAddress = 0);
+		/// Creates the NetworkInterface.
+
+	IPAddress interfaceNameToAddress(const std::string& interfaceName) const;
+		/// Determines the IPAddress bound to the interface with the given name.
+
+	unsigned interfaceNameToIndex(const std::string& interfaceName) const;
+		/// Determines the interface index of the interface with the given name.
+
+	NetworkInterfaceImpl& impl() { return *_pImpl; };
+
+private:
+	NetworkInterfaceImpl* _pImpl;
+
+	static Poco::FastMutex _mutex;
+};
+
+
+///
+/// inlines
+///
+
+
+inline bool NetworkInterface::operator < (const NetworkInterface& other) const
+{
+	return this->index() < other.index();
+}
+
+
+inline bool NetworkInterface::operator == (const NetworkInterface& other) const
+{
+	return this->index() == other.index();
+}
+
+
+} } // namespace Poco::Net
+
+
+Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::NetworkInterface::MACAddress& addr);
+
+
+#endif // POCO_NET_HAS_INTERFACE
+
+
+#endif // Net_NetworkInterface_INCLUDED
diff --git a/Poco/Net/NullPartHandler.h b/Poco/Net/NullPartHandler.h
new file mode 100644
index 0000000..21c45c6
--- /dev/null
+++ b/Poco/Net/NullPartHandler.h
@@ -0,0 +1,47 @@
+//
+// NullPartHandler.h
+//
+// Library: Net
+// Package: Messages
+// Module:  NullPartHandler
+//
+// Definition of the NullPartHandler class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_NullPartHandler_INCLUDED
+#define Net_NullPartHandler_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/PartHandler.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API NullPartHandler: public PartHandler
+	/// A very special PartHandler that simply discards all data.
+{
+public:
+	NullPartHandler();
+		/// Creates the NullPartHandler.
+	
+	~NullPartHandler();
+		/// Destroys the NullPartHandler.
+	
+	void handlePart(const MessageHeader& header, std::istream& stream);
+		/// Reads and discards all data from the stream.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_NullPartHandler_INCLUDED
diff --git a/Poco/Net/OAuth10Credentials.h b/Poco/Net/OAuth10Credentials.h
new file mode 100644
index 0000000..1402d40
--- /dev/null
+++ b/Poco/Net/OAuth10Credentials.h
@@ -0,0 +1,274 @@
+//
+// OAuth10Credentials.h
+//
+// Library: Net
+// Package: OAuth
+// Module:	OAuth10Credentials
+//
+// Definition of the OAuth10Credentials class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_OAuth10Credentials_INCLUDED
+#define Net_OAuth10Credentials_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/URI.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+class HTMLForm;
+
+
+class Net_API OAuth10Credentials
+	/// This class implements OAuth 1.0A authentication for HTTP requests,
+	/// according to RFC 5849.
+	/// 
+	/// Only PLAINTEXT and HMAC-SHA1 signature methods are
+	/// supported. The RSA-SHA1 signature method is not supported.
+	///
+	/// The OAuth10Credentials can be used to sign a client request, as
+	/// well as to verify the signature of a request on the server.
+	///
+	/// To sign a client request, using a known consumer (client) key, consumer (client) secret,
+	/// OAuth token and token secret:
+	///
+	///   1. Create an OAuth10Credentials object using all four credentials, either using
+	///      the four argument constructor, or by using the default constructor and setting
+	///      the credentials using the setter methods.
+	///   2. Create a URI containing the full request URI.
+	///   3. Create an appropriate HTTPRequest object.
+	///   4. Optionally, create a HTMLForm object containing additional parameters to sign.
+	///   5. Sign the request by calling authenticate(). This will add an OAuth
+	///      Authorization header to the request.
+	///   6. Send the request using a HTTPClientSession.
+	///
+	/// To request the OAuth request token from a server, using only the consumer (client) key
+	/// and consumer (client) secret:
+	///
+	///   1. Create an OAuth10Credentials object using the two consumer credentials, either using
+	///      the two argument constructor, or by using the default constructor and setting
+	///      the credentials using the setter methods.
+	///   2. Specify the callback URI using setCallback().
+	///   3. Create a URI containing the full request URI to obtain the token.
+	///   4. Create an appropriate HTTPRequest object.
+	///   5. Sign the request by calling authenticate(). This will add an OAuth
+	///      Authorization header to the request.
+	///   6. Send the request using a HTTPClientSession.
+	///   7. The response will contain the request token and request token secret.
+	///      These can be extracted from the response body using a HTMLForm object.
+	///
+	/// Requesting the access token and secret (temporary credentials) from the server 
+	/// is analogous to signing a client request using consumer key, consumer secret, 
+	/// request token and request token secret. 
+	/// The server response will contain the access token and access token secret,
+	/// which can again be extracted from the response body using a HTMLForm object.
+	///
+	/// To verify a request on the server:
+	///
+	///   1. Create an OAuth10Credentials object using the constructor taking a
+	///      HTTPRequest object. This will extract the consumer key and token (if
+	///      provided).
+	///   2. Provide the consumer secret and token secret (if required) matching the
+	///      consumer key and token to the OAuth10Credentials object using the 
+	///      setter methods.
+	///   3. Create an URI object containing the full request URI.
+	///   4. Call verify() to verify the signature.
+	///   5. If verification was successful, and the request was a request for
+	///      a request (temporary) token, call getCallback() to
+	///      obtain the callback URI provided by the client.
+{
+public:
+	enum SignatureMethod
+		/// OAuth 1.0A Signature Method.
+	{
+		SIGN_PLAINTEXT, /// OAuth 1.0A PLAINTEXT signature method
+		SIGN_HMAC_SHA1  /// OAuth 1.0A HMAC-SHA1 signature method
+	};
+	
+	OAuth10Credentials();
+		/// Creates an empty OAuth10Credentials object.
+
+	OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret);
+		/// Creates an OAuth10Credentials object with the given consumer key and consumer secret.
+		///
+		/// The token and tokenSecret will be left empty.
+
+	OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret, const std::string& token, const std::string& tokenSecret);
+		/// Creates an OAuth10Credentials object with the given consumer key and 
+		/// consumer secret, as well as token and token secret.
+
+	explicit OAuth10Credentials(const HTTPRequest& request);
+		/// Creates an OAuth10Credentials object from a HTTPRequest object.
+		///
+		/// Extracts consumer key and token (if available) from the Authorization header.
+		///
+		/// Throws a NotAuthenticatedException if the request does
+		/// not contain OAuth 1.0 credentials.
+
+	~OAuth10Credentials();
+		/// Destroys the OAuth10Credentials.
+
+	void setConsumerKey(const std::string& consumerKey);
+		/// Sets the consumer key.
+		
+	const std::string& getConsumerKey() const;
+		/// Returns the consumer key.
+
+	void setConsumerSecret(const std::string& consumerSecret);
+		/// Sets the consumer secret.
+		
+	const std::string& getConsumerSecret() const;
+		/// Returns the consumer secret.
+		
+	void setToken(const std::string& token);
+		/// Sets the token.
+		
+	const std::string& getToken() const;
+		/// Returns the token.
+
+	void setTokenSecret(const std::string& tokenSecret);
+		/// Sets the token.
+		
+	const std::string& getTokenSecret() const;
+		/// Returns the token secret.
+		
+	void setRealm(const std::string& realm);
+		/// Sets the optional realm to be included in the Authorization header.
+		
+	const std::string& getRealm() const;
+		/// Returns the optional realm to be included in the Authorization header.
+		
+	void setCallback(const std::string& uri);
+		/// Sets the callback URI.
+		
+	const std::string& getCallback() const;
+		/// Returns the callback URI.
+				
+	void authenticate(HTTPRequest& request, const Poco::URI& uri, SignatureMethod method = SIGN_HMAC_SHA1);
+		/// Adds an OAuth 1.0A Authentication header to the given request, using
+		/// the given signature method.
+		
+	void authenticate(HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params, SignatureMethod method = SIGN_HMAC_SHA1);
+		/// Adds an OAuth 1.0A Authentication header to the given request, using
+		/// the given signature method.
+
+	bool verify(const HTTPRequest& request, const Poco::URI& uri);
+		/// Verifies the signature of the given request. 
+		///
+		/// The consumer key, consumer secret, token and token secret must have been set.
+		///
+		/// Returns true if the signature is valid, otherwise false.
+		///
+		/// Throws a NotAuthenticatedException if the request does not contain OAuth
+		/// credentials, or in case of an unsupported OAuth version or signature method.
+		
+	bool verify(const HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params);
+		/// Verifies the signature of the given request. 
+		///
+		/// The consumer key, consumer secret, token and token secret must have been set.
+		///
+		/// Returns true if the signature is valid, otherwise false.
+		///
+		/// Throws a NotAuthenticatedException if the request does not contain OAuth
+		/// credentials, or in case of an unsupported OAuth version or signature method.
+
+	void nonceAndTimestampForTesting(const std::string& nonce, const std::string& timestamp);
+		/// Sets the nonce and timestamp to a wellknown value.
+		///
+		/// For use by testsuite only, to test the signature
+		/// algorithm with wellknown inputs.
+		///
+		/// In normal operation, the nonce is a random value
+		/// computed by createNonce() and the timestamp is taken
+		/// from the system time.
+
+	static const std::string SCHEME;
+
+protected:
+	void signPlaintext(Poco::Net::HTTPRequest& request) const;
+		/// Signs the given HTTP request according to OAuth 1.0A PLAINTEXT signature method.
+
+	void signHMACSHA1(Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params) const;
+		/// Signs the given HTTP request according to OAuth 1.0A HMAC-SHA1 signature method.
+
+	std::string createNonce() const;
+		/// Creates a nonce, which is basically a Base64-encoded 32 character random
+		/// string, with non-alphanumeric characters removed.
+
+	std::string createSignature(const Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params, const std::string& nonce, const std::string& timestamp) const;
+		/// Creates a OAuth signature for the given request and its parameters, according
+		/// to <https://dev.twitter.com/docs/auth/creating-signature>.
+		
+	static std::string percentEncode(const std::string& str);
+		/// Percent-encodes the given string according to Twitter API's rules,
+		/// given in <https://dev.twitter.com/docs/auth/percent-encoding-parameters>.
+
+private:
+	OAuth10Credentials(const OAuth10Credentials&);
+	OAuth10Credentials& operator = (const OAuth10Credentials&);
+	
+	std::string _consumerKey;
+	std::string _consumerSecret;
+	std::string _token;
+	std::string _tokenSecret;
+	std::string _callback;
+	std::string _realm;
+	std::string _nonce;
+	std::string _timestamp;
+};
+
+
+//
+// inlines
+//
+inline const std::string& OAuth10Credentials::getConsumerKey() const
+{
+	return _consumerKey;
+}
+
+
+inline const std::string& OAuth10Credentials::getConsumerSecret() const
+{
+	return _consumerSecret;
+}
+
+
+inline const std::string& OAuth10Credentials::getToken() const
+{
+	return _token;
+}
+
+
+inline const std::string& OAuth10Credentials::getTokenSecret() const
+{
+	return _tokenSecret;
+}
+
+
+inline const std::string& OAuth10Credentials::getRealm() const
+{
+	return _realm;
+}
+
+
+inline const std::string& OAuth10Credentials::getCallback() const
+{
+	return _callback;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_OAuth10Credentials_INCLUDED
diff --git a/Poco/Net/OAuth20Credentials.h b/Poco/Net/OAuth20Credentials.h
new file mode 100644
index 0000000..6935f2d
--- /dev/null
+++ b/Poco/Net/OAuth20Credentials.h
@@ -0,0 +1,132 @@
+//
+// OAuth20Credentials.h
+//
+// Library: Net
+// Package: OAuth
+// Module:	OAuth20Credentials
+//
+// Definition of the OAuth20Credentials class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_OAuth20Credentials_INCLUDED
+#define Net_OAuth20Credentials_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPRequest;
+
+
+class Net_API OAuth20Credentials
+	/// This class implements OAuth 2.0 authentication for HTTP requests,
+	/// via Bearer tokens in the Authorization header, 
+	/// according to RFC 6749 and RFC 6750.
+	///
+	/// To add an Authorization header containing a bearer token
+	/// to a HTTPRequest object, create an OAuth20Credentials object
+	/// with the bearer token and call authenticate().
+	///
+	/// The bearer token can also be extracted from a HTTPRequest
+	/// by creating the OAuth20Credentials object with a HTTPRequest
+	/// object containing a "Bearer" Authorization header and
+	/// calling getBearerToken().
+	///
+	/// The authorization header scheme can be changed from 
+	/// "Bearer" to a custom value. For example, GitHub uses
+	/// the "token" scheme.
+{
+public:
+	OAuth20Credentials();
+		/// Creates an empty OAuth20Credentials object.
+
+	explicit OAuth20Credentials(const std::string& bearerToken);
+		/// Creates an OAuth20Credentials object with the given bearer token.
+
+	OAuth20Credentials(const std::string& bearerToken, const std::string& scheme);
+		/// Creates an OAuth20Credentials object with the given bearer token
+		/// and authorization scheme, which overrides the default scheme ("Bearer").
+		///
+		/// This is useful for services like GitHub, which use "token" as scheme.
+
+	explicit OAuth20Credentials(const HTTPRequest& request);
+		/// Creates an OAuth20Credentials object from a HTTPRequest object.
+		///
+		/// Extracts bearer token from the Authorization header, which
+		/// must use the "Bearer" authorization scheme.
+		///
+		/// Throws a NotAuthenticatedException if the request does
+		/// not contain a bearer token in the Authorization header.
+
+	OAuth20Credentials(const HTTPRequest& request, const std::string& scheme);
+		/// Creates an OAuth20Credentials object from a HTTPRequest object.
+		///
+		/// Extracts bearer token from the Authorization header, which must
+		/// use the given authorization scheme.
+		///
+		/// Throws a NotAuthenticatedException if the request does
+		/// not contain a bearer token in the Authorization header.
+
+	~OAuth20Credentials();
+		/// Destroys the HTTPCredentials.
+
+	void setBearerToken(const std::string& bearerToken);
+		/// Sets the bearer token.
+		
+	const std::string& getBearerToken() const;
+		/// Returns the bearer token.
+
+	void setScheme(const std::string& scheme);
+		/// Sets the Authorization header scheme.
+		
+	const std::string& getScheme() const;
+		/// Returns the Authorization header scheme.
+		
+	void authenticate(HTTPRequest& request);
+		/// Adds an Authorization header containing the bearer token to
+		/// the HTTPRequest.
+
+	static const std::string SCHEME;
+
+protected:
+	void extractBearerToken(const HTTPRequest& request);
+		/// Extracts the bearer token from the HTTPRequest.
+		
+private:
+	OAuth20Credentials(const OAuth20Credentials&);
+	OAuth20Credentials& operator = (const OAuth20Credentials&);
+	
+	std::string _bearerToken;
+	std::string _scheme;
+};
+
+
+//
+// inlines
+//
+inline const std::string& OAuth20Credentials::getBearerToken() const
+{
+	return _bearerToken;
+}
+
+
+inline const std::string& OAuth20Credentials::getScheme() const
+{
+	return _scheme;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_OAuth20Credentials_INCLUDED
diff --git a/Poco/Net/POP3ClientSession.h b/Poco/Net/POP3ClientSession.h
new file mode 100644
index 0000000..a4b12ce
--- /dev/null
+++ b/Poco/Net/POP3ClientSession.h
@@ -0,0 +1,185 @@
+//
+// POP3ClientSession.h
+//
+// Library: Net
+// Package: Mail
+// Module:  POP3ClientSession
+//
+// Definition of the POP3ClientSession class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_POP3ClientSession_INCLUDED
+#define Net_POP3ClientSession_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/DialogSocket.h"
+#include "Poco/Timespan.h"
+#include <ostream>
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class MessageHeader;
+class MailMessage;
+class PartHandler;
+
+
+class Net_API POP3ClientSession
+	/// This class implements an Post Office Protocol
+	/// Version 3 (POP3, RFC 1939)
+	/// client for receiving e-mail messages.
+{
+public:
+	enum
+	{
+		POP3_PORT = 110
+	};
+	
+	struct MessageInfo
+		/// Information returned by listMessages().
+	{
+		int id;
+		int size;
+	};
+	
+	typedef std::vector<MessageInfo> MessageInfoVec;
+
+	explicit POP3ClientSession(const StreamSocket& socket);
+		/// Creates the POP3ClientSession using
+		/// the given socket, which must be connected
+		/// to a POP3 server.
+
+	POP3ClientSession(const std::string& host, Poco::UInt16 port = POP3_PORT);
+		/// Creates the POP3ClientSession using a socket connected
+		/// to the given host and port.
+
+	virtual ~POP3ClientSession();
+		/// Destroys the SMTPClientSession.
+
+	void setTimeout(const Poco::Timespan& timeout);
+		/// Sets the timeout for socket read operations.
+		
+	Poco::Timespan getTimeout() const;
+		/// Returns the timeout for socket read operations.
+
+	void login(const std::string& username, const std::string& password);
+		/// Logs in to the POP3 server by sending a USER command
+		/// followed by a PASS command.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void close();
+		/// Sends a QUIT command and closes the connection to the server.	
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	int messageCount();
+		/// Sends a STAT command to determine the number of messages
+		/// available on the server and returns that number.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void listMessages(MessageInfoVec& messages);
+		/// Fills the given vector with the ids and sizes of all
+		/// messages available on the server.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void retrieveMessage(int id, MailMessage& message);
+		/// Retrieves the message with the given id from the server and
+		/// stores the raw message content in the message's
+		/// content string, available with message.getContent().
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void retrieveMessage(int id, MailMessage& message, PartHandler& handler);
+		/// Retrieves the message with the given id from the server and
+		/// stores it in message.
+		///
+		/// If the message has multiple parts, the parts
+		/// are reported to the PartHandler. If the message
+		/// is not a multi-part message, the content is stored
+		/// in a string available by calling message.getContent().
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void retrieveMessage(int id, std::ostream& ostr);
+		/// Retrieves the raw message with the given id from the
+		/// server and copies it to the given output stream.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void retrieveHeader(int id, MessageHeader& header);
+		/// Retrieves the message header of the message with the
+		/// given id and stores it in header.
+		///
+		/// For this to work, the server must support the TOP command.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void deleteMessage(int id);
+		/// Marks the message with the given ID for deletion. The message
+		/// will be deleted when the connection to the server is
+		/// closed by calling close().
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	bool sendCommand(const std::string& command, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+		///
+		/// Returns true if the response is positive, false otherwise.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	bool sendCommand(const std::string& command, const std::string& arg, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+		///
+		/// Returns true if the response is positive, false otherwise.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	bool sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+		///
+		/// Returns true if the response is positive, false otherwise.
+		///
+		/// Throws a POP3Exception in case of a POP3-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+protected:
+	static bool isPositive(const std::string& response);
+	
+private:
+	DialogSocket _socket;
+	bool         _isOpen;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_POP3ClientSession_INCLUDED
diff --git a/Poco/Net/ParallelSocketAcceptor.h b/Poco/Net/ParallelSocketAcceptor.h
new file mode 100644
index 0000000..514bcfb
--- /dev/null
+++ b/Poco/Net/ParallelSocketAcceptor.h
@@ -0,0 +1,233 @@
+//
+// ParallelSocketAcceptor.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  ParallelSocketAcceptor
+//
+// Definition of the ParallelSocketAcceptor class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ParallelSocketAcceptor_INCLUDED
+#define Net_ParallelSocketAcceptor_INCLUDED
+
+
+#include "Poco/Net/ParallelSocketReactor.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Environment.h"
+#include "Poco/NObserver.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+
+
+using Poco::Net::Socket;
+using Poco::Net::SocketReactor;
+using Poco::Net::ServerSocket;
+using Poco::Net::StreamSocket;
+using Poco::NObserver;
+using Poco::AutoPtr;
+
+
+namespace Poco {
+namespace Net {
+
+
+template <class ServiceHandler, class SR>
+class ParallelSocketAcceptor
+	/// This class implements the Acceptor part of the Acceptor-Connector design pattern.
+	/// Only the difference from single-threaded version is documented here, For full 
+	/// description see Poco::Net::SocketAcceptor documentation.
+	/// 
+	/// This is a multi-threaded version of SocketAcceptor, it differs from the
+	/// single-threaded version in number of reactors (defaulting to number of processors)
+	/// that can be specified at construction time and is rotated in a round-robin fashion
+	/// by event handler. See ParallelSocketAcceptor::onAccept and 
+	/// ParallelSocketAcceptor::createServiceHandler documentation and implementation for 
+	/// details.
+{
+public:
+	typedef Poco::Net::ParallelSocketReactor<SR> ParallelReactor;
+
+	explicit ParallelSocketAcceptor(ServerSocket& socket,
+		unsigned threads = Poco::Environment::processorCount()):
+		_socket(socket),
+		_pReactor(0),
+		_threads(threads),
+		_next(0)
+		/// Creates a ParallelSocketAcceptor using the given ServerSocket, 
+		/// sets number of threads and populates the reactors vector.
+	{
+		init();
+	}
+
+	ParallelSocketAcceptor(ServerSocket& socket,
+		SocketReactor& reactor,
+		unsigned threads = Poco::Environment::processorCount()):
+		_socket(socket),
+		_pReactor(&reactor),
+		_threads(threads),
+		_next(0)
+		/// Creates a ParallelSocketAcceptor using the given ServerSocket, sets the 
+		/// number of threads, populates the reactors vector and registers itself 
+		/// with the given SocketReactor.
+	{
+		init();
+		_pReactor->addEventHandler(_socket,
+			Poco::Observer<ParallelSocketAcceptor,
+			ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept));
+	}
+
+	virtual ~ParallelSocketAcceptor()
+		/// Destroys the ParallelSocketAcceptor.
+	{
+		try
+		{
+			if (_pReactor)
+			{
+				_pReactor->removeEventHandler(_socket,
+					Poco::Observer<ParallelSocketAcceptor,
+					ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept));
+			}
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	void setReactor(SocketReactor& reactor)
+		/// Sets the reactor for this acceptor.
+	{
+		_pReactor = &reactor;
+		if (!_pReactor->hasEventHandler(_socket, 
+			Poco::Observer<ParallelSocketAcceptor,
+			ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept)))
+		{
+			registerAcceptor(reactor);
+		}
+	}
+	
+	virtual void registerAcceptor(SocketReactor& reactor)
+		/// Registers the ParallelSocketAcceptor with a SocketReactor.
+		///
+		/// A subclass can override this function to e.g.
+		/// register an event handler for timeout event.
+		/// 
+		/// The overriding method must either call the base class
+		/// implementation or register the accept handler on its own.
+	{
+		if (_pReactor)
+			throw Poco::InvalidAccessException("Acceptor already registered.");
+
+		_pReactor = &reactor;
+		_pReactor->addEventHandler(_socket,
+			Poco::Observer<ParallelSocketAcceptor,
+			ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept));
+	}
+	
+	virtual void unregisterAcceptor()
+		/// Unregisters the ParallelSocketAcceptor.
+		///
+		/// A subclass can override this function to e.g.
+		/// unregister its event handler for a timeout event.
+		/// 
+		/// The overriding method must either call the base class
+		/// implementation or unregister the accept handler on its own.
+	{
+		if (_pReactor)
+		{
+			_pReactor->removeEventHandler(_socket,
+				Poco::Observer<ParallelSocketAcceptor,
+				ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept));
+		}
+	}
+	
+	void onAccept(ReadableNotification* pNotification)
+		/// Accepts connection and creates event handler.
+	{
+		pNotification->release();
+		StreamSocket sock = _socket.acceptConnection();
+		_pReactor->wakeUp();
+		createServiceHandler(sock);
+	}
+
+protected:
+	virtual ServiceHandler* createServiceHandler(StreamSocket& socket)
+		/// Create and initialize a new ServiceHandler instance.
+		///
+		/// Subclasses can override this method.
+	{
+		std::size_t next = _next++;
+		if (_next == _reactors.size()) _next = 0;
+		_reactors[next]->wakeUp();
+		return new ServiceHandler(socket, *_reactors[next]);
+	}
+
+	SocketReactor* reactor()
+		/// Returns a pointer to the SocketReactor where
+		/// this SocketAcceptor is registered.
+		///
+		/// The pointer may be null.
+	{
+		return _pReactor;
+	}
+
+	Socket& socket()
+		/// Returns a reference to the SocketAcceptor's socket.
+	{
+		return _socket;
+	}
+
+	void init()
+		/// Populates the reactors vector.
+	{
+		poco_assert (_threads > 0);
+
+		for (unsigned i = 0; i < _threads; ++i)
+			_reactors.push_back(new ParallelReactor);
+	}
+
+	typedef std::vector<typename ParallelReactor::Ptr> ReactorVec;
+
+	ReactorVec& reactors()
+		/// Returns reference to vector of reactors.
+	{
+		return _reactors;
+	}
+
+	SocketReactor* reactor(std::size_t idx)
+		/// Returns reference to the reactor at position idx.
+	{
+		return _reactors.at(idx).get();
+	}
+
+	std::size_t& next()
+		/// Returns reference to the next reactor index.
+	{
+		return _next;
+	}
+
+private:
+	ParallelSocketAcceptor();
+	ParallelSocketAcceptor(const ParallelSocketAcceptor&);
+	ParallelSocketAcceptor& operator = (const ParallelSocketAcceptor&);
+
+	ServerSocket   _socket;
+	SocketReactor* _pReactor;
+	unsigned       _threads;
+	ReactorVec     _reactors;
+	std::size_t    _next;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ParallelSocketAcceptor_INCLUDED
diff --git a/Poco/Net/ParallelSocketReactor.h b/Poco/Net/ParallelSocketReactor.h
new file mode 100644
index 0000000..a7631ce
--- /dev/null
+++ b/Poco/Net/ParallelSocketReactor.h
@@ -0,0 +1,90 @@
+//
+// ParallelSocketReactor.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  ParallelSocketReactor
+//
+// Definition of the ParallelSocketReactor class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ParallelSocketReactor_INCLUDED
+#define Net_ParallelSocketReactor_INCLUDED
+
+
+#include "Poco/Net/SocketReactor.h"
+#include "Poco/Net/SocketNotification.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/NObserver.h"
+#include "Poco/Thread.h"
+#include "Poco/SharedPtr.h"
+
+
+using Poco::Net::Socket;
+using Poco::Net::SocketReactor;
+using Poco::Net::ReadableNotification;
+using Poco::Net::ShutdownNotification;
+using Poco::Net::ServerSocket;
+using Poco::Net::StreamSocket;
+using Poco::NObserver;
+using Poco::AutoPtr;
+using Poco::Thread;
+
+
+namespace Poco {
+namespace Net {
+
+
+template <class SR>
+class ParallelSocketReactor: public SR
+{
+public:
+	typedef Poco::SharedPtr<ParallelSocketReactor> Ptr;
+
+	ParallelSocketReactor()
+	{
+		_thread.start(*this);
+	}
+	
+	ParallelSocketReactor(const Poco::Timespan& timeout):
+		SR(timeout)
+	{
+		_thread.start(*this);
+	}
+	
+	~ParallelSocketReactor()
+	{
+		try
+		{
+			this->stop();
+			_thread.join();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+	
+protected:
+	void onIdle()
+	{
+		SR::onIdle();
+		Poco::Thread::yield();
+	}
+	
+private:
+	Poco::Thread _thread;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ParallelSocketReactor_INCLUDED
diff --git a/Poco/Net/PartHandler.h b/Poco/Net/PartHandler.h
new file mode 100644
index 0000000..941dd03
--- /dev/null
+++ b/Poco/Net/PartHandler.h
@@ -0,0 +1,68 @@
+//
+// PartHandler.h
+//
+// Library: Net
+// Package: Messages
+// Module:  PartHandler
+//
+// Definition of the PartHandler class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_PartHandler_INCLUDED
+#define Net_PartHandler_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class MessageHeader;
+
+
+class Net_API PartHandler
+	/// The base class for all part or attachment handlers.
+	///
+	/// Part handlers are used for handling email parts and 
+	/// attachments in MIME multipart messages, as well as file 
+	/// uploads via HTML forms.
+	///
+	/// Subclasses must override handlePart().
+{
+public:
+	virtual void handlePart(const MessageHeader& header, std::istream& stream) = 0;
+		/// Called for every part encountered during the processing
+		/// of an email message or an uploaded HTML form.
+		///
+		/// Information about the part can be extracted from
+		/// the given message header. What information can be obtained
+		/// from header depends on the kind of part.
+		///
+		/// The content of the part can be read from stream.
+		
+protected:
+	PartHandler();
+		/// Creates the PartHandler.
+
+	virtual ~PartHandler();
+		/// Destroys the PartHandler.
+
+private:
+	PartHandler(const PartHandler&);
+	PartHandler& operator = (const PartHandler&);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_PartHandler_INCLUDED
diff --git a/Poco/Net/PartSource.h b/Poco/Net/PartSource.h
new file mode 100644
index 0000000..06978d7
--- /dev/null
+++ b/Poco/Net/PartSource.h
@@ -0,0 +1,110 @@
+//
+// PartSource.h
+//
+// Library: Net
+// Package: Messages
+// Module:  PartSource
+//
+// Definition of the PartSource class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_PartSource_INCLUDED
+#define Net_PartSource_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/MessageHeader.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API PartSource
+	/// This abstract class is used for adding parts or attachments
+	/// to mail messages, as well as for uploading files as part of a HTML form.
+{
+public:
+	virtual std::istream& stream() = 0;
+		/// Returns an input stream for reading the
+		/// part data.
+		///
+		/// Subclasses must override this method.
+
+	virtual const std::string& filename() const;
+		/// Returns the filename for the part or attachment.
+		///
+		/// May be overridded by subclasses. The default
+		/// implementation returns an empty string.
+
+	const std::string& mediaType() const;
+		/// Returns the MIME media type for this part or attachment.
+
+	MessageHeader& headers();
+		/// Returns a MessageHeader containing additional header
+		/// fields for the part.
+
+	const MessageHeader& headers() const;
+		/// Returns a MessageHeader containing additional header
+		/// fields for the part.
+
+	virtual std::streamsize getContentLength() const;
+		/// Returns the content length for this part
+		/// which may be UNKNOWN_CONTENT_LENGTH if
+		/// not available.
+
+	virtual ~PartSource();
+		/// Destroys the PartSource.
+
+	static const int UNKNOWN_CONTENT_LENGTH;
+
+protected:
+	PartSource();
+		/// Creates the PartSource, using
+		/// the application/octet-stream MIME type.
+
+	PartSource(const std::string& mediaType);
+		/// Creates the PartSource, using the
+		/// given MIME type.
+
+private:
+	PartSource(const PartSource&);
+	PartSource& operator = (const PartSource&);
+
+	std::string _mediaType;
+	MessageHeader _headers;
+};
+
+
+//
+// inlines
+//
+inline const std::string& PartSource::mediaType() const
+{
+	return _mediaType;
+}
+
+
+inline MessageHeader& PartSource::headers()
+{
+	return _headers;
+}
+
+
+inline const MessageHeader& PartSource::headers() const
+{
+	return _headers;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_PartSource_INCLUDED
diff --git a/Poco/Net/PartStore.h b/Poco/Net/PartStore.h
new file mode 100644
index 0000000..a7be187
--- /dev/null
+++ b/Poco/Net/PartStore.h
@@ -0,0 +1,106 @@
+//
+// PartStore.h
+//
+// Library: Net
+// Package: Messages
+// Module:  PartStore
+//
+// Definition of the PartStore class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_PartStore_INCLUDED
+#define Net_PartStore_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/PartSource.h"
+#include "Poco/FileStream.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API PartStore: public PartSource
+	/// A parent class for part stores storing message parts.
+{
+public:
+	PartStore(const std::string& mediaType);
+		/// Creates the PartStore for the given MIME type.
+
+	~PartStore();
+		/// Destroys the PartFileStore.
+
+private:
+	PartStore();
+};
+
+
+class Net_API FilePartStore: public PartStore
+	/// An implementation of PartSource for persisting
+	/// parts (usually email attachment files) to the file system.
+{
+public:
+	FilePartStore(const std::string& content, const std::string& mediaType, const std::string& filename = "");
+		/// Creates the FilePartStore for the given MIME type.
+		/// For security purposes, attachment filename is NOT used to save file to the file system.
+		/// A unique temporary file name is used to persist the file.
+		/// The given filename parameter is the message part (attachment) filename (see filename()) only.
+		///
+		/// Throws an exception if the file cannot be opened.
+
+	~FilePartStore();
+		/// Destroys the FilePartStore.
+
+	std::istream& stream();
+		/// Returns a file input stream for the given file.
+
+	const std::string& filename() const;
+		/// Returns the filename portion of the path.
+		/// This is the name under which the file is known
+		/// to the user of this class (typically, MailMessage
+		/// class). The real name of the file as saved
+		/// to the filesystem can be obtained by calling
+		/// path() member function.
+
+	const std::string& path() const;
+		/// Returns the full path to the file as saved
+		/// to the file system. For security reasons,
+		/// file is not saved under the real file name
+		/// (as specified by the user).
+
+private:
+	std::string      _filename;
+	std::string      _path;
+	Poco::FileStream _fstr;
+};
+
+
+class PartStoreFactory
+	/// Parent factory class for part stores creation.
+{
+public:
+	virtual PartSource* createPartStore(const std::string& content, const std::string& mediaType, const std::string& filename = "") = 0;
+};
+
+
+class FilePartStoreFactory: public PartStoreFactory
+{
+public:
+	PartSource* createPartStore(const std::string& content, const std::string& mediaType, const std::string& filename = "")
+	{
+		return new FilePartStore(content, mediaType, filename);
+	}
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_PartStore_INCLUDED
diff --git a/Poco/Net/PollSet.h b/Poco/Net/PollSet.h
new file mode 100644
index 0000000..9b24e13
--- /dev/null
+++ b/Poco/Net/PollSet.h
@@ -0,0 +1,86 @@
+//
+// PollSet.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  PollSet
+//
+// Definition of the PollSet class.
+//
+// Copyright (c) 2016, Applied Informatics Software Engineering GmbH.
+// All rights reserved.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_PollSet_INCLUDED
+#define Net_PollSet_INCLUDED
+
+
+#include "Poco/Net/Socket.h"
+#include <map>
+
+
+namespace Poco {
+namespace Net {
+
+
+class PollSetImpl;
+
+
+class Net_API PollSet
+	/// A set of sockets that can be efficiently polled as a whole.
+	///
+	/// If supported, PollSet is implemented using epoll (Linux) or
+	/// poll (BSD) APIs. A fallback implementation using select()
+	/// is also provided.
+{
+public:
+	enum Mode
+	{
+		POLL_READ  = 0x01,
+		POLL_WRITE = 0x02,
+		POLL_ERROR = 0x04
+	};
+
+	typedef std::map<Poco::Net::Socket, int> SocketModeMap;
+
+	PollSet();
+		/// Creates an empty PollSet.
+
+	~PollSet();
+		/// Destroys the PollSet.
+
+	void add(const Poco::Net::Socket& socket, int mode);
+		/// Adds the given socket to the set, for polling with
+		/// the given mode, which can be an OR'd combination of
+		/// POLL_READ, POLL_WRITE and POLL_ERROR.
+
+	void remove(const Poco::Net::Socket& socket);
+		/// Removes the given socket from the set.
+
+	void update(const Poco::Net::Socket& socket, int mode);
+		/// Updates the mode of the given socket.
+
+	void clear();
+		/// Removes all sockets from the PollSet.
+
+	SocketModeMap poll(const Poco::Timespan& timeout);
+		/// Waits until the state of at least one of the PollSet's sockets
+		/// changes accordingly to its mode, or the timeout expires.
+		/// Returns a PollMap containing the sockets that have had
+		/// their state changed.
+
+private:
+	PollSetImpl* _pImpl;
+
+	PollSet(const PollSet&);
+	PollSet& operator = (const PollSet&);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_PollSet_INCLUDED
diff --git a/Poco/Net/PrivateKeyFactory.h b/Poco/Net/PrivateKeyFactory.h
new file mode 100644
index 0000000..9c0fa37
--- /dev/null
+++ b/Poco/Net/PrivateKeyFactory.h
@@ -0,0 +1,95 @@
+//
+// PrivateKeyFactory.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  PrivateKeyFactory
+//
+// Definition of the PrivateKeyFactory class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_PrivateKeyFactory_INCLUDED
+#define NetSSL_PrivateKeyFactory_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class PrivateKeyPassphraseHandler;
+
+
+class NetSSL_API PrivateKeyFactory
+	/// A PrivateKeyFactory is responsible for creating PrivateKeyPassphraseHandlers.
+	///
+	/// You don't need to access this class directly. Use the macro
+	///     POCO_REGISTER_KEYFACTORY(namespace, PrivateKeyPassphraseHandlerName) 
+	/// instead (see the documentation of PrivateKeyPassphraseHandler for an example).
+{
+public:
+	PrivateKeyFactory();
+		/// Creates the PrivateKeyFactory.
+
+	virtual ~PrivateKeyFactory();
+		/// Destroys the PrivateKeyFactory.
+
+	virtual PrivateKeyPassphraseHandler* create(bool onServer) const = 0;
+		/// Creates a new PrivateKeyPassphraseHandler
+};
+
+
+class NetSSL_API PrivateKeyFactoryRegistrar
+	/// Registrar class which automatically registers PrivateKeyFactories at the PrivateKeyFactoryMgr.
+	///
+	/// You don't need to access this class directly. Use the macro
+	///     POCO_REGISTER_KEYFACTORY(namespace, PrivateKeyPassphraseHandlerName) 
+	/// instead (see the documentation of PrivateKeyPassphraseHandler for an example).
+
+{
+public:
+	PrivateKeyFactoryRegistrar(const std::string& name, PrivateKeyFactory* pFactory);
+		/// Registers the PrivateKeyFactory with the given name at the factory manager.
+
+	virtual ~PrivateKeyFactoryRegistrar();
+		/// Destroys the PrivateKeyFactoryRegistrar.
+};
+
+
+template<typename T>
+class PrivateKeyFactoryImpl: public Poco::Net::PrivateKeyFactory
+{
+public:
+	PrivateKeyFactoryImpl()
+	{
+	}
+
+	~PrivateKeyFactoryImpl()
+	{
+	}
+
+	PrivateKeyPassphraseHandler* create(bool server) const
+	{
+		return new T(server);
+	}
+};
+
+
+} } // namespace Poco::Net
+
+
+// DEPRECATED: register the factory directly at the FactoryMgr:
+// Poco::Net::SSLManager::instance().privateKeyFactoryMgr().setFactory(name, new Poco::Net::PrivateKeyFactoryImpl<MyKeyHandler>());
+#define POCO_REGISTER_KEYFACTORY(API, PKCLS)	\
+	static Poco::Net::PrivateKeyFactoryRegistrar aRegistrar(std::string(#PKCLS), new Poco::Net::PrivateKeyFactoryImpl<PKCLS>());
+
+
+#endif // NetSSL_PrivateKeyFactory_INCLUDED
diff --git a/Poco/Net/PrivateKeyFactoryMgr.h b/Poco/Net/PrivateKeyFactoryMgr.h
new file mode 100644
index 0000000..b29b37f
--- /dev/null
+++ b/Poco/Net/PrivateKeyFactoryMgr.h
@@ -0,0 +1,64 @@
+//
+// PrivateKeyFactoryMgr.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  PrivateKeyFactoryMgr
+//
+// Definition of the PrivateKeyFactoryMgr class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_PrivateKeyFactoryMgr_INCLUDED
+#define NetSSL_PrivateKeyFactoryMgr_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/PrivateKeyFactory.h"
+#include "Poco/SharedPtr.h"
+#include <map>
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API PrivateKeyFactoryMgr
+	/// A PrivateKeyFactoryMgr manages all existing PrivateKeyFactories.
+{
+public:
+	typedef std::map<std::string, Poco::SharedPtr<PrivateKeyFactory> > FactoriesMap;
+	
+	PrivateKeyFactoryMgr();
+		/// Creates the PrivateKeyFactoryMgr.
+
+	~PrivateKeyFactoryMgr();
+		/// Destroys the PrivateKeyFactoryMgr.
+
+	void setFactory(const std::string& name, PrivateKeyFactory* pFactory);
+		/// Registers the factory. Class takes ownership of the pointer.
+		/// If a factory with the same name already exists, an exception is thrown.
+
+	bool hasFactory(const std::string& name) const;
+		/// Returns true if for the given name a factory is already registered
+	
+	const PrivateKeyFactory* getFactory(const std::string& name) const;
+		/// Returns NULL if for the given name a factory does not exist, otherwise the factory is returned
+
+	void removeFactory(const std::string& name);
+		/// Removes the factory from the manager. 
+
+private:
+	FactoriesMap _factories;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_PrivateKeyFactoryMgr_INCLUDED
diff --git a/Poco/Net/PrivateKeyPassphraseHandler.h b/Poco/Net/PrivateKeyPassphraseHandler.h
new file mode 100644
index 0000000..726703f
--- /dev/null
+++ b/Poco/Net/PrivateKeyPassphraseHandler.h
@@ -0,0 +1,84 @@
+//
+// PrivateKeyPassphraseHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  PrivateKeyPassphraseHandler
+//
+// Definition of the PrivateKeyPassphraseHandler class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_PrivateKeyPassphraseHandler_INCLUDED
+#define NetSSL_PrivateKeyPassphraseHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API PrivateKeyPassphraseHandler
+	/// A passphrase handler is needed whenever the private key of a certificate is loaded and the certificate is protected
+	/// by a passphrase. The PrivateKeyPassphraseHandler's task is to provide that passphrase.
+	/// One can install one's own PrivateKeyPassphraseHandler by implementing this interface. Note that
+	/// in the implementation file of the subclass the following code must be present (assuming you use the namespace My_API 
+	/// and the name of your handler class is MyGuiHandler):
+	///    
+	///    #include "Poco/Net/PrivateKeyFactory.h"
+	///    ...
+	///    POCO_REGISTER_KEYFACTORY(My_API, MyGuiHandler)
+	///
+	/// One can either set the handler directly in the startup code of the main method of ones application by calling
+	///
+	///    SSLManager::instance().initialize(myguiHandler, myInvalidCertificateHandler, mySSLContext)
+	///
+	/// or in case one's application extends Poco::Util::Application one can use an XML configuration and put the following entry
+	/// under the path openSSL.privateKeyPassphraseHandler:
+	///    
+	///    <privateKeyPassphraseHandler>
+	///        <name>MyGuiHandler</name>
+	///        <options>
+	///            [...] // Put optional config params for the handler here
+	///        </options>
+	///    </privateKeyPassphraseHandler>
+	///
+	/// Note that the name of the passphrase handler must be same as the one provided to the POCO_REGISTER_KEYFACTORY macro.
+{
+public:
+	PrivateKeyPassphraseHandler(bool onServerSide);
+		/// Creates the PrivateKeyPassphraseHandler. Automatically registers at the SSLManager::PrivateKeyPassword event.
+
+	virtual ~PrivateKeyPassphraseHandler();
+		/// Destroys the PrivateKeyPassphraseHandler.
+
+	virtual void onPrivateKeyRequested(const void* pSender, std::string& privateKey) = 0;
+		/// Returns the requested private key in the parameter privateKey.
+
+	bool serverSide() const;
+
+private:
+	bool _serverSide;
+};
+
+
+//
+// inlines
+//
+inline bool PrivateKeyPassphraseHandler::serverSide() const
+{
+	return _serverSide;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_PrivateKeyPassphraseHandler_INCLUDED
diff --git a/Poco/Net/QuotedPrintableDecoder.h b/Poco/Net/QuotedPrintableDecoder.h
new file mode 100644
index 0000000..b456660
--- /dev/null
+++ b/Poco/Net/QuotedPrintableDecoder.h
@@ -0,0 +1,86 @@
+//
+// QuotedPrintableDecoder.h
+//
+// Library: Net
+// Package: Messages
+// Module:  QuotedPrintableDecoder
+//
+// Definition of the QuotedPrintableDecoder class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_QuotedPrintableDecoder_INCLUDED
+#define Net_QuotedPrintableDecoder_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API QuotedPrintableDecoderBuf: public Poco::UnbufferedStreamBuf
+	/// This streambuf decodes all quoted-printable (see RFC 2045) 
+	/// encoded data read from the istream connected to it.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	QuotedPrintableDecoderBuf(std::istream& istr);
+	~QuotedPrintableDecoderBuf();
+	
+private:
+	int readFromDevice();
+
+	std::streambuf& _buf;
+};
+
+
+class Net_API QuotedPrintableDecoderIOS: public virtual std::ios
+	/// The base class for QuotedPrintableDecoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	QuotedPrintableDecoderIOS(std::istream& istr);
+	~QuotedPrintableDecoderIOS();
+	QuotedPrintableDecoderBuf* rdbuf();
+
+protected:
+	QuotedPrintableDecoderBuf _buf;
+};
+
+
+class Net_API QuotedPrintableDecoder: public QuotedPrintableDecoderIOS, public std::istream
+	/// This istream decodes all quoted-printable (see RFC 2045)
+	/// encoded data read from the istream connected to it.
+	///
+	/// Note: For performance reasons, the characters 
+	/// are read directly from the given istream's 
+	/// underlying streambuf, so the state
+	/// of the istream will not reflect that of
+	/// its streambuf.
+{
+public:
+	QuotedPrintableDecoder(std::istream& istr);
+	~QuotedPrintableDecoder();
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_QuotedPrintableDecoder_INCLUDED
diff --git a/Poco/Net/QuotedPrintableEncoder.h b/Poco/Net/QuotedPrintableEncoder.h
new file mode 100644
index 0000000..d0e7d74
--- /dev/null
+++ b/Poco/Net/QuotedPrintableEncoder.h
@@ -0,0 +1,85 @@
+//
+// QuotedPrintableEncoder.h
+//
+// Library: Net
+// Package: Messages
+// Module:  QuotedPrintableEncoder
+//
+// Definition of the QuotedPrintableEncoder class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_QuotedPrintableEncoder_INCLUDED
+#define Net_QuotedPrintableEncoder_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API QuotedPrintableEncoderBuf: public Poco::UnbufferedStreamBuf
+	/// This streambuf encodes all data written
+	/// to it in quoted-printable encoding (see RFC 2045)
+	/// and forwards it to a connected ostream.
+{
+public:
+	QuotedPrintableEncoderBuf(std::ostream& ostr);
+	~QuotedPrintableEncoderBuf();
+	int close();
+	
+private:
+	int writeToDevice(char c);
+	void writeEncoded(char c);
+	void writeRaw(char c);
+
+	int           _pending;
+	int           _lineLength;
+	std::ostream& _ostr;
+};
+
+
+class Net_API QuotedPrintableEncoderIOS: public virtual std::ios
+	/// The base class for QuotedPrintableEncoder.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	QuotedPrintableEncoderIOS(std::ostream& ostr);
+	~QuotedPrintableEncoderIOS();
+	int close();
+	QuotedPrintableEncoderBuf* rdbuf();
+
+protected:
+	QuotedPrintableEncoderBuf _buf;
+};
+
+
+class Net_API QuotedPrintableEncoder: public QuotedPrintableEncoderIOS, public std::ostream
+	/// This ostream encodes all data
+	/// written to it in quoted-printable encoding
+	/// (see RFC 2045) and forwards it to a connected ostream.
+	/// Always call close() when done
+	/// writing data, to ensure proper
+	/// completion of the encoding operation.
+{
+public:
+	QuotedPrintableEncoder(std::ostream& ostr);
+	~QuotedPrintableEncoder();
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_QuotedPrintableEncoder_INCLUDED
diff --git a/Poco/Net/RawSocket.h b/Poco/Net/RawSocket.h
new file mode 100644
index 0000000..3638b20
--- /dev/null
+++ b/Poco/Net/RawSocket.h
@@ -0,0 +1,161 @@
+//
+// RawSocket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  RawSocket
+//
+// Definition of the RawSocket class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_RawSocket_INCLUDED
+#define Net_RawSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API RawSocket: public Socket
+	/// This class provides an interface to a
+	/// raw IP socket.
+{
+public:
+	RawSocket();
+		/// Creates an unconnected IPv4 raw socket.
+
+	RawSocket(SocketAddress::Family family, int proto = IPPROTO_RAW);
+		/// Creates an unconnected raw socket.
+		///
+		/// The socket will be created for the
+		/// given address family.
+
+	RawSocket(const SocketAddress& address, bool reuseAddress = false);
+		/// Creates a raw socket and binds it
+		/// to the given address.
+		///
+		/// Depending on the address family, the socket
+		/// will be either an IPv4 or an IPv6 socket.
+
+	RawSocket(const Socket& socket);
+		/// Creates the RawSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a RawSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	~RawSocket();
+		/// Destroys the RawSocket.
+
+	RawSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	void connect(const SocketAddress& address);
+		/// Restricts incoming and outgoing
+		/// packets to the specified address.
+		///
+		/// Calls to connect() cannot come before calls to bind().
+
+	void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// Calls to connect() cannot come before calls to bind().
+
+	void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+		///
+		/// Calls to connect() cannot come before calls to bind().
+
+	int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+
+	int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		///
+		/// Returns the number of bytes received.
+
+	int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket to the given address.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+
+	int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		/// Stores the address of the sender in address.
+		///
+		/// Returns the number of bytes received.
+
+	void setBroadcast(bool flag);
+		/// Sets the value of the SO_BROADCAST socket option.
+		///
+		/// Setting this flag allows sending datagrams to
+		/// the broadcast address.
+	
+	bool getBroadcast() const;
+		/// Returns the value of the SO_BROADCAST socket option.
+
+protected:
+	RawSocket(SocketImpl* pImpl);
+		/// Creates the Socket and attaches the given SocketImpl.
+		/// The socket takes ownership of the SocketImpl.
+		///
+		/// The SocketImpl must be a StreamSocketImpl, otherwise
+		/// an InvalidArgumentException will be thrown.
+};
+
+
+//
+// inlines
+//
+inline void RawSocket::setBroadcast(bool flag)
+{
+	impl()->setBroadcast(flag);
+}
+
+
+inline bool RawSocket::getBroadcast() const
+{
+	return impl()->getBroadcast();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_RawSocket_INCLUDED
diff --git a/Poco/Net/RawSocketImpl.h b/Poco/Net/RawSocketImpl.h
new file mode 100644
index 0000000..df10b64
--- /dev/null
+++ b/Poco/Net/RawSocketImpl.h
@@ -0,0 +1,56 @@
+//
+// RawSocketImpl.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  RawSocketImpl
+//
+// Definition of the RawSocketImpl class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_RawSocketImpl_INCLUDED
+#define Net_RawSocketImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketImpl.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API RawSocketImpl: public SocketImpl
+	/// This class implements a raw socket.
+{
+public:
+	RawSocketImpl();
+		/// Creates an unconnected IPv4 raw socket with IPPROTO_RAW.
+		
+	RawSocketImpl(SocketAddress::Family family, int proto = IPPROTO_RAW);
+		/// Creates an unconnected raw socket.
+		///
+		/// The socket will be created for the
+		/// given address family.
+
+	RawSocketImpl(poco_socket_t sockfd);
+		/// Creates a RawSocketImpl using the given native socket.
+				
+protected:
+	void init(int af);
+	void init2(int af, int proto);
+	
+	~RawSocketImpl();
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_RawSocketImpl_INCLUDED
diff --git a/Poco/Net/RejectCertificateHandler.h b/Poco/Net/RejectCertificateHandler.h
new file mode 100644
index 0000000..b170ad5
--- /dev/null
+++ b/Poco/Net/RejectCertificateHandler.h
@@ -0,0 +1,48 @@
+//
+// RejectCertificateHandler.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  RejectCertificateHandler
+//
+// Definition of the RejectCertificateHandler class.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_RejectCertificateHandler_INCLUDED
+#define NetSSL_RejectCertificateHandler_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/InvalidCertificateHandler.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API RejectCertificateHandler: public InvalidCertificateHandler
+	/// A RejectCertificateHandler is invoked whenever an error 
+	/// occurs verifying the certificate. It always rejects
+	/// the certificate.
+{
+public:
+	RejectCertificateHandler(bool handleErrorsOnServerSide);
+		/// Creates the RejectCertificateHandler
+
+	virtual ~RejectCertificateHandler();
+		/// Destroys the RejectCertificateHandler.
+
+	void onInvalidCertificate(const void* pSender, VerificationErrorArgs& errorCert);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_RejectCertificateHandler_INCLUDED
diff --git a/Poco/Net/RemoteSyslogChannel.h b/Poco/Net/RemoteSyslogChannel.h
new file mode 100644
index 0000000..848b163
--- /dev/null
+++ b/Poco/Net/RemoteSyslogChannel.h
@@ -0,0 +1,158 @@
+//
+// RemoteSyslogChannel.h
+//
+// Library: Net
+// Package: Logging
+// Module:  RemoteSyslogChannel
+//
+// Definition of the RemoteSyslogChannel class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_RemoteSyslogChannel_INCLUDED
+#define Net_RemoteSyslogChannel_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Channel.h"
+#include "Poco/Mutex.h"
+#include "Poco/Net/DatagramSocket.h"
+#include "Poco/Net/SocketAddress.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API RemoteSyslogChannel: public Poco::Channel
+	/// This Channel implements remote syslog logging over UDP according
+	/// to RFC 5424 "The Syslog Protocol"
+	/// and RFC 5426 "Transmission of syslog messages over UDP".
+	///
+	/// In addition, RemoteSyslogListener also supports the "old" BSD syslog
+	/// protocol, as described in RFC 3164.
+	///
+	/// RFC 5425 structured data can be passed via the "structured-data"
+	/// property of the log Message. The content of the "structured-data"
+	/// property must be correct according to RFC 5425.
+	///
+	/// Example:
+	///     msg.set("structured-data", "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"]");
+{
+public:
+	static const std::string BSD_TIMEFORMAT;
+	static const std::string SYSLOG_TIMEFORMAT;
+
+	enum Severity
+	{
+		SYSLOG_EMERGENCY     = 0, /// Emergency: system is unusable
+		SYSLOG_ALERT         = 1, /// Alert: action must be taken immediately
+		SYSLOG_CRITICAL      = 2, /// Critical: critical conditions
+		SYSLOG_ERROR         = 3, /// Error: error conditions
+		SYSLOG_WARNING       = 4, /// Warning: warning conditions
+		SYSLOG_NOTICE        = 5, /// Notice: normal but significant condition
+		SYSLOG_INFORMATIONAL = 6, /// Informational: informational messages
+		SYSLOG_DEBUG         = 7  /// Debug: debug-level messages
+	};
+
+	enum Facility
+	{
+		SYSLOG_KERN     = ( 0<<3), /// kernel messages
+		SYSLOG_USER     = ( 1<<3), /// random user-level messages
+		SYSLOG_MAIL     = ( 2<<3), /// mail system
+		SYSLOG_DAEMON   = ( 3<<3), /// system daemons
+		SYSLOG_AUTH     = ( 4<<3), /// security/authorization messages
+		SYSLOG_SYSLOG   = ( 5<<3), /// messages generated internally by syslogd
+		SYSLOG_LPR      = ( 6<<3), /// line printer subsystem
+		SYSLOG_NEWS     = ( 7<<3), /// network news subsystem
+		SYSLOG_UUCP     = ( 8<<3), /// UUCP subsystem
+		SYSLOG_CRON     = ( 9<<3), /// clock daemon
+		SYSLOG_AUTHPRIV = (10<<3), /// security/authorization messages (private)
+		SYSLOG_FTP      = (11<<3), /// ftp daemon
+		SYSLOG_NTP      = (12<<3), /// ntp subsystem
+		SYSLOG_LOGAUDIT = (13<<3), /// log audit
+		SYSLOG_LOGALERT = (14<<3), /// log alert
+		SYSLOG_CLOCK    = (15<<3), /// clock daemon
+		SYSLOG_LOCAL0   = (16<<3), /// reserved for local use
+		SYSLOG_LOCAL1   = (17<<3), /// reserved for local use
+		SYSLOG_LOCAL2   = (18<<3), /// reserved for local use
+		SYSLOG_LOCAL3   = (19<<3), /// reserved for local use
+		SYSLOG_LOCAL4   = (20<<3), /// reserved for local use
+		SYSLOG_LOCAL5   = (21<<3), /// reserved for local use
+		SYSLOG_LOCAL6   = (22<<3), /// reserved for local use
+		SYSLOG_LOCAL7   = (23<<3)  /// reserved for local use
+	};
+
+	enum
+	{
+		SYSLOG_PORT = 514
+	};
+
+	RemoteSyslogChannel();
+		/// Creates a RemoteSyslogChannel.
+
+	RemoteSyslogChannel(const std::string& address, const std::string& name, int facility = SYSLOG_USER, bool bsdFormat = false);
+		/// Creates a RemoteSyslogChannel with the given target address, name, and facility.
+		/// If bsdFormat is true, messages are formatted according to RFC 3164.
+
+	void open();
+		/// Opens the RemoteSyslogChannel.
+
+	void close();
+		/// Closes the RemoteSyslogChannel.
+
+	void log(const Message& msg);
+		/// Sends the message's text to the syslog service.
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given value.
+		///
+		/// The following properties are supported:
+		///     * name:      The name used to identify the source of log messages.
+		///     * facility:  The facility added to each log message. See the Facility enumeration for a list of supported values.
+		///                  The LOG_ prefix can be omitted and values are case insensitive (e.g. a facility value "mail" is recognized as SYSLOG_MAIL)
+		///     * format:    "bsd"/"rfc3164" (RFC 3164 format) or "new"/"rfc5424" (default)
+		///     * loghost:   The target IP address or host name where log messages are sent. Optionally, a port number (separated
+		///                  by a colon) can also be specified.
+		///     * host:      (optional) Host name included in syslog messages. If not specified, the host's real domain name or
+		///                  IP address will be used.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+
+	static void registerChannel();
+		/// Registers the channel with the global LoggingFactory.
+
+	static const std::string PROP_NAME;
+	static const std::string PROP_FACILITY;
+	static const std::string PROP_FORMAT;
+	static const std::string PROP_LOGHOST;
+	static const std::string PROP_HOST;
+	static const std::string STRUCTURED_DATA;
+
+protected:
+	~RemoteSyslogChannel();
+	static int getPrio(const Message& msg);
+
+private:
+	std::string _logHost;
+	std::string _name;
+	std::string _host;
+	int  _facility;
+	bool _bsdFormat;
+	DatagramSocket _socket;
+	SocketAddress _socketAddress;
+	bool _open;
+	mutable Poco::FastMutex _mutex;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_RemoteSyslogChannel_INCLUDED
diff --git a/Poco/Net/RemoteSyslogListener.h b/Poco/Net/RemoteSyslogListener.h
new file mode 100644
index 0000000..9389524
--- /dev/null
+++ b/Poco/Net/RemoteSyslogListener.h
@@ -0,0 +1,121 @@
+//
+// RemoteSyslogListener.h
+//
+// Library: Net
+// Package: Logging
+// Module:  RemoteSyslogListener
+//
+// Definition of the RemoteSyslogListener class.
+//
+// Copyright (c) 2007-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_RemoteSyslogListener_INCLUDED
+#define Net_RemoteSyslogListener_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/ThreadPool.h"
+#include "Poco/SplitterChannel.h"
+#include "Poco/NotificationQueue.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class RemoteUDPListener;
+class SyslogParser;
+
+
+class Net_API RemoteSyslogListener: public Poco::SplitterChannel
+	/// RemoteSyslogListener implements listening for syslog messages
+	/// sent over UDP, according to RFC 5424 "The Syslog Protocol"
+	/// and RFC 5426 "Transmission of syslog messages over UDP".
+	///
+	/// In addition, RemoteSyslogListener also supports the "old" BSD syslog
+	/// protocol, as described in RFC 3164.
+	///
+	/// The RemoteSyslogListener is a subclass of Poco::SplitterChannel.
+	/// Every received log message is sent to the channels registered
+	/// with addChannel() or the "channel" property.
+	///
+	/// Poco::Message objects created by RemoteSyslogListener will have
+	/// the following named parameters:
+	///   - addr: IP address of the host/interface sending the message.
+	///   - host: host name; only for "new" syslog messages.
+	///   - app:  application name; only for "new" syslog messages.
+	///   - structured-data: RFC 5424 structured data, or empty if not present.
+{
+public:
+	RemoteSyslogListener();
+		/// Creates the RemoteSyslogListener.
+
+	RemoteSyslogListener(Poco::UInt16 port);
+		/// Creates the RemoteSyslogListener, listening on the given port number.
+
+	RemoteSyslogListener(Poco::UInt16 port, int threads);
+		/// Creates the RemoteSyslogListener, listening on the given port number
+		/// and using the number of threads for message processing.
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given value.
+		///
+		/// The following properties are supported:
+		///     * port: The UDP port number where to listen for UDP packets
+		///       containing syslog messages. If 0 is specified, does not
+		///       listen for UDP messages.
+		///     * threads: The number of parser threads processing
+		///       received syslog messages. Defaults to 1. A maximum
+		///       of 16 threads is supported.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+
+	void open();
+		/// Starts the listener.
+
+	void close();
+		/// Stops the listener.
+
+	void processMessage(const std::string& messageText);
+		/// Parses a single line of text containing a syslog message
+		/// and sends it down the filter chain.
+
+	void enqueueMessage(const std::string& messageText, const Poco::Net::SocketAddress& senderAddress);
+		/// Enqueues a single line of text containing a syslog message
+		/// for asynchronous processing by a parser thread.
+
+	static void registerChannel();
+		/// Registers the channel with the global LoggingFactory.
+
+	static const std::string PROP_PORT;
+	static const std::string PROP_THREADS;
+
+    static const std::string LOG_PROP_APP;
+    static const std::string LOG_PROP_HOST;
+	static const std::string LOG_PROP_STRUCTURED_DATA;
+
+protected:
+	~RemoteSyslogListener();
+		/// Destroys the RemoteSyslogListener.
+
+private:
+	RemoteUDPListener*      _pListener;
+	SyslogParser*           _pParser;
+	Poco::ThreadPool        _threadPool;
+	Poco::NotificationQueue _queue;
+	Poco::UInt16            _port;
+	int                     _threads;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_RemoteSyslogListener_INCLUDED
diff --git a/Poco/Net/SMTPChannel.h b/Poco/Net/SMTPChannel.h
new file mode 100644
index 0000000..373d93d
--- /dev/null
+++ b/Poco/Net/SMTPChannel.h
@@ -0,0 +1,108 @@
+//
+// SMTPChannel.h
+//
+// Library: Net
+// Package: Logging
+// Module:  SMTPChannel
+//
+// Definition of the SMTPChannel class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SMTPChannel_INCLUDED
+#define Net_SMTPChannel_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Channel.h"
+#include "Poco/String.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API SMTPChannel: public Poco::Channel
+	/// This Channel implements SMTP (email) logging.
+{
+public:
+	SMTPChannel();
+		/// Creates a SMTPChannel.
+		
+	SMTPChannel(const std::string& mailhost, const std::string& sender, const std::string& recipient);
+		/// Creates a SMTPChannel with the given target mailhost, sender, and recipient.
+	
+	void open();
+		/// Opens the SMTPChannel.
+		
+	void close();
+		/// Closes the SMTPChannel.
+		
+	void log(const Message& msg);
+		/// Sends the message's text to the recipient.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given value.
+		///
+		/// The following properties are supported:
+		///     * mailhost:   The SMTP server. Default is "localhost".
+		///     * sender:     The sender address.
+		///     * recipient:  The recipient address.
+		///     * local:      If true, local time is used. Default is true.
+		///     * attachment: Filename of the file to attach.
+		///     * type:       Content type of the file to attach.
+		///     * delete:     Boolean value indicating whether to delete 
+		///                   the attachment file after sending.
+		///     * throw:      Boolean value indicating whether to throw 
+		///                   exception upon failure.
+		
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+
+	static void registerChannel();
+		/// Registers the channel with the global LoggingFactory.
+
+	static const std::string PROP_MAILHOST;
+	static const std::string PROP_SENDER;
+	static const std::string PROP_RECIPIENT;
+	static const std::string PROP_LOCAL;
+	static const std::string PROP_ATTACHMENT;
+	static const std::string PROP_TYPE;
+	static const std::string PROP_DELETE;
+	static const std::string PROP_THROW;
+
+protected:
+	~SMTPChannel();
+
+private:
+	bool isTrue(const std::string& value) const;
+
+	std::string _mailHost;
+	std::string _sender;
+	std::string _recipient;
+	bool        _local;
+	std::string _attachment;
+	std::string _type;
+	bool        _delete;
+	bool        _throw;
+};
+
+
+inline bool SMTPChannel::isTrue(const std::string& value) const
+{
+	return ((0 == icompare(value, "true")) ||
+			(0 == icompare(value, "t")) ||
+			(0 == icompare(value, "yes")) ||
+			(0 == icompare(value, "y")));
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SMTPChannel_INCLUDED
diff --git a/Poco/Net/SMTPClientSession.h b/Poco/Net/SMTPClientSession.h
new file mode 100644
index 0000000..5edf999
--- /dev/null
+++ b/Poco/Net/SMTPClientSession.h
@@ -0,0 +1,234 @@
+//
+// SMTPClientSession.h
+//
+// Library: Net
+// Package: Mail
+// Module:  SMTPClientSession
+//
+// Definition of the SMTPClientSession class.
+//
+// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SMTPClientSession_INCLUDED
+#define Net_SMTPClientSession_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/DialogSocket.h"
+#include "Poco/DigestEngine.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class MailMessage;
+
+
+class Net_API SMTPClientSession
+	/// This class implements an Simple Mail
+	/// Transfer Protocol (SMTP, RFC 2821)
+	/// client for sending e-mail messages.
+{
+public:
+	typedef std::vector<std::string> Recipients;
+
+	enum
+	{
+		SMTP_PORT = 25
+	};
+
+	enum LoginMethod
+	{
+		AUTH_NONE,
+		AUTH_CRAM_MD5,
+		AUTH_CRAM_SHA1,
+		AUTH_LOGIN,
+		AUTH_PLAIN,
+		AUTH_XOAUTH2 
+	};
+
+	explicit SMTPClientSession(const StreamSocket& socket);
+		/// Creates the SMTPClientSession using
+		/// the given socket, which must be connected
+		/// to a SMTP server.
+
+	SMTPClientSession(const std::string& host, Poco::UInt16 port = SMTP_PORT);
+		/// Creates the SMTPClientSession using a socket connected
+		/// to the given host and port.
+
+	virtual ~SMTPClientSession();
+		/// Destroys the SMTPClientSession.
+
+	void setTimeout(const Poco::Timespan& timeout);
+		/// Sets the timeout for socket read operations.
+		
+	Poco::Timespan getTimeout() const;
+		/// Returns the timeout for socket read operations.
+
+	void login(const std::string& hostname);
+		/// Greets the SMTP server by sending a EHLO command
+		/// with the given hostname as argument.
+		///
+		/// If the server does not understand the EHLO command,
+		/// a HELO command is sent instead.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void login();
+		/// Calls login(hostname) with the current host name.
+
+	void login(const std::string& hostname, LoginMethod loginMethod, const std::string& username, const std::string& password);
+		/// Logs in to the SMTP server using the given authentication method and the given
+		/// credentials.
+
+	void login(LoginMethod loginMethod, const std::string& username, const std::string& password);
+		/// Logs in to the SMTP server using the given authentication method and the given
+		/// credentials.
+		
+	void open();
+		/// Reads the initial response from the SMTP server.
+		///
+		/// Usually called implicitly through login(), but can
+		/// also be called explicitly to implement different forms
+		/// of SMTP authentication.
+		///
+		/// Does nothing if called more than once.
+
+	void close();
+		/// Sends a QUIT command and closes the connection to the server.	
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void sendMessage(const MailMessage& message);
+		/// Sends the given mail message by sending a MAIL FROM command,
+		/// a RCPT TO command for every recipient, and a DATA command with
+		/// the message headers and content. Using this function results in
+		/// RCPT TO commands list generated from the recipient list supplied
+		/// with the message itself.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void sendMessage(const MailMessage& message, const Recipients& recipients);
+		/// Sends the given mail message by sending a MAIL FROM command,
+		/// a RCPT TO command for every recipient, and a DATA command with
+		/// the message headers and content. Using this function results in
+		/// message header being generated from the supplied recipients list.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void sendMessage(std::istream& istr);
+		/// Sends the mail message from the supplied stream. Content of the stream
+		/// is copied without any checking. Only the completion status is checked and,
+		/// if not valid, SMTPExcpetion is thrown.
+
+	int sendCommand(const std::string& command, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	int sendCommand(const std::string& command, const std::string& arg, std::string& response);
+		/// Sends the given command verbatim to the server
+		/// and waits for a response.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void sendAddresses(const std::string& from, const Recipients& recipients);
+		/// Sends the message preamble by sending a MAIL FROM command,
+		/// and a RCPT TO command for every recipient.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+	void sendData();
+		/// Sends the message preamble by sending a DATA command.
+		///
+		/// Throws a SMTPException in case of a SMTP-specific error, or a
+		/// NetException in case of a general network communication failure.
+
+protected:
+	enum StatusClass
+	{
+		SMTP_POSITIVE_COMPLETION   = 2,
+		SMTP_POSITIVE_INTERMEDIATE = 3,
+		SMTP_TRANSIENT_NEGATIVE    = 4,
+		SMTP_PERMANENT_NEGATIVE    = 5
+	};
+	enum
+	{
+		DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations	
+	};
+
+	static bool isPositiveCompletion(int status);
+	static bool isPositiveIntermediate(int status);
+	static bool isTransientNegative(int status);
+	static bool isPermanentNegative(int status);
+
+	void login(const std::string& hostname, std::string& response);
+	void loginUsingCRAMMD5(const std::string& username, const std::string& password);
+	void loginUsingCRAMSHA1(const std::string& username, const std::string& password);
+	void loginUsingCRAM(const std::string& username, const std::string& method, Poco::DigestEngine& hmac);
+	void loginUsingLogin(const std::string& username, const std::string& password);
+	void loginUsingPlain(const std::string& username, const std::string& password);
+	void loginUsingXOAUTH2(const std::string& username, const std::string& password);
+	DialogSocket& socket();
+
+private:
+	void sendCommands(const MailMessage& message, const Recipients* pRecipients = 0);
+	void transportMessage(const MailMessage& message);
+
+	DialogSocket _socket;
+	bool         _isOpen;
+};
+
+
+//
+// inlines
+//
+inline bool SMTPClientSession::isPositiveCompletion(int status)
+{
+	return status/100 == SMTP_POSITIVE_COMPLETION;
+}
+
+
+inline bool SMTPClientSession::isPositiveIntermediate(int status)
+{
+	return status/100 == SMTP_POSITIVE_INTERMEDIATE;
+}
+
+
+inline bool SMTPClientSession::isTransientNegative(int status)
+{
+	return status/100 == SMTP_TRANSIENT_NEGATIVE;
+}
+
+
+inline bool SMTPClientSession::isPermanentNegative(int status)
+{
+	return status/100 == SMTP_PERMANENT_NEGATIVE;
+}
+
+
+inline DialogSocket& SMTPClientSession::socket()
+{
+	return _socket;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SMTPClientSession_INCLUDED
diff --git a/Poco/Net/SSLException.h b/Poco/Net/SSLException.h
new file mode 100644
index 0000000..7b8dfe7
--- /dev/null
+++ b/Poco/Net/SSLException.h
@@ -0,0 +1,39 @@
+//
+// SSLException.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  SSLException
+//
+// Definition of the SSLException class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SSLException_INCLUDED
+#define NetSSL_SSLException_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/NetException.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+POCO_DECLARE_EXCEPTION(NetSSL_API, SSLException, NetException)
+POCO_DECLARE_EXCEPTION(NetSSL_API, SSLContextException, SSLException)
+POCO_DECLARE_EXCEPTION(NetSSL_API, InvalidCertificateException, SSLException)
+POCO_DECLARE_EXCEPTION(NetSSL_API, CertificateValidationException, SSLException)
+POCO_DECLARE_EXCEPTION(NetSSL_API, SSLConnectionUnexpectedlyClosedException, SSLException)
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SSLException_INCLUDED
diff --git a/Poco/Net/SSLManager.h b/Poco/Net/SSLManager.h
new file mode 100644
index 0000000..6d0f469
--- /dev/null
+++ b/Poco/Net/SSLManager.h
@@ -0,0 +1,390 @@
+//
+// SSLManager.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  SSLManager
+//
+// Definition of the SSLManager class.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SSLManager_INCLUDED
+#define NetSSL_SSLManager_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/VerificationErrorArgs.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Net/PrivateKeyFactoryMgr.h"
+#include "Poco/Net/CertificateHandlerFactoryMgr.h"
+#include "Poco/Net/InvalidCertificateHandler.h"
+#include "Poco/Util/AbstractConfiguration.h"
+#include "Poco/BasicEvent.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Mutex.h"
+#include <openssl/ssl.h>
+#if defined(OPENSSL_FIPS) && OPENSSL_VERSION_NUMBER < 0x010001000L
+#include <openssl/fips.h>
+#endif
+
+
+namespace Poco {
+namespace Net {
+
+
+class Context;
+
+
+class NetSSL_API SSLManager
+	/// SSLManager is a singleton for holding the default server/client
+	/// Context and handling callbacks for certificate verification errors
+	/// and private key passphrases.
+	///
+	/// Proper initialization of SSLManager is critical.
+	///
+	/// SSLManager can be initialized manually, by calling initializeServer()
+	/// and/or initializeClient(), or initialization can be automatic. In the latter
+	/// case, a Poco::Util::Application instance must be available and the required
+	/// configuration properties must be set (see below).
+	///
+	/// Note that manual initialization must happen very early in the application,
+	/// before defaultClientContext() or defaultServerContext() are called.
+	///
+	/// If defaultClientContext() and defaultServerContext() are never called
+	/// in an application, initialization of SSLManager can be omitted.
+	/// However, in this case, delegates for the ServerVerificationError,
+	/// ClientVerificationError and PrivateKeyPassphraseRequired events
+	/// must be registered.
+	///
+	/// An exemplary documentation which sets either the server or client default context and creates
+	/// a PrivateKeyPassphraseHandler that reads the password from the XML file looks like this:
+	///
+	///    <AppConfig>
+	///       <openSSL>
+	///          <server|client>
+	///            <privateKeyFile>mycert.key</privateKeyFile>
+	///            <certificateFile>mycert.crt</certificateFile>
+	///            <caConfig>rootcert.pem</caConfig>
+	///            <verificationMode>none|relaxed|strict|once</verificationMode>
+	///            <verificationDepth>1..9</verificationDepth>
+	///            <loadDefaultCAFile>true|false</loadDefaultCAFile>
+	///            <cipherList>ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH</cipherList>
+	///            <preferServerCiphers>true|false</preferServerCiphers>
+	///            <privateKeyPassphraseHandler>
+	///                <name>KeyFileHandler</name>
+	///                <options>
+	///                    <password>test</password>
+	///                </options>
+	///            </privateKeyPassphraseHandler>
+	///            <invalidCertificateHandler>
+	///                 <name>ConsoleCertificateHandler</name>
+	///            </invalidCertificateHandler>
+	///            <cacheSessions>true|false</cacheSessions>
+	///            <sessionIdContext>someString</sessionIdContext> <!-- server only -->
+	///            <sessionCacheSize>0..n</sessionCacheSize>       <!-- server only -->
+	///            <sessionTimeout>0..n</sessionTimeout>           <!-- server only -->
+	///            <extendedVerification>true|false</extendedVerification>
+	///            <requireTLSv1>true|false</requireTLSv1>
+	///            <requireTLSv1_1>true|false</requireTLSv1_1>
+	///            <requireTLSv1_2>true|false</requireTLSv1_2>
+	///            <disableProtocols>sslv2,sslv3,tlsv1,tlsv1_1,tlsv1_2</disableProtocols>
+	///            <dhParamsFile>dh.pem</dhParamsFile>
+	///            <ecdhCurve>prime256v1</ecdhCurve>
+	///          </server|client>
+	///          <fips>false</fips>
+	///       </openSSL>
+	///    </AppConfig>
+	///
+	/// Following is a list of supported configuration properties. Property names must always
+	/// be prefixed with openSSL.server or openSSL.client. Some properties are only supported
+	/// for servers.
+	///
+	///    - privateKeyFile (string): The path to the file containing the private key for the certificate
+	///      in PEM format (or containing both the private key and the certificate).
+	///    - certificateFile (string): The Path to the file containing the server's or client's certificate
+	///      in PEM format. Can be omitted if the the file given in privateKeyFile contains the certificate as well.
+	///    - caConfig (string): The path to the file or directory containing the trusted root certificates.
+	///    - verificationMode (string): Specifies whether and how peer certificates are validated (see
+	///      the Context class for details). Valid values are none, relaxed, strict, once.
+	///    - verificationDepth (integer, 1-9): Sets the upper limit for verification chain sizes. Verification
+	///      will fail if a certificate chain larger than this is encountered.
+	///    - loadDefaultCAFile (boolean): Specifies whether the builtin CA certificates from OpenSSL are used.
+	///    - cipherList (string): Specifies the supported ciphers in OpenSSL notation
+	///      (e.g. "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH").
+	///    - preferServerCiphers (bool): When choosing a cipher, use the server's preferences instead of the
+	///      client preferences. When not called, the SSL server will always follow the clients
+	///      preferences. When called, the SSL/TLS server will choose following its own
+	///      preferences.
+	///    - privateKeyPassphraseHandler.name (string): The name of the class (subclass of PrivateKeyPassphraseHandler)
+	///      used for obtaining the passphrase for accessing the private key.
+	///    - privateKeyPassphraseHandler.options.password (string): The password to be used by KeyFileHandler.
+	///    - invalidCertificateHandler.name: The name of the class (subclass of CertificateHandler)
+	///      used for confirming invalid certificates.
+	///    - cacheSessions (boolean): Enables or disables session caching.
+	///    - sessionIdContext (string): contains the application's unique session ID context, which becomes
+	///      part of each session identifier generated by the server. Can be an arbitrary sequence
+	///      of bytes with a maximum length of SSL_MAX_SSL_SESSION_ID_LENGTH. Should be specified
+	///      for a server to enable session caching. Should be specified even if session caching
+	///      is disabled to avoid problems with clients that request session caching (e.g. Firefox 3.6).
+	///      If not specified, defaults to ${application.name}.
+	///    - sessionCacheSize (integer): Sets the maximum size of the server session cache, in number of
+	///      sessions. The default size (according to OpenSSL documentation) is 1024*20, which may be too
+	///      large for many applications, especially on embedded platforms with limited memory.
+	///      Specifying a size of 0 will set an unlimited cache size.
+	///    - sessionTimeout (integer):  Sets the timeout (in seconds) of cached sessions on the server.
+	///    - extendedVerification (boolean): Enable or disable the automatic post-connection
+	///      extended certificate verification.
+	///    - requireTLSv1 (boolean): Require a TLSv1 connection.
+	///    - requireTLSv1_1 (boolean): Require a TLSv1.1 connection.
+	///    - requireTLSv1_2 (boolean): Require a TLSv1.2 connection.
+	///    - disableProtocols (string): A comma-separated list of protocols that should be
+	///      disabled. Valid protocol names are sslv2, sslv3, tlsv1, tlsv1_1, tlsv1_2.
+	///    - dhParamsFile (string): Specifies a file containing Diffie-Hellman parameters.
+	///      If not specified or empty, the default parameters are used.
+	///    - ecdhCurve (string): Specifies the name of the curve to use for ECDH, based
+	///      on the curve names specified in RFC 4492. Defaults to "prime256v1".
+	///    - fips: Enable or disable OpenSSL FIPS mode. Only supported if the OpenSSL version
+	///      that this library is built against supports FIPS mode.
+{
+public:
+	typedef Poco::SharedPtr<PrivateKeyPassphraseHandler> PrivateKeyPassphraseHandlerPtr;
+	typedef Poco::SharedPtr<InvalidCertificateHandler> InvalidCertificateHandlerPtr;
+
+	Poco::BasicEvent<VerificationErrorArgs> ServerVerificationError;
+		/// Fired whenever a certificate verification error is detected by the server during a handshake.
+
+	Poco::BasicEvent<VerificationErrorArgs> ClientVerificationError;
+		/// Fired whenever a certificate verification error is detected by the client during a handshake.
+
+	Poco::BasicEvent<std::string> PrivateKeyPassphraseRequired;
+		/// Fired when a encrypted certificate is loaded. Not setting the password
+		/// in the event parameter will result in a failure to load the certificate.
+
+	static SSLManager& instance();
+		/// Returns the instance of the SSLManager singleton.
+
+	void initializeServer(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr ptrCertificateHandler, Context::Ptr ptrContext);
+		/// Initializes the server side of the SSLManager with a default passphrase handler, a default invalid certificate handler and a default context. If this method
+		/// is never called the SSLmanager will try to initialize its members from an application configuration.
+		///
+		/// PtrPassphraseHandler and ptrCertificateHandler can be 0. However, in this case, event delegates
+		/// must be registered with the ServerVerificationError and PrivateKeyPassphraseRequired events.
+		///
+		/// Note: Always create the handlers (or register the corresponding event delegates) before creating
+		/// the Context, as during creation of the Context the passphrase for the private key might be needed.
+		///
+		/// Valid initialization code would be:
+		///     SharedPtr<PrivateKeyPassphraseHandler> pConsoleHandler = new KeyConsoleHandler;
+		///     SharedPtr<InvalidCertificateHandler> pInvalidCertHandler = new ConsoleCertificateHandler;
+		///     Context::Ptr pContext = new Context(Context::SERVER_USE, "any.pem", "any.pem", "rootcert.pem", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+		///     SSLManager::instance().initializeServer(pConsoleHandler, pInvalidCertHandler, pContext);
+
+	void initializeClient(PrivateKeyPassphraseHandlerPtr ptrPassphraseHandler, InvalidCertificateHandlerPtr ptrHandler, Context::Ptr ptrContext);
+		/// Initializes the client side of the SSLManager with a default passphrase handler, a default invalid certificate handler and a default context. If this method
+		/// is never called the SSLmanager will try to initialize its members from an application configuration.
+		///
+		/// PtrPassphraseHandler and ptrCertificateHandler can be 0. However, in this case, event delegates
+		/// must be registered with the ClientVerificationError and PrivateKeyPassphraseRequired events.
+		///
+		/// Note: Always create the handlers (or register the corresponding event delegates) before creating
+		/// the Context, as during creation of the Context the passphrase for the private key might be needed.
+		///
+		/// Valid initialization code would be:
+		///     SharedPtr<PrivateKeyPassphraseHandler> pConsoleHandler = new KeyConsoleHandler;
+		///     SharedPtr<InvalidCertificateHandler> pInvalidCertHandler = new ConsoleCertificateHandler;
+		///     Context::Ptr pContext = new Context(Context::CLIENT_USE, "", "", "rootcert.pem", Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+		///     SSLManager::instance().initializeClient(pConsoleHandler, pInvalidCertHandler, pContext);
+
+	Context::Ptr defaultServerContext();
+		/// Returns the default Context used by the server.
+		///
+		/// Unless initializeServer() has been called, the first call to this method initializes the default Context
+		/// from the application configuration.
+
+	Context::Ptr defaultClientContext();
+		/// Returns the default Context used by the client.
+		///
+		/// Unless initializeClient() has been called, the first call to this method initializes the default Context
+		/// from the application configuration.
+
+	PrivateKeyPassphraseHandlerPtr serverPassphraseHandler();
+		/// Returns the configured passphrase handler of the server. If none is set, the method will create a default one
+		/// from an application configuration.
+
+	InvalidCertificateHandlerPtr serverCertificateHandler();
+		/// Returns an initialized certificate handler (used by the server to verify client cert) which determines how invalid certificates are treated.
+		/// If none is set, it will try to auto-initialize one from an application configuration.
+
+	PrivateKeyPassphraseHandlerPtr clientPassphraseHandler();
+		/// Returns the configured passphrase handler of the client. If none is set, the method will create a default one
+		/// from an application configuration.
+
+	InvalidCertificateHandlerPtr clientCertificateHandler();
+		/// Returns an initialized certificate handler (used by the client to verify server cert) which determines how invalid certificates are treated.
+		/// If none is set, it will try to auto-initialize one from an application configuration.
+
+	PrivateKeyFactoryMgr& privateKeyFactoryMgr();
+		/// Returns the private key factory manager which stores the
+		/// factories for the different registered passphrase handlers for private keys.
+
+	CertificateHandlerFactoryMgr& certificateHandlerFactoryMgr();
+		/// Returns the CertificateHandlerFactoryMgr which stores the
+		/// factories for the different registered certificate handlers.
+
+	static bool isFIPSEnabled();
+		// Returns true if FIPS mode is enabled, false otherwise.
+
+	void shutdown();
+		/// Shuts down the SSLManager and releases the default Context
+		/// objects. After a call to shutdown(), the SSLManager can no
+		/// longer be used.
+		///
+		/// Normally, it's not necessary to call this method directly, as this
+		/// will be called either by uninitializeSSL(), or when
+		/// the SSLManager instance is destroyed.
+
+	static const std::string CFG_SERVER_PREFIX;
+	static const std::string CFG_CLIENT_PREFIX;
+
+protected:
+	static int verifyClientCallback(int ok, X509_STORE_CTX* pStore);
+		/// The return value of this method defines how errors in
+		/// verification are handled. Return 0 to terminate the handshake,
+		/// or 1 to continue despite the error.
+
+	static int verifyServerCallback(int ok, X509_STORE_CTX* pStore);
+		/// The return value of this method defines how errors in
+		/// verification are handled. Return 0 to terminate the handshake,
+		/// or 1 to continue despite the error.
+
+	static int privateKeyPassphraseCallback(char* pBuf, int size, int flag, void* userData);
+		/// Method is invoked by OpenSSL to retrieve a passwd for an encrypted certificate.
+		/// The request is delegated to the PrivatekeyPassword event. This method returns the
+		/// length of the password.
+
+	static Poco::Util::AbstractConfiguration& appConfig();
+		/// Returns the application configuration.
+		///
+		/// Throws a InvalidStateException if not application instance
+		/// is available.
+
+private:
+	SSLManager();
+		/// Creates the SSLManager.
+
+	~SSLManager();
+		/// Destroys the SSLManager.
+
+	void initDefaultContext(bool server);
+		/// Inits the default context, the first time it is accessed.
+
+	void initEvents(bool server);
+		/// Registers delegates at the events according to the configuration.
+
+	void initPassphraseHandler(bool server);
+		/// Inits the passphrase handler.
+
+	void initCertificateHandler(bool server);
+		/// Inits the certificate handler.
+
+	static int verifyCallback(bool server, int ok, X509_STORE_CTX* pStore);
+		/// The return value of this method defines how errors in
+		/// verification are handled. Return 0 to terminate the handshake,
+		/// or 1 to continue despite the error.
+
+	PrivateKeyFactoryMgr             _factoryMgr;
+	CertificateHandlerFactoryMgr     _certHandlerFactoryMgr;
+	Context::Ptr                     _ptrDefaultServerContext;
+	PrivateKeyPassphraseHandlerPtr   _ptrServerPassphraseHandler;
+	InvalidCertificateHandlerPtr     _ptrServerCertificateHandler;
+	Context::Ptr                     _ptrDefaultClientContext;
+	PrivateKeyPassphraseHandlerPtr   _ptrClientPassphraseHandler;
+	InvalidCertificateHandlerPtr     _ptrClientCertificateHandler;
+	Poco::FastMutex                  _mutex;
+
+	static const std::string CFG_PRIV_KEY_FILE;
+	static const std::string CFG_CERTIFICATE_FILE;
+	static const std::string CFG_CA_LOCATION;
+	static const std::string CFG_VER_MODE;
+	static const Context::VerificationMode VAL_VER_MODE;
+	static const std::string CFG_VER_DEPTH;
+	static const int         VAL_VER_DEPTH;
+	static const std::string CFG_ENABLE_DEFAULT_CA;
+	static const bool        VAL_ENABLE_DEFAULT_CA;
+	static const std::string CFG_CIPHER_LIST;
+	static const std::string CFG_CYPHER_LIST; // for backwards compatibility
+	static const std::string VAL_CIPHER_LIST;
+	static const std::string CFG_PREFER_SERVER_CIPHERS;
+	static const std::string CFG_DELEGATE_HANDLER;
+	static const std::string VAL_DELEGATE_HANDLER;
+	static const std::string CFG_CERTIFICATE_HANDLER;
+	static const std::string VAL_CERTIFICATE_HANDLER;
+	static const std::string CFG_CACHE_SESSIONS;
+	static const std::string CFG_SESSION_ID_CONTEXT;
+	static const std::string CFG_SESSION_CACHE_SIZE;
+	static const std::string CFG_SESSION_TIMEOUT;
+	static const std::string CFG_EXTENDED_VERIFICATION;
+	static const std::string CFG_REQUIRE_TLSV1;
+	static const std::string CFG_REQUIRE_TLSV1_1;
+	static const std::string CFG_REQUIRE_TLSV1_2;
+	static const std::string CFG_DISABLE_PROTOCOLS;
+	static const std::string CFG_DH_PARAMS_FILE;
+	static const std::string CFG_ECDH_CURVE;
+
+#ifdef OPENSSL_FIPS
+	static const std::string CFG_FIPS_MODE;
+	static const bool        VAL_FIPS_MODE;
+#endif
+
+	friend class Poco::SingletonHolder<SSLManager>;
+	friend class Context;
+};
+
+
+//
+// inlines
+//
+inline PrivateKeyFactoryMgr& SSLManager::privateKeyFactoryMgr()
+{
+	return _factoryMgr;
+}
+
+
+inline CertificateHandlerFactoryMgr& SSLManager::certificateHandlerFactoryMgr()
+{
+	return _certHandlerFactoryMgr;
+}
+
+
+inline bool SSLManager::isFIPSEnabled()
+{
+#ifdef OPENSSL_FIPS
+	return FIPS_mode() ? true : false;
+#else
+	return false;
+#endif
+}
+
+
+inline int SSLManager::verifyServerCallback(int ok, X509_STORE_CTX* pStore)
+{
+	return SSLManager::verifyCallback(true, ok, pStore);
+}
+
+
+inline int SSLManager::verifyClientCallback(int ok, X509_STORE_CTX* pStore)
+{
+	return SSLManager::verifyCallback(false, ok, pStore);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SSLManager_INCLUDED
diff --git a/Poco/Net/SecureSMTPClientSession.h b/Poco/Net/SecureSMTPClientSession.h
new file mode 100644
index 0000000..146be2a
--- /dev/null
+++ b/Poco/Net/SecureSMTPClientSession.h
@@ -0,0 +1,96 @@
+//
+// SecureSMTPClientSession.h
+//
+// Library: NetSSL_OpenSSL
+// Package: Mail
+// Module:  SecureSMTPClientSession
+//
+// Definition of the SecureSMTPClientSession class.
+//
+// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SecureSMTPClientSession_INCLUDED
+#define Net_SecureSMTPClientSession_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/SMTPClientSession.h"
+#include "Poco/Net/Context.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API SecureSMTPClientSession: public SMTPClientSession
+	/// This class implements an Simple Mail
+	/// Transfer Protocol (SMTP, RFC 2821)
+	/// client for sending e-mail messages that
+	/// supports the STARTTLS command for secure
+	/// connections.
+	///
+	/// Usage is as follows:
+	///   1. Create a SecureSMTPClientSession object.
+	///   2. Call login() or login(hostname).
+	///   3. Call startTLS() to switch to a secure connection.
+	///      Check the return value to see if a secure connection
+	///      has actually been established (not all servers may
+	///      support STARTTLS).
+	///   4. Call any of the login() methods to securely authenticate
+	///      with a username and password.
+	///   5. Send the message(s).
+{
+public:
+	explicit SecureSMTPClientSession(const StreamSocket& socket);
+		/// Creates the SecureSMTPClientSession using
+		/// the given socket, which must be connected
+		/// to a SMTP server.
+
+	SecureSMTPClientSession(const std::string& host, Poco::UInt16 port = SMTP_PORT);
+		/// Creates the SecureSMTPClientSession using a socket connected
+		/// to the given host and port.
+
+	virtual ~SecureSMTPClientSession();
+		/// Destroys the SMTPClientSession.
+
+	bool startTLS();
+		/// Sends a STARTTLS command and, if successful, 
+		/// creates a secure SSL/TLS connection over the
+		/// existing socket connection.
+		///
+		/// Must be called after login() or login(hostname).
+		/// If successful, login() can be called again
+		/// to authenticate the user.
+		///
+		/// Returns true if the STARTTLS command was successful,
+		/// false otherwise.
+
+	bool startTLS(Context::Ptr pContext);
+		/// Sends a STARTTLS command and, if successful, 
+		/// creates a secure SSL/TLS connection over the
+		/// existing socket connection.
+		///
+		/// Uses the given Context object for creating
+		/// the SSL/TLS connection.
+		///
+		/// Must be called after login() or login(hostname).
+		/// If successful, login() can be called again
+		/// to authenticate the user.
+		///
+		/// Returns true if the STARTTLS command was successful,
+		/// false otherwise.
+		
+private:
+	std::string _host;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SecureSMTPClientSession_INCLUDED
diff --git a/Poco/Net/SecureServerSocket.h b/Poco/Net/SecureServerSocket.h
new file mode 100644
index 0000000..2b89c45
--- /dev/null
+++ b/Poco/Net/SecureServerSocket.h
@@ -0,0 +1,136 @@
+//
+// SecureServerSocket.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLSockets
+// Module:  SecureServerSocket
+//
+// Definition of the SecureServerSocket class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SecureServerSocket_INCLUDED
+#define NetSSL_SecureServerSocket_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Net/Context.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API SecureServerSocket: public ServerSocket
+	/// A server socket for secure SSL connections.
+{
+public:
+	SecureServerSocket();
+		/// Creates a SSL server socket using the
+		/// default SSL server context.
+		///
+		/// The server socket must be bound to
+		/// an address and put into listening state.
+
+	explicit SecureServerSocket(Context::Ptr pContext);
+		/// Creates a SSL server socket, using the
+		/// given SSL context object.
+		///
+		/// The server socket must be bound to
+		/// an address and put into listening state.
+
+	SecureServerSocket(const Socket& socket);
+		/// Creates the SecureServerSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a SecureServerSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	SecureServerSocket(const SocketAddress& address, int backlog = 64);
+		/// Creates a server socket using the default server SSL context,
+		/// binds it to the given address and puts it in listening
+		/// state.
+		///
+		/// After successful construction, the server socket
+		/// is ready to accept connections.
+
+	SecureServerSocket(const SocketAddress& address, int backlog, Context::Ptr pContext);
+		/// Creates a server socket using the given SSL context, binds it
+		/// to the given address and puts it in listening
+		/// state.
+		///
+		/// After successful construction, the server socket
+		/// is ready to accept connections.
+
+	SecureServerSocket(Poco::UInt16 port, int backlog = 64);
+		/// Creates a server socket using the default server SSL context,
+		/// binds it to the given port and puts it in listening
+		/// state.
+		///
+		/// After successful construction, the server socket
+		/// is ready to accept connections.
+
+	SecureServerSocket(Poco::UInt16 port, int backlog, Context::Ptr pContext);
+		/// Creates a server socket using the given SSL context, binds it
+		/// to the given port and puts it in listening
+		/// state.
+		///
+		/// After successful construction, the server socket
+		/// is ready to accept connections.
+
+	virtual ~SecureServerSocket();
+		/// Destroys the StreamSocket.
+
+	SecureServerSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	StreamSocket acceptConnection(SocketAddress& clientAddr);
+		/// Get the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new SSL socket for the connection
+		/// with the client.
+		///
+		/// The client socket's address is returned in clientAddr.
+		///
+		/// No SSL handshake is performed on the new connection.
+		/// The SSL handshake will be performed the first time
+		/// sendBytes(), receiveBytes() or completeHandshake()
+		/// is called on the returned SecureStreamSocket.
+
+	StreamSocket acceptConnection();
+		/// Get the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new SSL socket for the connection
+		/// with the client.
+		///
+		/// No SSL handshake is performed on the new connection.
+		/// The SSL handshake will be performed the first time
+		/// sendBytes(), receiveBytes() or completeHandshake()
+		/// is called on the returned SecureStreamSocket.
+
+	Context::Ptr context() const;
+		/// Returns the SSL context used by this socket.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SecureServerSocket_INCLUDED
diff --git a/Poco/Net/SecureServerSocketImpl.h b/Poco/Net/SecureServerSocketImpl.h
new file mode 100644
index 0000000..c78cbac
--- /dev/null
+++ b/Poco/Net/SecureServerSocketImpl.h
@@ -0,0 +1,146 @@
+//
+// SecureServerSocketImpl.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLSockets
+// Module:  SecureServerSocketImpl
+//
+// Definition of the SecureServerSocketImpl class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SecureServerSocketImpl_INCLUDED
+#define NetSSL_SecureServerSocketImpl_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/SecureSocketImpl.h"
+#include "Poco/Net/ServerSocketImpl.h"
+#include "Poco/Net/Context.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API SecureServerSocketImpl: public ServerSocketImpl
+	/// The SocketImpl class for SecureServerSocket.
+{
+public:
+	SecureServerSocketImpl(Context::Ptr pContext);
+		/// Creates the SecureServerSocketImpl using the
+		/// given SSL context object.
+
+	SocketImpl* acceptConnection(SocketAddress& clientAddr);
+		/// Get the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new TCP socket for the connection
+		/// with the client.
+		///
+		/// The client socket's address is returned in clientAddr.
+	
+	void connect(const SocketAddress& address);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+
+	void connect(const SocketAddress& address, const Poco::Timespan& timeout);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+
+	void connectNB(const SocketAddress& address);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		
+	void listen(int backlog = 64);
+		/// Puts the socket into listening state.
+		///
+		/// The socket becomes a passive socket that
+		/// can accept incoming connection requests.
+		///
+		/// The backlog argument specifies the maximum
+		/// number of connections that can be queued
+		/// for this socket.
+
+	void close();
+		/// Close the socket.
+	
+	int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	void sendUrgent(unsigned char data);
+		/// Not supported by this kind of socket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+
+	bool secure() const;
+		/// Returns true iff the socket's connection is secure
+		/// (using SSL or TLS).
+		
+	Context::Ptr context() const;
+		/// Returns the SSL context used by this socket.
+
+protected:
+	~SecureServerSocketImpl();
+		/// Destroys the SecureServerSocketImpl.
+
+private:
+	SecureServerSocketImpl(const SecureServerSocketImpl&);
+	SecureServerSocketImpl& operator = (const SecureServerSocketImpl&);
+
+private:
+	SecureSocketImpl _impl;
+};
+
+
+//
+// inlines
+//
+inline Context::Ptr SecureServerSocketImpl::context() const
+{
+	return _impl.context();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SecureServerSocketImpl_INCLUDED
diff --git a/Poco/Net/SecureSocketImpl.h b/Poco/Net/SecureSocketImpl.h
new file mode 100644
index 0000000..853bf8b
--- /dev/null
+++ b/Poco/Net/SecureSocketImpl.h
@@ -0,0 +1,263 @@
+//
+// SecureSocketImpl.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLSockets
+// Module:  SecureSocketImpl
+//
+// Definition of the SecureSocketImpl class.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SecureSocketImpl_INCLUDED
+#define NetSSL_SecureSocketImpl_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/SocketImpl.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Net/X509Certificate.h"
+#include "Poco/Net/Session.h"
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HostEntry;
+
+
+class NetSSL_API SecureSocketImpl
+	/// The SocketImpl for SecureStreamSocket.
+{
+public:
+	SecureSocketImpl(Poco::AutoPtr<SocketImpl> pSocketImpl, Context::Ptr pContext);
+		/// Creates the SecureSocketImpl using an already
+		/// connected stream socket.
+
+	virtual ~SecureSocketImpl();
+		/// Destroys the SecureSocketImpl.
+
+	SocketImpl* acceptConnection(SocketAddress& clientAddr);
+		/// Get the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new SSL socket for the connection
+		/// with the client.
+		///
+		/// The client socket's address is returned in clientAddr.
+	
+	void connect(const SocketAddress& address, bool performHandshake);
+		/// Initializes the socket and establishes a secure connection to 
+		/// the TCP server at the given address.
+		///
+		/// If performHandshake is true, the SSL handshake is performed immediately 
+		/// after establishing the connection. Otherwise, the handshake is performed
+		/// the first time sendBytes(), receiveBytes() or completeHandshake() is called.
+
+	void connect(const SocketAddress& address, const Poco::Timespan& timeout, bool performHandshake);
+		/// Initializes the socket, sets the socket timeout and 
+		/// establishes a secure connection to the TCP server at the given address.
+		///
+		/// If performHandshake is true, the SSL handshake is performed immediately 
+		/// after establishing the connection. Otherwise, the handshake is performed
+		/// the first time sendBytes(), receiveBytes() or completeHandshake() is called.
+
+	void connectNB(const SocketAddress& address);
+		/// Initializes the socket and establishes a secure connection to 
+		/// the TCP server at the given address. Prior to opening the
+		/// connection the socket is set to nonblocking mode.
+
+	void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. SSL clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		
+	void listen(int backlog = 64);
+		/// Puts the socket into listening state.
+		///
+		/// The socket becomes a passive socket that
+		/// can accept incoming connection requests.
+		///
+		/// The backlog argument specifies the maximum
+		/// number of connections that can be queued
+		/// for this socket.
+
+	void shutdown();
+		/// Shuts down the connection by attempting
+		/// an orderly SSL shutdown, then actually
+		/// shutting down the TCP connection.
+
+	void close();
+		/// Close the socket.
+		
+	void abort();
+		/// Aborts the connection by closing the
+		/// underlying TCP connection. No orderly SSL shutdown
+		/// is performed.
+	
+	int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket. Any specified flags are ignored.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+	
+	int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		///
+		/// Returns the number of bytes received.
+		
+	int available() const;
+		/// Returns the number of bytes available from the
+		/// SSL buffer for immediate reading.
+	
+	int completeHandshake();
+		/// Completes the SSL handshake.
+		///
+		/// If the SSL connection was the result of an accept(),
+		/// the server-side handshake is completed, otherwise
+		/// a client-side handshake is performed. 
+		
+	poco_socket_t sockfd();
+		/// Returns the underlying socket descriptor.
+
+	X509* peerCertificate() const;
+		/// Returns the peer's certificate.
+		
+	Context::Ptr context() const;
+		/// Returns the SSL context used for this socket.
+
+	void verifyPeerCertificate();
+		/// Performs post-connect (or post-accept) peer certificate validation,
+		/// using the peer host name set with setPeerHostName(), or the peer's
+		/// IP address string if no peer host name has been set.
+
+	void verifyPeerCertificate(const std::string& hostName);
+		/// Performs post-connect (or post-accept) peer certificate validation
+		/// using the given peer host name.
+
+	void setPeerHostName(const std::string& hostName);
+		/// Sets the peer host name for certificate validation purposes.
+		
+	const std::string& getPeerHostName() const;
+		/// Returns the peer host name.
+		
+	Session::Ptr currentSession();
+		/// Returns the SSL session of the current connection,
+		/// for reuse in a future connection (if session caching
+		/// is enabled).
+		///
+		/// If no connection is established, returns null.
+		
+	void useSession(Session::Ptr pSession);
+		/// Sets the SSL session to use for the next
+		/// connection. Setting a previously saved Session
+		/// object is necessary to enable session caching.
+		///
+		/// To remove the currently set session, a null pointer
+		/// can be given.
+		///
+		/// Must be called before connect() to be effective.
+		
+	bool sessionWasReused();
+		/// Returns true iff a reused session was negotiated during
+		/// the handshake.
+		
+protected:
+	void acceptSSL();
+		/// Performs a server-side SSL handshake and certificate verification.
+
+	void connectSSL(bool performHandshake);
+		/// Performs a client-side SSL handshake and establishes a secure 
+		/// connection over an already existing TCP connection.
+	
+	long verifyPeerCertificateImpl(const std::string& hostName);
+		/// Performs post-connect (or post-accept) peer certificate validation.
+		
+	static bool isLocalHost(const std::string& hostName);
+		/// Returns true iff the given host name is the local host 
+		/// (either "localhost" or "127.0.0.1").
+
+	bool mustRetry(int rc);
+		/// Returns true if the last operation should be retried,
+		/// otherwise false.
+		///
+		/// In case of an SSL_ERROR_WANT_READ error, and if the socket is 
+		/// blocking, waits for the underlying socket to become readable.
+		///
+		/// In case of an SSL_ERROR_WANT_WRITE error, and if the socket is
+		/// blocking, waits for the underlying socket to become writable.
+		///
+		/// Can also throw a Poco::TimeoutException if the socket does
+		/// not become readable or writable within the sockets
+		/// receive or send timeout.
+
+	int handleError(int rc);
+		/// Handles an SSL error by throwing an appropriate exception.
+
+	void reset();
+		/// Prepares the socket for re-use. 
+		///
+		/// After closing and resetting a socket, the socket can
+		/// be used for a new connection.
+		///
+		/// Note that simply closing a socket is not sufficient
+		/// to be able to re-use it again.
+
+private:	
+	SecureSocketImpl(const SecureSocketImpl&);
+	SecureSocketImpl& operator = (const SecureSocketImpl&);
+
+	SSL* _pSSL;
+	Poco::AutoPtr<SocketImpl> _pSocket;
+	Context::Ptr _pContext;
+	bool _needHandshake;
+	std::string _peerHostName;
+	Session::Ptr _pSession;
+	
+	friend class SecureStreamSocketImpl;
+};
+
+
+//
+// inlines
+//
+inline poco_socket_t SecureSocketImpl::sockfd()
+{
+	return _pSocket->sockfd();
+}
+
+
+inline Context::Ptr SecureSocketImpl::context() const
+{
+	return _pContext;
+}
+
+
+inline const std::string& SecureSocketImpl::getPeerHostName() const
+{
+	return _peerHostName;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SecureSocketImpl_INCLUDED
diff --git a/Poco/Net/SecureStreamSocket.h b/Poco/Net/SecureStreamSocket.h
new file mode 100644
index 0000000..059be1b
--- /dev/null
+++ b/Poco/Net/SecureStreamSocket.h
@@ -0,0 +1,272 @@
+//
+// SecureStreamSocket.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLSockets
+// Module:  SecureStreamSocket
+//
+// Definition of the SecureStreamSocket class.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SecureStreamSocket_INCLUDED
+#define NetSSL_SecureStreamSocket_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Net/Session.h"
+#include "Poco/Net/X509Certificate.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API SecureStreamSocket: public StreamSocket
+	/// A subclass of StreamSocket for secure SSL sockets.
+	///
+	/// A few notes about nonblocking IO:
+	/// sendBytes() and receiveBytes() can return a
+	/// negative value when using a nonblocking socket, which means 
+	/// a SSL handshake is currently in progress and more data
+	/// needs to be read or written for the handshake to continue.
+	/// If sendBytes() or receiveBytes() return ERR_SSL_WANT_WRITE,
+	/// sendBytes() must be called as soon as possible (usually, after
+	/// select() indicates that data can be written). Likewise, if
+	/// ERR_SSL_WANT_READ is returned, receiveBytes() must be called
+	/// as soon as data is available for reading (indicated by select()).
+	///
+	/// The SSL handshake is delayed until the first sendBytes() or 
+	/// receiveBytes() operation is performed on the socket. No automatic
+	/// post connection check (checking the peer certificate for a valid
+	/// hostname) is performed when using nonblocking I/O. To manually
+	/// perform peer certificate validation, call verifyPeerCertificate()
+	/// after the SSL handshake has been completed.
+{
+public:
+	enum
+	{
+		ERR_SSL_WANT_READ  = -1,
+		ERR_SSL_WANT_WRITE = -2
+	};
+	
+	SecureStreamSocket();
+		/// Creates an unconnected secure stream socket
+		/// using the default client SSL context.
+		///
+		/// Before sending or receiving data, the socket
+		/// must be connected with a call to connect().
+
+	explicit SecureStreamSocket(Context::Ptr pContext);
+		/// Creates an unconnected secure stream socket
+		/// using the given SSL context.
+		///
+		/// Before sending or receiving data, the socket
+		/// must be connected with a call to connect().
+
+	SecureStreamSocket(Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates an unconnected secure stream socket
+		/// using the given SSL context.
+		///
+		/// Before sending or receiving data, the socket
+		/// must be connected with a call to connect().
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	explicit SecureStreamSocket(const SocketAddress& address);
+		/// Creates a secure stream socket using the default 
+		/// client SSL context and connects it to
+		/// the socket specified by address.
+
+	SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext);
+		/// Creates a secure stream socket using the given 
+		/// client SSL context and connects it to
+		/// the socket specified by address.
+
+	SecureStreamSocket(const SocketAddress& address, Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates a secure stream socket using the given 
+		/// client SSL context and connects it to
+		/// the socket specified by address.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	SecureStreamSocket(const SocketAddress& address, const std::string& hostName);
+		/// Creates a secure stream socket using the default 
+		/// client SSL context and connects it to
+		/// the socket specified by address.
+		///
+		/// The given host name is used for certificate verification.
+
+	SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext);
+		/// Creates a secure stream socket using the given 
+		/// client SSL context and connects it to
+		/// the socket specified by address.
+		///
+		/// The given host name is used for certificate verification.
+
+	SecureStreamSocket(const SocketAddress& address, const std::string& hostName, Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates a secure stream socket using the given 
+		/// client SSL context and connects it to
+		/// the socket specified by address.
+		///
+		/// The given host name is used for certificate verification.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	SecureStreamSocket(const Socket& socket);
+		/// Creates the SecureStreamSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a SecureStreamSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	virtual ~SecureStreamSocket();
+		/// Destroys the StreamSocket.
+
+	SecureStreamSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+	
+	bool havePeerCertificate() const;
+		/// Returns true iff the peer has presented a
+		/// certificate.
+
+	X509Certificate peerCertificate() const;
+		/// Returns the peer's X509 certificate.
+		///
+		/// Throws a SSLException if the peer did not
+		/// present a certificate.
+		
+	void setPeerHostName(const std::string& hostName);
+		/// Sets the peer's host name used for certificate validation.
+		
+	const std::string& getPeerHostName() const;
+		/// Returns the peer's host name used for certificate validation.
+
+	static SecureStreamSocket attach(const StreamSocket& streamSocket);
+		/// Creates a SecureStreamSocket over an existing socket
+		/// connection. The given StreamSocket must be connected.
+		/// A SSL handshake will be performed.
+
+	static SecureStreamSocket attach(const StreamSocket& streamSocket, Context::Ptr pContext);
+		/// Creates a SecureStreamSocket over an existing socket
+		/// connection. The given StreamSocket must be connected.
+		/// A SSL handshake will be performed.
+
+	static SecureStreamSocket attach(const StreamSocket& streamSocket, Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates a SecureStreamSocket over an existing socket
+		/// connection. The given StreamSocket must be connected.
+		/// A SSL handshake will be performed.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName);
+		/// Creates a SecureStreamSocket over an existing socket
+		/// connection. The given StreamSocket must be connected.
+		/// A SSL handshake will be performed.
+
+	static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext);
+		/// Creates a SecureStreamSocket over an existing socket
+		/// connection. The given StreamSocket must be connected.
+		/// A SSL handshake will be performed.
+
+	static SecureStreamSocket attach(const StreamSocket& streamSocket, const std::string& peerHostName, Context::Ptr pContext, Session::Ptr pSession);
+		/// Creates a SecureStreamSocket over an existing socket
+		/// connection. The given StreamSocket must be connected.
+		/// A SSL handshake will be performed.
+		///
+		/// The given Session is reused, if possible (client session
+		/// caching is enabled for the given Context, and the server
+		/// agrees to reuse the session).
+
+	Context::Ptr context() const;
+		/// Returns the SSL context used by this socket.
+		
+	void setLazyHandshake(bool flag = true);
+		/// Enable lazy SSL handshake. If enabled, the SSL handshake
+		/// will be performed the first time date is sent or
+		/// received over the connection.
+		
+	bool getLazyHandshake() const;
+		/// Returns true if setLazyHandshake(true) has been called.
+		
+	void verifyPeerCertificate();
+		/// Performs post-connect (or post-accept) peer certificate validation,
+		/// using the peer host name set with setPeerHostName(), or the peer's
+		/// IP address string if no peer host name has been set.
+		///
+		/// Should only be used for non-blocking connections, after the
+		/// initial SSL handshake has been performed (see completeHandshake()).
+
+	void verifyPeerCertificate(const std::string& hostName);
+		/// Performs post-connect (or post-accept) peer certificate validation
+		/// using the given host name.
+		///
+		/// Should only be used for non-blocking connections, after the
+		/// initial SSL handshake has been performed (see completeHandshake()).
+		
+	int completeHandshake();
+		/// Completes the SSL handshake.
+		///
+		/// If the SSL connection was the result of an accept(),
+		/// the server-side handshake is completed, otherwise
+		/// a client-side handshake is performed.
+		///
+		/// Returns 1 if the handshake was successful, ERR_SSL_WANT_READ or
+		/// ERR_SSL_WANT_WRITE if more data is required to complete the
+		/// handshake. In this case, completeHandshake() should be called
+		/// again, after the necessary condition has been met.
+
+	Session::Ptr currentSession();
+		/// Returns the SSL session of the current connection,
+		/// for reuse in a future connection (if session caching
+		/// is enabled).
+		///
+		/// If no connection is established, returns null.
+		
+	void useSession(Session::Ptr pSession);
+		/// Sets the SSL session to use for the next
+		/// connection. Setting a previously saved Session
+		/// object is necessary to enable session caching.
+		///
+		/// To remove the currently set session, a null pointer
+		/// can be given.
+		///
+		/// Must be called before connect() to be effective.
+		
+	bool sessionWasReused();
+		/// Returns true iff a reused session was negotiated during
+		/// the handshake.
+		
+	void abort();
+		/// Aborts the SSL connection by closing the underlying
+		/// TCP connection. No orderly SSL shutdown is performed.
+		
+protected:
+	SecureStreamSocket(SocketImpl* pImpl);
+
+	friend class SecureServerSocket;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SecureStreamSocket_INCLUDED
diff --git a/Poco/Net/SecureStreamSocketImpl.h b/Poco/Net/SecureStreamSocketImpl.h
new file mode 100644
index 0000000..72fe6c9
--- /dev/null
+++ b/Poco/Net/SecureStreamSocketImpl.h
@@ -0,0 +1,299 @@
+//
+// SecureStreamSocketImpl.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLSockets
+// Module:  SecureStreamSocketImpl
+//
+// Definition of the SecureStreamSocketImpl class.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_SecureStreamSocketImpl_INCLUDED
+#define NetSSL_SecureStreamSocketImpl_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/SecureSocketImpl.h"
+#include "Poco/Net/StreamSocketImpl.h"
+#include "Poco/Net/Context.h"
+#include "Poco/Net/X509Certificate.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API SecureStreamSocketImpl: public StreamSocketImpl
+	/// This class implements a SSL stream socket.
+{
+public:
+	SecureStreamSocketImpl(Context::Ptr pContext);
+		/// Creates the SecureStreamSocketImpl.
+
+	SecureStreamSocketImpl(StreamSocketImpl* pStreamSocket, Context::Ptr pContext);
+		/// Creates the SecureStreamSocketImpl.
+
+	SocketImpl* acceptConnection(SocketAddress& clientAddr);
+		/// Not supported by a SecureStreamSocket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+
+	void connect(const SocketAddress& address);
+		/// Initializes the socket and establishes a connection to 
+		/// the TCP server at the given address.
+		///
+		/// Can also be used for UDP sockets. In this case, no
+		/// connection is established. Instead, incoming and outgoing
+		/// packets are restricted to the specified address.
+
+	void connect(const SocketAddress& address, const Poco::Timespan& timeout);
+		/// Initializes the socket, sets the socket timeout and 
+		/// establishes a connection to the TCP server at the given address.
+
+	void connectNB(const SocketAddress& address);
+		/// Initializes the socket and establishes a connection to 
+		/// the TCP server at the given address. Prior to opening the
+		/// connection the socket is set to nonblocking mode.
+		
+	void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Not supported by a SecureStreamSocket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+		
+	void listen(int backlog = 64);
+		/// Not supported by a SecureStreamSocket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+
+	void close();
+		/// Close the socket.
+	
+	int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket. Any specified flags are ignored.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+	
+	int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		///
+		/// Returns the number of bytes received.
+	
+	int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
+		/// Not supported by a SecureStreamSocket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
+		/// Not supported by a SecureStreamSocket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+	
+	void sendUrgent(unsigned char data);
+		/// Not supported by a SecureStreamSocket.
+		///
+		/// Throws a Poco::InvalidAccessException.
+
+	int available();
+		/// Returns the number of bytes available that can be read
+		/// without causing the socket to block.
+		///
+		/// For an SSL connection, returns the number of bytes that
+		/// can be read from the currently buffered SSL record,
+		/// before a new record is read from the underlying socket.
+
+	void shutdownReceive();
+		/// Shuts down the receiving part of the socket connection.
+		///
+		/// Since SSL does not support a half shutdown, this does
+		/// nothing.
+		
+	void shutdownSend();
+		/// Shuts down the receiving part of the socket connection.
+		///
+		/// Since SSL does not support a half shutdown, this does
+		/// nothing.
+		
+	void shutdown();
+		/// Shuts down the SSL connection.
+		
+	void abort();
+		/// Aborts the connection by closing the underlying
+		/// TCP connection. No orderly SSL shutdown is performed.
+		
+	bool secure() const;
+		/// Returns true iff the socket's connection is secure
+		/// (using SSL or TLS).
+
+	void setPeerHostName(const std::string& hostName);
+		/// Sets the peer host name for certificate validation purposes.
+		
+	const std::string& getPeerHostName() const;
+		/// Returns the peer host name.
+
+	bool havePeerCertificate() const;
+		/// Returns true iff the peer has presented a
+		/// certificate.
+
+	X509Certificate peerCertificate() const;
+		/// Returns the peer's X509 certificate.
+		///
+		/// Throws a SSLException if the peer did not
+		/// present a certificate.
+		
+	Context::Ptr context() const;
+		/// Returns the SSL context used by this socket.
+
+	void setLazyHandshake(bool flag = true);
+		/// Enable lazy SSL handshake. If enabled, the SSL handshake
+		/// will be performed the first time date is sent or
+		/// received over the connection.
+		
+	bool getLazyHandshake() const;
+		/// Returns true if setLazyHandshake(true) has been called.
+
+	void verifyPeerCertificate();
+		/// Performs post-connect (or post-accept) peer certificate validation,
+		/// using the peer's IP address as host name.
+
+	void verifyPeerCertificate(const std::string& hostName);
+		/// Performs post-connect (or post-accept) peer certificate validation
+		/// using the given host name.
+
+	int completeHandshake();
+		/// Completes the SSL handshake.
+		///
+		/// If the SSL connection was the result of an accept(),
+		/// the server-side handshake is completed, otherwise
+		/// a client-side handshake is performed. 
+
+	Session::Ptr currentSession();
+		/// Returns the SSL session of the current connection,
+		/// for reuse in a future connection (if session caching
+		/// is enabled).
+		///
+		/// If no connection is established, returns null.
+		
+	void useSession(Session::Ptr pSession);
+		/// Sets the SSL session to use for the next
+		/// connection. Setting a previously saved Session
+		/// object is necessary to enable session caching.
+		///
+		/// To remove the currently set session, a null pointer
+		/// can be given.
+		///
+		/// Must be called before connect() to be effective.
+		
+	bool sessionWasReused();
+		/// Returns true iff a reused session was negotiated during
+		/// the handshake.
+		
+protected:
+	void acceptSSL();
+		/// Performs a SSL server-side handshake.
+	
+	void connectSSL();
+		/// Performs a SSL client-side handshake on an already connected TCP socket.
+	
+	~SecureStreamSocketImpl();
+		/// Destroys the SecureStreamSocketImpl.
+
+	static int lastError();
+	static void error();
+	static void error(const std::string& arg);
+	static void error(int code);
+	static void error(int code, const std::string& arg);
+
+private:
+	SecureStreamSocketImpl(const SecureStreamSocketImpl&);
+	SecureStreamSocketImpl& operator = (const SecureStreamSocketImpl&);
+
+	SecureSocketImpl _impl;
+	bool             _lazyHandshake;
+
+	friend class SecureSocketImpl;
+	friend class SecureStreamSocket;
+};
+
+
+//
+// inlines
+//
+inline const std::string& SecureStreamSocketImpl::getPeerHostName() const
+{
+	return _impl.getPeerHostName();
+}
+
+
+inline void SecureStreamSocketImpl::setPeerHostName(const std::string& peerHostName)
+{
+	_impl.setPeerHostName(peerHostName);
+}
+
+
+inline Context::Ptr SecureStreamSocketImpl::context() const
+{
+	return _impl.context();
+}
+
+
+inline Session::Ptr SecureStreamSocketImpl::currentSession()
+{
+	return _impl.currentSession();
+}
+
+	
+inline void SecureStreamSocketImpl::useSession(Session::Ptr pSession)
+{
+	_impl.useSession(pSession);
+}
+
+	
+inline bool SecureStreamSocketImpl::sessionWasReused()
+{
+	return _impl.sessionWasReused();
+}
+
+
+inline int SecureStreamSocketImpl::lastError()
+{
+	return SocketImpl::lastError();
+}
+
+
+inline void SecureStreamSocketImpl::error()
+{
+	return SocketImpl::error();
+}
+
+
+inline void SecureStreamSocketImpl::error(const std::string& arg)
+{
+	return SocketImpl::error(arg);
+}
+
+
+inline void SecureStreamSocketImpl::error(int code)
+{
+	return SocketImpl::error(code);
+}
+
+
+inline void SecureStreamSocketImpl::error(int code, const std::string& arg)
+{
+	return SocketImpl::error(code, arg);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_SecureStreamSocketImpl_INCLUDED
diff --git a/Poco/Net/ServerSocket.h b/Poco/Net/ServerSocket.h
new file mode 100644
index 0000000..d8aca67
--- /dev/null
+++ b/Poco/Net/ServerSocket.h
@@ -0,0 +1,230 @@
+//
+// ServerSocket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  ServerSocket
+//
+// Definition of the ServerSocket class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ServerSocket_INCLUDED
+#define Net_ServerSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/Net/StreamSocket.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ServerSocket: public Socket
+	/// This class provides an interface to a
+	/// TCP server socket.
+{
+public:
+	ServerSocket();
+		/// Creates a server socket.
+		///
+		/// The server socket must be bound to
+		/// an address and put into listening state.
+
+	ServerSocket(const Socket& socket);
+		/// Creates the ServerSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a ServerSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	ServerSocket(const SocketAddress& address, int backlog = 64);
+		/// Creates a server socket, binds it
+		/// to the given address and puts it in listening
+		/// state.
+		///
+		/// After successful construction, the server socket
+		/// is ready to accept connections.
+
+	ServerSocket(Poco::UInt16 port, int backlog = 64);
+		/// Creates a server socket, binds it
+		/// to the given port and puts it in listening
+		/// state.
+		///
+		/// After successful construction, the server socket
+		/// is ready to accept connections.
+
+	virtual ~ServerSocket();
+		/// Destroys the StreamSocket.
+
+	ServerSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	virtual void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Binds a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+
+	virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
+		/// Binds a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEPORT
+		/// socket option.
+
+	virtual void bind(Poco::UInt16 port, bool reuseAddress = false);
+		/// Binds a local port to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+
+	virtual void bind(Poco::UInt16 port, bool reuseAddress, bool reusePort);
+		/// Binds a local port to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+        	///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+
+	virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
+		/// Binds a local IPv6 address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// The given address must be an IPv6 address. The
+		/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
+		/// according to the ipV6Only parameter.
+		///
+		/// If the library has not been built with IPv6 support,
+		/// a Poco::NotImplementedException will be thrown.
+
+	virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort,  bool ipV6Only);
+		/// Binds a local IPv6 address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+		///
+		/// The given address must be an IPv6 address. The
+		/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
+		/// according to the ipV6Only parameter.
+		///
+		/// If the library has not been built with IPv6 support,
+		/// a Poco::NotImplementedException will be thrown.
+
+	virtual void bind6(Poco::UInt16 port, bool reuseAddress = false, bool ipV6Only = false);
+		/// Binds a local IPv6 port to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// The given address must be an IPv6 address. The
+		/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
+		/// according to the ipV6Only parameter.
+		///
+		/// If the library has not been built with IPv6 support,
+		/// a Poco::NotImplementedException will be thrown.
+		
+	virtual void bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only);
+		/// Binds a local IPv6 port to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. 
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+		/// The given address must be an IPv6 address. The
+		/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
+		/// according to the ipV6Only parameter.
+		///
+		/// If the library has not been built with IPv6 support,
+		/// a Poco::NotImplementedException will be thrown.
+
+	virtual void listen(int backlog = 64);
+		/// Puts the socket into listening state.
+		///
+		/// The socket becomes a passive socket that
+		/// can accept incoming connection requests.
+		///
+		/// The backlog argument specifies the maximum
+		/// number of connections that can be queued
+		/// for this socket.
+
+	virtual StreamSocket acceptConnection(SocketAddress& clientAddr);
+		/// Gets the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new TCP socket for the connection
+		/// with the client.
+		///
+		/// The client socket's address is returned in clientAddr.
+
+	virtual StreamSocket acceptConnection();
+		/// Gets the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new TCP socket for the connection
+		/// with the client.
+
+protected:
+	ServerSocket(SocketImpl* pImpl, bool);
+		/// The bool argument is to resolve an ambiguity with
+		/// another constructor (Microsoft Visual C++ 2005)
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ServerSocket_INCLUDED
diff --git a/Poco/Net/ServerSocketImpl.h b/Poco/Net/ServerSocketImpl.h
new file mode 100644
index 0000000..aaa5c7c
--- /dev/null
+++ b/Poco/Net/ServerSocketImpl.h
@@ -0,0 +1,45 @@
+//
+// ServerSocketImpl.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  ServerSocketImpl
+//
+// Definition of the ServerSocketImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_ServerSocketImpl_INCLUDED
+#define Net_ServerSocketImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketImpl.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API ServerSocketImpl: public SocketImpl
+	/// This class implements a TCP server socket.
+{
+public:
+	ServerSocketImpl();
+		/// Creates the ServerSocketImpl.
+
+protected:
+	virtual ~ServerSocketImpl();
+		/// Destroys the ServerSocketImpl.
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ServerSocketImpl_INCLUDED
diff --git a/Poco/Net/Session.h b/Poco/Net/Session.h
new file mode 100644
index 0000000..cc9b2db
--- /dev/null
+++ b/Poco/Net/Session.h
@@ -0,0 +1,79 @@
+//
+// Session.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  Session
+//
+// Definition of the Session class.
+//
+// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_Session_INCLUDED
+#define NetSSL_Session_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <openssl/ssl.h>
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API Session: public Poco::RefCountedObject
+	/// This class encapsulates a SSL session object
+	/// used with session caching on the client side.
+	///
+	/// For session caching to work, a client must
+	/// save the session object from an existing connection,
+	/// if it wants to reuse it with a future connection.
+{
+public:
+	typedef Poco::AutoPtr<Session> Ptr;
+
+	SSL_SESSION* sslSession() const;
+		/// Returns the stored OpenSSL SSL_SESSION object.
+
+protected:	
+	Session(SSL_SESSION* pSession);
+		/// Creates a new Session object, using the given
+		/// SSL_SESSION object. 
+		/// 
+		/// The SSL_SESSION's reference count is not changed.
+
+	~Session();
+		/// Destroys the Session.
+		///
+		/// Calls SSL_SESSION_free() on the stored
+		/// SSL_SESSION object.
+
+private:
+	Session();
+
+	SSL_SESSION* _pSession;
+	
+	friend class SecureSocketImpl;
+};
+
+
+//
+// inlines
+//
+inline SSL_SESSION* Session::sslSession() const
+{
+	return _pSession;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_Session_INCLUDED
diff --git a/Poco/Net/Socket.h b/Poco/Net/Socket.h
new file mode 100644
index 0000000..c509187
--- /dev/null
+++ b/Poco/Net/Socket.h
@@ -0,0 +1,631 @@
+//
+// Socket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  Socket
+//
+// Definition of the Socket class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_Socket_INCLUDED
+#define Net_Socket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketImpl.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API Socket
+	/// Socket is the common base class for
+	/// StreamSocket, ServerSocket, DatagramSocket and other
+	/// socket classes.
+	///
+	/// It provides operations common to all socket types.
+{
+public:
+	enum SelectMode
+		/// The mode argument to poll() and select().
+	{
+		SELECT_READ  = 1,
+		SELECT_WRITE = 2,
+		SELECT_ERROR = 4
+	};
+	
+	typedef std::vector<Socket> SocketList;
+
+	Socket();
+		/// Creates an uninitialized socket.
+
+	Socket(const Socket& socket);
+		/// Copy constructor.
+		///
+		/// Attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.
+		
+	Socket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.
+		
+	virtual ~Socket();
+		/// Destroys the Socket and releases the
+		/// SocketImpl.
+		
+	bool operator == (const Socket& socket) const;
+		/// Returns true if both sockets share the same
+		/// SocketImpl, false otherwise.
+
+	bool operator != (const Socket& socket) const;
+		/// Returns false if both sockets share the same
+		/// SocketImpl, true otherwise.
+
+	bool operator <  (const Socket& socket) const;
+		/// Compares the SocketImpl pointers.
+	
+	bool operator <= (const Socket& socket) const;
+		/// Compares the SocketImpl pointers.
+
+	bool operator >  (const Socket& socket) const;
+		/// Compares the SocketImpl pointers.
+
+	bool operator >= (const Socket& socket) const;
+		/// Compares the SocketImpl pointers.
+		
+	void close();
+		/// Closes the socket.
+
+	static int select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout);
+		/// Determines the status of one or more sockets, 
+		/// using a call to select().
+		///
+		/// ReadList contains the list of sockets which should be
+		/// checked for readability.
+		///
+		/// WriteList contains the list of sockets which should be
+		/// checked for writeability.
+		///
+		/// ExceptList contains a list of sockets which should be
+		/// checked for a pending error.
+		///
+		/// Returns the number of sockets ready.
+		///
+		/// After return, 
+		///   * readList contains those sockets ready for reading,
+		///   * writeList contains those sockets ready for writing,
+		///   * exceptList contains those sockets with a pending error.
+		///
+		/// If the total number of sockets passed in readList, writeList and
+		/// exceptList is zero, select() will return immediately and the
+		/// return value will be 0.
+		///
+		/// If one of the sockets passed to select() is closed while
+		/// select() runs, select will return immediately. However,
+		/// the closed socket will not be included in any list.
+		/// In this case, the return value may be greater than the sum
+		/// of all sockets in all list.
+
+	bool poll(const Poco::Timespan& timeout, int mode) const;
+		/// Determines the status of the socket, using a 
+		/// call to poll() or select().
+		/// 
+		/// The mode argument is constructed by combining the values
+		/// of the SelectMode enumeration.
+		///
+		/// Returns true if the next operation corresponding to
+		/// mode will not block, false otherwise.
+
+	int available() const;
+		/// Returns the number of bytes available that can be read
+		/// without causing the socket to block.
+
+	void setSendBufferSize(int size);
+		/// Sets the size of the send buffer.
+		
+	int getSendBufferSize() const;
+		/// Returns the size of the send buffer.
+		///
+		/// The returned value may be different than the
+		/// value previously set with setSendBufferSize(),
+		/// as the system is free to adjust the value.
+
+	void setReceiveBufferSize(int size);
+		/// Sets the size of the receive buffer.
+		
+	int getReceiveBufferSize() const;
+		/// Returns the size of the receive buffer.
+		///
+		/// The returned value may be different than the
+		/// value previously set with setReceiveBufferSize(),
+		/// as the system is free to adjust the value.
+
+	void setSendTimeout(const Poco::Timespan& timeout);
+		/// Sets the send timeout for the socket.
+	
+	Poco::Timespan getSendTimeout() const;
+		/// Returns the send timeout for the socket.
+		///
+		/// The returned timeout may be different than the
+		/// timeout previously set with setSendTimeout(),
+		/// as the system is free to adjust the value.
+
+	void setReceiveTimeout(const Poco::Timespan& timeout);
+		/// Sets the send timeout for the socket.
+		///
+		/// On systems that do not support SO_RCVTIMEO, a
+		/// workaround using poll() is provided.
+	
+	Poco::Timespan getReceiveTimeout() const;
+		/// Returns the receive timeout for the socket.
+		///
+		/// The returned timeout may be different than the
+		/// timeout previously set with getReceiveTimeout(),
+		/// as the system is free to adjust the value.
+
+	void setOption(int level, int option, int value);
+		/// Sets the socket option specified by level and option
+		/// to the given integer value.
+
+	void setOption(int level, int option, unsigned value);
+		/// Sets the socket option specified by level and option
+		/// to the given integer value.
+
+	void setOption(int level, int option, unsigned char value);
+		/// Sets the socket option specified by level and option
+		/// to the given integer value.
+		
+	void setOption(int level, int option, const Poco::Timespan& value);
+		/// Sets the socket option specified by level and option
+		/// to the given time value.
+		
+	void setOption(int level, int option, const IPAddress& value);
+		/// Sets the socket option specified by level and option
+		/// to the given time value.
+
+	void getOption(int level, int option, int& value) const;
+		/// Returns the value of the socket option 
+		/// specified by level and option.
+
+	void getOption(int level, int option, unsigned& value) const;
+		/// Returns the value of the socket option 
+		/// specified by level and option.
+
+	void getOption(int level, int option, unsigned char& value) const;
+		/// Returns the value of the socket option 
+		/// specified by level and option.
+
+	void getOption(int level, int option, Poco::Timespan& value) const;
+		/// Returns the value of the socket option 
+		/// specified by level and option.
+	
+	void getOption(int level, int option, IPAddress& value) const;
+		/// Returns the value of the socket option 
+		/// specified by level and option.
+
+	void setLinger(bool on, int seconds);
+		/// Sets the value of the SO_LINGER socket option.
+		
+	void getLinger(bool& on, int& seconds) const;
+		/// Returns the value of the SO_LINGER socket option.
+	
+	void setNoDelay(bool flag);
+		/// Sets the value of the TCP_NODELAY socket option.
+		
+	bool getNoDelay() const;
+		/// Returns the value of the TCP_NODELAY socket option.
+	
+	void setKeepAlive(bool flag);
+		/// Sets the value of the SO_KEEPALIVE socket option.
+		
+	bool getKeepAlive() const;
+		/// Returns the value of the SO_KEEPALIVE socket option.
+	
+	void setReuseAddress(bool flag);
+		/// Sets the value of the SO_REUSEADDR socket option.
+	
+	bool getReuseAddress() const;
+		/// Returns the value of the SO_REUSEADDR socket option.
+
+	void setReusePort(bool flag);
+		/// Sets the value of the SO_REUSEPORT socket option.
+		/// Does nothing if the socket implementation does not
+		/// support SO_REUSEPORT.
+	
+	bool getReusePort() const;
+		/// Returns the value of the SO_REUSEPORT socket option.
+		///
+		/// Returns false if the socket implementation does not
+		/// support SO_REUSEPORT.
+		
+	void setOOBInline(bool flag);
+		/// Sets the value of the SO_OOBINLINE socket option.
+	
+	bool getOOBInline() const;
+		/// Returns the value of the SO_OOBINLINE socket option.
+
+	void setBlocking(bool flag);
+		/// Sets the socket in blocking mode if flag is true,
+		/// disables blocking mode if flag is false.
+
+	bool getBlocking() const;
+		/// Returns the blocking mode of the socket.
+		/// This method will only work if the blocking modes of 
+		/// the socket are changed via the setBlocking method!
+
+	SocketAddress address() const;
+		/// Returns the IP address and port number of the socket.
+		
+	SocketAddress peerAddress() const;
+		/// Returns the IP address and port number of the peer socket.
+
+	SocketImpl* impl() const;
+		/// Returns the SocketImpl for this socket.
+		
+	bool secure() const;
+		/// Returns true iff the socket's connection is secure
+		/// (using SSL or TLS).
+		
+	static bool supportsIPv4();
+		/// Returns true if the system supports IPv4.
+		
+	static bool supportsIPv6();
+		/// Returns true if the system supports IPv6.
+
+	void init(int af);
+		/// Creates the underlying system socket for the given
+		/// address family.
+		///
+		/// Normally, this method should not be called directly, as
+		/// socket creation will be handled automatically. There are
+		/// a few situations where calling this method after creation
+		/// of the Socket object makes sense. One example is setting
+		/// a socket option before calling bind() on a ServerSocket.
+
+protected:
+	Socket(SocketImpl* pImpl);
+		/// Creates the Socket and attaches the given SocketImpl.
+		/// The socket takes ownership of the SocketImpl.
+
+	poco_socket_t sockfd() const;
+		/// Returns the socket descriptor for this socket.
+
+private:
+
+#if defined(POCO_HAVE_FD_POLL)
+class FDCompare
+	/// Utility functor used to compare socket file descriptors.
+	/// Used in poll() member function.
+{
+public:
+	FDCompare(int fd): _fd(fd) { }
+	inline bool operator()(const Socket& socket) const
+	{ return socket.sockfd() == _fd; }
+
+private:
+	FDCompare();
+	int _fd;
+};
+#endif
+
+	SocketImpl* _pImpl;
+};
+
+
+//
+// inlines
+//
+inline bool Socket::operator == (const Socket& socket) const
+{
+	return _pImpl == socket._pImpl;
+}
+
+
+inline bool Socket::operator != (const Socket& socket) const
+{
+	return _pImpl != socket._pImpl;
+}
+
+
+inline bool Socket::operator <  (const Socket& socket) const
+{
+	return _pImpl < socket._pImpl;
+}
+
+
+inline bool Socket::operator <= (const Socket& socket) const
+{
+	return _pImpl <= socket._pImpl;
+}
+
+
+inline bool Socket::operator >  (const Socket& socket) const
+{
+	return _pImpl > socket._pImpl;
+}
+
+
+inline bool Socket::operator >= (const Socket& socket) const
+{
+	return _pImpl >= socket._pImpl;
+}
+
+
+inline void Socket::close()
+{
+	_pImpl->close();
+}
+
+
+inline bool Socket::poll(const Poco::Timespan& timeout, int mode) const
+{
+	return _pImpl->poll(timeout, mode);
+}
+
+
+inline int Socket::available() const
+{
+	return _pImpl->available();
+}
+
+
+inline void Socket::setSendBufferSize(int size)
+{
+	_pImpl->setSendBufferSize(size);
+}
+
+	
+inline int Socket::getSendBufferSize() const
+{
+	return _pImpl->getSendBufferSize();
+}
+
+
+inline void Socket::setReceiveBufferSize(int size)
+{
+	_pImpl->setReceiveBufferSize(size);
+}
+
+	
+inline int Socket::getReceiveBufferSize() const
+{
+	return _pImpl->getReceiveBufferSize();
+}
+
+
+inline void Socket::setSendTimeout(const Poco::Timespan& timeout)
+{
+	_pImpl->setSendTimeout(timeout);
+}
+
+
+inline Poco::Timespan Socket::getSendTimeout() const
+{
+	return _pImpl->getSendTimeout();
+}
+
+
+inline void Socket::setReceiveTimeout(const Poco::Timespan& timeout)
+{
+	_pImpl->setReceiveTimeout(timeout);
+}
+
+
+inline Poco::Timespan Socket::getReceiveTimeout() const
+{
+	return _pImpl->getReceiveTimeout();
+}
+
+
+inline void Socket::setOption(int level, int option, int value)
+{
+	_pImpl->setOption(level, option, value);
+}
+
+
+inline void Socket::setOption(int level, int option, unsigned value)
+{
+	_pImpl->setOption(level, option, value);
+}
+
+
+inline void Socket::setOption(int level, int option, unsigned char value)
+{
+	_pImpl->setOption(level, option, value);
+}
+
+
+inline void Socket::setOption(int level, int option, const Poco::Timespan& value)
+{
+	_pImpl->setOption(level, option, value);
+}
+
+	
+inline void Socket::setOption(int level, int option, const IPAddress& value)
+{
+	_pImpl->setOption(level, option, value);
+}
+
+
+inline void Socket::getOption(int level, int option, int& value) const
+{
+	_pImpl->getOption(level, option, value);
+}
+
+
+inline void Socket::getOption(int level, int option, unsigned& value) const
+{
+	_pImpl->getOption(level, option, value);
+}
+
+
+inline void Socket::getOption(int level, int option, unsigned char& value) const
+{
+	_pImpl->getOption(level, option, value);
+}
+
+
+inline void Socket::getOption(int level, int option, Poco::Timespan& value) const
+{
+	_pImpl->getOption(level, option, value);
+}
+
+
+inline void Socket::getOption(int level, int option, IPAddress& value) const
+{
+	_pImpl->getOption(level, option, value);
+}
+
+
+inline void Socket::setLinger(bool on, int seconds)
+{
+	_pImpl->setLinger(on, seconds);
+}
+
+	
+inline void Socket::getLinger(bool& on, int& seconds) const
+{
+	_pImpl->getLinger(on, seconds);
+}
+
+
+inline void Socket::setNoDelay(bool flag)
+{
+	_pImpl->setNoDelay(flag);
+}
+
+	
+inline bool Socket::getNoDelay() const
+{
+	return _pImpl->getNoDelay();
+}
+
+
+inline void Socket::setKeepAlive(bool flag)
+{
+	_pImpl->setKeepAlive(flag);
+}
+
+	
+inline bool Socket::getKeepAlive() const
+{
+	return _pImpl->getKeepAlive();
+}
+
+
+inline void Socket::setReuseAddress(bool flag)
+{
+	_pImpl->setReuseAddress(flag);
+}
+
+
+inline bool Socket::getReuseAddress() const
+{
+	return _pImpl->getReuseAddress();
+}
+
+
+inline void Socket::setReusePort(bool flag)
+{
+	_pImpl->setReusePort(flag);
+}
+
+
+inline bool Socket::getReusePort() const
+{
+	return _pImpl->getReusePort();
+}
+
+	
+inline void Socket::setOOBInline(bool flag)
+{
+	_pImpl->setOOBInline(flag);
+}
+
+
+inline bool Socket::getOOBInline() const
+{
+	return _pImpl->getOOBInline();
+}
+
+
+inline void Socket::setBlocking(bool flag)
+{
+	_pImpl->setBlocking(flag);
+}
+
+
+inline bool Socket::getBlocking() const
+{
+	return _pImpl->getBlocking();
+}
+
+
+inline SocketImpl* Socket::impl() const
+{
+	return _pImpl;
+}
+
+
+inline poco_socket_t Socket::sockfd() const
+{
+	return _pImpl->sockfd();
+}
+
+
+inline SocketAddress Socket::address() const
+{
+	return _pImpl->address();
+}
+
+	
+inline SocketAddress Socket::peerAddress() const
+{
+	return _pImpl->peerAddress();
+}
+
+
+inline bool Socket::secure() const
+{
+	return _pImpl->secure();
+}
+
+
+inline bool Socket::supportsIPv4()
+{
+	return true;
+}
+
+
+inline bool Socket::supportsIPv6()
+{
+#if defined(POCO_HAVE_IPv6)
+	return true;
+#else
+	return false;
+#endif
+}
+
+
+inline void Socket::init(int af)
+{
+	_pImpl->init(af);
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_Socket_INCLUDED
diff --git a/Poco/Net/SocketAcceptor.h b/Poco/Net/SocketAcceptor.h
new file mode 100644
index 0000000..c9021ec
--- /dev/null
+++ b/Poco/Net/SocketAcceptor.h
@@ -0,0 +1,196 @@
+//
+// SocketAcceptor.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  SocketAcceptor
+//
+// Definition of the SocketAcceptor class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketAcceptor_INCLUDED
+#define Net_SocketAcceptor_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketNotification.h"
+#include "Poco/Net/SocketReactor.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Observer.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+template <class ServiceHandler>
+class SocketAcceptor
+	/// This class implements the Acceptor part of the
+	/// Acceptor-Connector design pattern.
+	///
+	/// The Acceptor-Connector pattern has been described in the book
+	/// "Pattern Languages of Program Design 3", edited by Robert Martin,
+	/// Frank Buschmann and Dirk Riehle (Addison Wesley, 1997).
+	///
+	/// The Acceptor-Connector design pattern decouples connection
+	/// establishment and service initialization in a distributed system
+	/// from the processing performed once a service is initialized.
+	/// This decoupling is achieved with three components: Acceptors, 
+	/// Connectors and Service Handlers.
+	/// The SocketAcceptor passively waits for connection requests (usually
+	/// from a remote Connector) and establishes a connection upon
+	/// arrival of a connection requests. Also, a Service Handler is
+	/// initialized to process the data arriving via the connection in
+	/// an application-specific way.
+	///
+	/// The SocketAcceptor sets up a ServerSocket and registers itself
+	/// for a ReadableNotification, denoting an incoming connection request.
+	///
+	/// When the ServerSocket becomes readable the SocketAcceptor accepts
+	/// the connection request and creates a ServiceHandler to
+	/// service the connection.
+	///
+	/// The ServiceHandler class must provide a constructor that
+	/// takes a StreamSocket and a SocketReactor as arguments,
+	/// e.g.:
+	///     MyServiceHandler(const StreamSocket& socket, ServiceReactor& reactor)
+	///
+	/// When the ServiceHandler is done, it must destroy itself.
+	///
+	/// Subclasses can override the createServiceHandler() factory method
+	/// if special steps are necessary to create a ServiceHandler object.
+{
+public:
+	explicit SocketAcceptor(ServerSocket& socket):
+		_socket(socket),
+		_pReactor(0)
+		/// Creates a SocketAcceptor, using the given ServerSocket.
+	{
+	}
+
+	SocketAcceptor(ServerSocket& socket, SocketReactor& reactor):
+		_socket(socket),
+		_pReactor(&reactor)
+		/// Creates a SocketAcceptor, using the given ServerSocket.
+		/// The SocketAcceptor registers itself with the given SocketReactor.
+	{
+		_pReactor->addEventHandler(_socket, Poco::Observer<SocketAcceptor,
+			ReadableNotification>(*this, &SocketAcceptor::onAccept));
+	}
+
+	virtual ~SocketAcceptor()
+		/// Destroys the SocketAcceptor.
+	{
+		try
+		{
+			if (_pReactor)
+			{
+				_pReactor->removeEventHandler(_socket, Poco::Observer<SocketAcceptor,
+					ReadableNotification>(*this, &SocketAcceptor::onAccept));
+			}
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	void setReactor(SocketReactor& reactor)
+		/// Sets the reactor for this acceptor.
+	{
+		_pReactor = &reactor;
+		if (!_pReactor->hasEventHandler(_socket, Poco::Observer<SocketAcceptor,
+			ReadableNotification>(*this, &SocketAcceptor::onAccept)))
+		{
+			registerAcceptor(reactor);
+		}
+	}
+
+	virtual void registerAcceptor(SocketReactor& reactor)
+		/// Registers the SocketAcceptor with a SocketReactor.
+		///
+		/// A subclass can override this function to e.g.
+		/// register an event handler for timeout event.
+		/// 
+		/// If acceptor was constructed without providing reactor to it,
+		/// the override of this method must either call the base class
+		/// implementation or directly register the accept handler with
+		/// the reactor.
+	{
+		if (_pReactor)
+			throw Poco::InvalidAccessException("Acceptor already registered.");
+
+		_pReactor = &reactor;
+		_pReactor->addEventHandler(_socket, Poco::Observer<SocketAcceptor, ReadableNotification>(*this, &SocketAcceptor::onAccept));
+	}
+	
+	virtual void unregisterAcceptor()
+		/// Unregisters the SocketAcceptor.
+		///
+		/// A subclass can override this function to e.g.
+		/// unregister its event handler for a timeout event.
+		/// 
+		/// If the accept handler was registered with the reactor,
+		/// the overriding method must either call the base class
+		/// implementation or directly unregister the accept handler.
+	{
+		if (_pReactor)
+		{
+			_pReactor->removeEventHandler(_socket, Poco::Observer<SocketAcceptor, ReadableNotification>(*this, &SocketAcceptor::onAccept));
+		}
+	}
+	
+	void onAccept(ReadableNotification* pNotification)
+		/// Accepts connection and creates event handler.
+	{
+		pNotification->release();
+		StreamSocket sock = _socket.acceptConnection();
+		_pReactor->wakeUp();
+		createServiceHandler(sock);
+	}
+	
+protected:
+	virtual ServiceHandler* createServiceHandler(StreamSocket& socket)
+		/// Create and initialize a new ServiceHandler instance.
+		///
+		/// Subclasses can override this method.
+	{
+		return new ServiceHandler(socket, *_pReactor);
+	}
+
+	SocketReactor* reactor()
+		/// Returns a pointer to the SocketReactor where
+		/// this SocketAcceptor is registered.
+		///
+		/// The pointer may be null.
+	{
+		return _pReactor;
+	}
+
+	Socket& socket()
+		/// Returns a reference to the SocketAcceptor's socket.
+	{
+		return _socket;
+	}
+
+private:
+	SocketAcceptor();
+	SocketAcceptor(const SocketAcceptor&);
+	SocketAcceptor& operator = (const SocketAcceptor&);
+	
+	ServerSocket   _socket;
+	SocketReactor* _pReactor;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketAcceptor_INCLUDED
diff --git a/Poco/Net/SocketAddress.h b/Poco/Net/SocketAddress.h
new file mode 100644
index 0000000..61c5581
--- /dev/null
+++ b/Poco/Net/SocketAddress.h
@@ -0,0 +1,301 @@
+//
+// SocketAddress.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  SocketAddress
+//
+// Definition of the SocketAddress class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketAddress_INCLUDED
+#define Net_SocketAddress_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketAddressImpl.h"
+#include <ostream>
+
+
+namespace Poco {
+
+class BinaryReader;
+class BinaryWriter;
+
+namespace Net {
+
+
+class IPAddress;
+
+
+class Net_API SocketAddress
+	/// This class represents an internet (IP) endpoint/socket
+	/// address. The address can belong either to the
+	/// IPv4 or the IPv6 address family and consists of a
+	/// host address and a port number.
+{
+public:
+	// The following declarations keep the Family type
+	// backwards compatible with the previously used
+	// enum declaration.
+	typedef AddressFamily::Family Family;
+	static const Family IPv4 = AddressFamily::IPv4;
+#if defined(POCO_HAVE_IPv6)
+	static const Family IPv6 = AddressFamily::IPv6;
+#endif
+#if defined(POCO_OS_FAMILY_UNIX)
+	static const Family UNIX_LOCAL = AddressFamily::UNIX_LOCAL;
+#endif
+
+	SocketAddress();
+		/// Creates a wildcard (all zero) IPv4 SocketAddress.
+
+	explicit SocketAddress(Family family);
+		/// Creates a SocketAddress with unspecified (wildcard) IP address
+		/// of the given family.
+
+	SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber);
+		/// Creates a SocketAddress from an IP address and given port number.
+
+	explicit SocketAddress(Poco::UInt16 port);
+		/// Creates a SocketAddress with unspecified (wildcard) IP address
+		/// and given port number.
+
+	SocketAddress(Family family, Poco::UInt16 port);
+		/// Creates a SocketAddress with unspecified (wildcard) IP address
+		/// of the given family, and given port number.
+
+	SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber);
+		/// Creates a SocketAddress from an IP address and given port number.
+		///
+		/// The IP address must either be a domain name, or it must
+		/// be in dotted decimal (IPv4) or hex string (IPv6) format.
+
+	SocketAddress(Family family, const std::string& hostAddress, Poco::UInt16 portNumber);
+		/// Creates a SocketAddress from an IP address and given port number.
+		///
+		/// The IP address must either be a domain name, or it must
+		/// be in dotted decimal (IPv4) or hex string (IPv6) format.
+		///
+		/// If a domain name is given in hostAddress, it is resolved and the address
+		/// matching the given family is used. If no address matching the given family
+		/// is found, or the IP address given in hostAddress does not match the given
+		/// family, an AddressFamilyMismatchException is thrown.
+
+	SocketAddress(const std::string& hostAddress, const std::string& portNumber);
+		/// Creates a SocketAddress from an IP address and the
+		/// service name or port number.
+		///
+		/// The IP address must either be a domain name, or it must
+		/// be in dotted decimal (IPv4) or hex string (IPv6) format.
+		///
+		/// The given port must either be a decimal port number, or
+		/// a service name.
+
+	SocketAddress(Family family, const std::string& hostAddress, const std::string& portNumber);
+		/// Creates a SocketAddress from an IP address and the
+		/// service name or port number.
+		///
+		/// The IP address must either be a domain name, or it must
+		/// be in dotted decimal (IPv4) or hex string (IPv6) format.
+		///
+		/// The given port must either be a decimal port number, or
+		/// a service name.
+		///
+		/// If a domain name is given in hostAddress, it is resolved and the address
+		/// matching the given family is used. If no address matching the given family
+		/// is found, or the IP address given in hostAddress does not match the given
+		/// family, an AddressFamilyMismatchException is thrown.
+
+	explicit SocketAddress(const std::string& hostAndPort);
+		/// Creates a SocketAddress from an IP address or host name and the
+		/// port number/service name. Host name/address and port number must
+		/// be separated by a colon. In case of an IPv6 address,
+		/// the address part must be enclosed in brackets.
+		///
+		/// Examples:
+		///     192.168.1.10:80
+		///     [::ffff:192.168.1.120]:2040
+		///     www.appinf.com:8080
+		///
+		/// On POSIX platforms supporting UNIX_LOCAL sockets, hostAndPort
+		/// can also be the absolute path of a local socket, starting with a
+		/// slash, e.g. "/tmp/local.socket".
+
+	SocketAddress(Family family, const std::string& addr);
+		/// Creates a SocketAddress of the given family from a
+		/// string representation of the address, which is
+		/// either an IP address and port number, separated by
+		/// a colon for IPv4 or IPv6 addresses, or a path for
+		/// UNIX_LOCAL sockets.
+
+	SocketAddress(const SocketAddress& addr);
+		/// Creates a SocketAddress by copying another one.
+
+	SocketAddress(const struct sockaddr* addr, poco_socklen_t length);
+		/// Creates a SocketAddress from a native socket address.
+
+	~SocketAddress();
+		/// Destroys the SocketAddress.
+
+	SocketAddress& operator = (const SocketAddress& socketAddress);
+		/// Assigns another SocketAddress.
+
+	IPAddress host() const;
+		/// Returns the host IP address.
+
+	Poco::UInt16 port() const;
+		/// Returns the port number.
+
+	poco_socklen_t length() const;
+		/// Returns the length of the internal native socket address.
+
+	const struct sockaddr* addr() const;
+		/// Returns a pointer to the internal native socket address.
+
+	int af() const;
+		/// Returns the address family (AF_INET or AF_INET6) of the address.
+
+	std::string toString() const;
+		/// Returns a string representation of the address.
+
+	Family family() const;
+		/// Returns the address family of the host's address.
+
+	bool operator < (const SocketAddress& socketAddress) const;
+	bool operator == (const SocketAddress& socketAddress) const;
+	bool operator != (const SocketAddress& socketAddress) const;
+
+	enum
+	{
+		MAX_ADDRESS_LENGTH =
+#if defined(POCO_OS_FAMILY_UNIX)
+			sizeof(struct sockaddr_un)
+#elif defined(POCO_HAVE_IPv6)
+			sizeof(struct sockaddr_in6)
+#else
+			sizeof(struct sockaddr_in)
+#endif
+			/// Maximum length in bytes of a socket address.
+	};
+
+protected:
+	void init(const IPAddress& hostAddress, Poco::UInt16 portNumber);
+	void init(const std::string& hostAddress, Poco::UInt16 portNumber);
+	void init(Family family, const std::string& hostAddress, Poco::UInt16 portNumber);
+	void init(Family family, const std::string& address);
+	void init(const std::string& hostAndPort);
+	Poco::UInt16 resolveService(const std::string& service);
+
+private:
+	typedef Poco::Net::Impl::SocketAddressImpl Impl;
+	typedef Poco::AutoPtr<Impl> Ptr;
+
+	Ptr pImpl() const;
+
+	void newIPv4();
+	void newIPv4(const sockaddr_in*);
+	void newIPv4(const IPAddress& hostAddress, Poco::UInt16 portNumber);
+
+#if defined(POCO_HAVE_IPv6)
+	void newIPv6(const sockaddr_in6*);
+	void newIPv6(const IPAddress& hostAddress, Poco::UInt16 portNumber);
+#endif
+
+#if defined(POCO_OS_FAMILY_UNIX)
+	void newLocal(const sockaddr_un* sockAddr);
+	void newLocal(const std::string& path);
+#endif
+
+	Ptr _pImpl;
+};
+
+
+//
+// inlines
+//
+inline SocketAddress::Ptr SocketAddress::pImpl() const
+{
+	if (_pImpl) return _pImpl;
+	throw Poco::NullPointerException("Pointer to SocketAddress implementation is NULL.");
+}
+
+
+inline void SocketAddress::newIPv4()
+{
+	_pImpl = new Poco::Net::Impl::IPv4SocketAddressImpl;
+}
+
+
+inline void SocketAddress::newIPv4(const sockaddr_in* sockAddr)
+{
+	_pImpl = new Poco::Net::Impl::IPv4SocketAddressImpl(sockAddr);
+}
+
+
+inline void SocketAddress::newIPv4(const IPAddress& hostAddress, Poco::UInt16 portNumber)
+{
+	_pImpl = new Poco::Net::Impl::IPv4SocketAddressImpl(hostAddress.addr(), htons(portNumber));
+}
+
+
+#if defined(POCO_HAVE_IPv6)
+inline void SocketAddress::newIPv6(const sockaddr_in6* sockAddr)
+{
+	_pImpl = new Poco::Net::Impl::IPv6SocketAddressImpl(sockAddr);
+}
+
+
+inline void SocketAddress::newIPv6(const IPAddress& hostAddress, Poco::UInt16 portNumber)
+{
+	_pImpl = new Poco::Net::Impl::IPv6SocketAddressImpl(hostAddress.addr(), htons(portNumber), hostAddress.scope());
+}
+#endif // POCO_HAVE_IPv6
+
+
+#if defined(POCO_OS_FAMILY_UNIX)
+inline void SocketAddress::newLocal(const sockaddr_un* sockAddr)
+{
+	_pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(sockAddr);
+}
+
+
+inline void SocketAddress::newLocal(const std::string& path)
+{
+	_pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(path.c_str(), path.size());
+}
+#endif // POCO_OS_FAMILY_UNIX
+
+
+inline 	bool SocketAddress::operator == (const SocketAddress& socketAddress) const
+{
+#if defined(POCO_OS_FAMILY_UNIX)
+	if (family() == UNIX_LOCAL)
+		return toString() == socketAddress.toString();
+	else
+#endif
+		return host() == socketAddress.host() && port() == socketAddress.port();
+}
+
+
+inline bool SocketAddress::operator != (const SocketAddress& socketAddress) const
+{
+	return !(operator == (socketAddress));
+}
+
+
+} } // namespace Poco::Net
+
+
+Net_API Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value);
+Net_API Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value);
+Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address);
+
+
+#endif // Net_SocketAddress_INCLUDED
diff --git a/Poco/Net/SocketAddressImpl.h b/Poco/Net/SocketAddressImpl.h
new file mode 100644
index 0000000..079bece
--- /dev/null
+++ b/Poco/Net/SocketAddressImpl.h
@@ -0,0 +1,258 @@
+//
+// SocketAddressImpl.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  SocketAddressImpl
+//
+// Definition of the SocketAddressImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketAddressImpl_INCLUDED
+#define Net_SocketAddressImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Net/IPAddress.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+namespace Net {
+namespace Impl {
+
+
+class Net_API SocketAddressImpl : public Poco::RefCountedObject
+{
+public:
+	typedef AddressFamily::Family Family;
+
+	virtual ~SocketAddressImpl();
+
+	virtual IPAddress host() const = 0;
+	virtual UInt16 port() const = 0;
+	virtual poco_socklen_t length() const = 0;
+	virtual const struct sockaddr* addr() const = 0;
+	virtual int af() const = 0;
+	virtual Family family() const = 0;
+	virtual std::string toString() const = 0;
+
+protected:
+	SocketAddressImpl();
+
+private:
+	SocketAddressImpl(const SocketAddressImpl&);
+	SocketAddressImpl& operator = (const SocketAddressImpl&);
+};
+
+
+class Net_API IPv4SocketAddressImpl: public SocketAddressImpl
+{
+public:
+	IPv4SocketAddressImpl();
+	IPv4SocketAddressImpl(const struct sockaddr_in* addr);
+	IPv4SocketAddressImpl(const void* addr, UInt16 port);
+	IPAddress host() const;
+	UInt16 port() const;
+	poco_socklen_t length() const;
+	const struct sockaddr* addr() const;
+	int af() const;
+	Family family() const;
+	std::string toString() const;
+
+private:
+	struct sockaddr_in _addr;
+};
+
+
+//
+// inlines
+//
+
+inline IPAddress IPv4SocketAddressImpl::host() const
+{
+	return IPAddress(&_addr.sin_addr, sizeof(_addr.sin_addr));
+}
+
+
+inline UInt16 IPv4SocketAddressImpl::port() const
+{
+	return _addr.sin_port;
+}
+
+
+inline poco_socklen_t IPv4SocketAddressImpl::length() const
+{
+	return sizeof(_addr);
+}
+
+
+inline const struct sockaddr* IPv4SocketAddressImpl::addr() const
+{
+	return reinterpret_cast<const struct sockaddr*>(&_addr);
+}
+
+
+inline int IPv4SocketAddressImpl::af() const
+{
+	return _addr.sin_family;
+}
+
+
+inline SocketAddressImpl::Family IPv4SocketAddressImpl::family() const
+{
+	return AddressFamily::IPv4;
+}
+
+
+#if defined(POCO_HAVE_IPv6)
+
+
+class Net_API IPv6SocketAddressImpl: public SocketAddressImpl
+{
+public:
+	IPv6SocketAddressImpl(const struct sockaddr_in6* addr);
+	IPv6SocketAddressImpl(const void* addr, UInt16 port);
+	IPv6SocketAddressImpl(const void* addr, UInt16 port, UInt32 scope);
+	IPAddress host() const;
+	UInt16 port() const;
+	poco_socklen_t length() const;
+	const struct sockaddr* addr() const;
+	int af() const;
+	Family family() const;
+	std::string toString() const;
+
+private:
+	struct sockaddr_in6 _addr;
+};
+
+
+//
+// inlines
+//
+
+inline IPAddress IPv6SocketAddressImpl::host() const
+{
+	return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr), _addr.sin6_scope_id);
+}
+
+
+inline UInt16 IPv6SocketAddressImpl::port() const
+{
+	return _addr.sin6_port;
+}
+
+
+inline poco_socklen_t IPv6SocketAddressImpl::length() const
+{
+	return sizeof(_addr);
+}
+
+
+inline const struct sockaddr* IPv6SocketAddressImpl::addr() const
+{
+	return reinterpret_cast<const struct sockaddr*>(&_addr);
+}
+
+
+inline int IPv6SocketAddressImpl::af() const
+{
+	return _addr.sin6_family;
+}
+
+
+inline SocketAddressImpl::Family IPv6SocketAddressImpl::family() const
+{
+	return AddressFamily::IPv6;
+}
+
+
+#endif // POCO_HAVE_IPv6
+
+
+#if defined(POCO_OS_FAMILY_UNIX)
+
+
+class Net_API LocalSocketAddressImpl: public SocketAddressImpl
+{
+public:
+	LocalSocketAddressImpl(const struct sockaddr_un* addr);
+	LocalSocketAddressImpl(const char* path);
+	LocalSocketAddressImpl(const char* path, std::size_t length);
+	~LocalSocketAddressImpl();
+	IPAddress host() const;
+	UInt16 port() const;
+	poco_socklen_t length() const;
+	const struct sockaddr* addr() const;
+	int af() const;
+	Family family() const;
+	const char* path() const;
+	std::string toString() const;
+
+private:
+	struct sockaddr_un* _pAddr;
+		// Note: We allocate struct sockaddr_un on the heap, otherwise we would
+		// waste a lot of memory due to small object optimization in SocketAddress.
+};
+
+
+//
+// inlines
+//
+
+inline IPAddress LocalSocketAddressImpl::host() const
+{
+	throw Poco::InvalidAccessException("local socket address does not have host IP address");
+}
+
+
+inline UInt16 LocalSocketAddressImpl::port() const
+{
+	throw Poco::InvalidAccessException("local socket address does not have port number");
+}
+
+
+inline poco_socklen_t LocalSocketAddressImpl::length() const
+{
+	return sizeof(struct sockaddr_un);
+}
+
+
+inline const struct sockaddr* LocalSocketAddressImpl::addr() const
+{
+	return reinterpret_cast<const struct sockaddr*>(_pAddr);
+}
+
+
+inline int LocalSocketAddressImpl::af() const
+{
+	return _pAddr->sun_family;
+}
+
+
+inline SocketAddressImpl::Family LocalSocketAddressImpl::family() const
+{
+	return AddressFamily::UNIX_LOCAL;
+}
+
+
+inline const char* LocalSocketAddressImpl::path() const
+{
+	return _pAddr->sun_path;
+}
+
+
+#endif // POCO_OS_FAMILY_UNIX
+
+
+} } } // namespace Poco::Net::Impl
+
+
+#endif // Net_SocketAddressImpl_INCLUDED
diff --git a/Poco/Net/SocketConnector.h b/Poco/Net/SocketConnector.h
new file mode 100644
index 0000000..d3196c9
--- /dev/null
+++ b/Poco/Net/SocketConnector.h
@@ -0,0 +1,212 @@
+//
+// SocketConnector.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  SocketConnector
+//
+// Definition of the SocketConnector class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketConnector_INCLUDED
+#define Net_SocketConnector_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketNotification.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Observer.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+template <class ServiceHandler>
+class SocketConnector
+	/// This class implements the Connector part of the
+	/// Acceptor-Connector design pattern.
+	///
+	/// The Acceptor-Connector pattern has been described in the book
+	/// "Pattern Languages of Program Design 3", edited by Robert Martin,
+	/// Frank Buschmann and Dirk Riehle (Addison Wesley, 1997).
+	///
+	/// The Acceptor-Connector design pattern decouples connection
+	/// establishment and service initialization in a distributed system
+	/// from the processing performed once a service is initialized.
+	/// This decoupling is achieved with three components: Acceptors, 
+	/// Connectors and Service Handlers.
+	/// The Connector actively establishes a connection with a remote
+	/// server socket (usually managed by an Acceptor) and initializes
+	/// a Service Handler to manage the connection.
+	///
+	/// The SocketConnector sets up a StreamSocket, initiates a non-blocking
+	/// connect operation and registers itself for ReadableNotification, WritableNotification
+	/// and ErrorNotification. ReadableNotification or WritableNotification denote the successful 
+	/// establishment of the connection.
+	///
+	/// When the StreamSocket becomes readable or writeable, the SocketConnector 
+	/// creates a ServiceHandler to service the connection and unregisters
+	/// itself.
+	///
+	/// In case of an error (ErrorNotification), the SocketConnector unregisters itself
+	/// and calls the onError() method, which can be overridden by subclasses
+	/// to perform custom error handling.
+	///
+	/// The ServiceHandler class must provide a constructor that
+	/// takes a StreamSocket and a SocketReactor as arguments,
+	/// e.g.:
+	///     MyServiceHandler(const StreamSocket& socket, ServiceReactor& reactor)
+	///
+	/// When the ServiceHandler is done, it must destroy itself.
+	///
+	/// Subclasses can override the createServiceHandler() factory method
+	/// if special steps are necessary to create a ServiceHandler object.
+{
+public:		
+	explicit SocketConnector(SocketAddress& address):
+		_pReactor(0)
+		/// Creates a SocketConnector, using the given Socket.
+	{
+		_socket.connectNB(address);
+	}
+
+	SocketConnector(SocketAddress& address, SocketReactor& reactor):
+		_pReactor(0)
+		/// Creates an acceptor, using the given ServerSocket.
+		/// The SocketConnector registers itself with the given SocketReactor.
+	{
+		_socket.connectNB(address);
+		registerConnector(reactor);
+	}
+
+	virtual ~SocketConnector()
+		/// Destroys the SocketConnector.
+	{
+		try
+		{
+			unregisterConnector();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+	
+	virtual void registerConnector(SocketReactor& reactor)
+		/// Registers the SocketConnector with a SocketReactor.
+		///
+		/// A subclass can override this and, for example, also register
+		/// an event handler for a timeout event.
+		///
+		/// The overriding method must call the baseclass implementation first.
+	{
+		_pReactor = &reactor;
+		_pReactor->addEventHandler(_socket, Poco::Observer<SocketConnector, ReadableNotification>(*this, &SocketConnector::onReadable));
+		_pReactor->addEventHandler(_socket, Poco::Observer<SocketConnector, WritableNotification>(*this, &SocketConnector::onWritable));
+		_pReactor->addEventHandler(_socket, Poco::Observer<SocketConnector, ErrorNotification>(*this, &SocketConnector::onError));
+	}
+	
+	virtual void unregisterConnector()
+		/// Unregisters the SocketConnector.
+		///
+		/// A subclass can override this and, for example, also unregister
+		/// its event handler for a timeout event.
+		///
+		/// The overriding method must call the baseclass implementation first.
+	{
+		if (_pReactor)
+		{
+			_pReactor->removeEventHandler(_socket, Poco::Observer<SocketConnector, ReadableNotification>(*this, &SocketConnector::onReadable));
+			_pReactor->removeEventHandler(_socket, Poco::Observer<SocketConnector, WritableNotification>(*this, &SocketConnector::onWritable));
+			_pReactor->removeEventHandler(_socket, Poco::Observer<SocketConnector, ErrorNotification>(*this, &SocketConnector::onError));
+		}
+	}
+	
+	void onReadable(ReadableNotification* pNotification)
+	{
+		pNotification->release();
+		int err = _socket.impl()->socketError(); 
+		if (err)
+		{
+			onError(err);
+			unregisterConnector();
+		}
+		else
+		{
+			onConnect();
+		}
+	}
+	
+	void onWritable(WritableNotification* pNotification)
+	{
+		pNotification->release();
+		onConnect();
+	}
+	
+	void onConnect()
+	{
+		_socket.setBlocking(true);
+		createServiceHandler();
+		unregisterConnector();
+	}
+	
+	void onError(ErrorNotification* pNotification)
+	{
+		pNotification->release();
+		onError(_socket.impl()->socketError());
+		unregisterConnector();
+	}
+	
+protected:
+	virtual ServiceHandler* createServiceHandler()
+		/// Create and initialize a new ServiceHandler instance.
+		///
+		/// Subclasses can override this method.
+	{
+		return new ServiceHandler(_socket, *_pReactor);
+	}
+
+	virtual void onError(int errorCode)
+		/// Called when the socket cannot be connected.
+		///
+		/// Subclasses can override this method.
+	{
+	}
+	
+	SocketReactor* reactor()
+		/// Returns a pointer to the SocketReactor where
+		/// this SocketConnector is registered.
+		///
+		/// The pointer may be null.
+	{
+		return _pReactor;
+	}
+	
+	StreamSocket& socket()
+		/// Returns a reference to the SocketConnector's socket.
+	{
+		return _socket;
+	}
+
+private:
+	SocketConnector();
+	SocketConnector(const SocketConnector&);
+	SocketConnector& operator = (const SocketConnector&);
+	
+	StreamSocket   _socket;
+	SocketReactor* _pReactor;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketConnector_INCLUDED
diff --git a/Poco/Net/SocketDefs.h b/Poco/Net/SocketDefs.h
new file mode 100644
index 0000000..858b089
--- /dev/null
+++ b/Poco/Net/SocketDefs.h
@@ -0,0 +1,378 @@
+//
+// SocketDefs.h
+//
+// Library: Net
+// Package: NetCore
+// Module:  SocketDefs
+//
+// Include platform-specific header files for sockets.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketDefs_INCLUDED
+#define Net_SocketDefs_INCLUDED
+
+
+#define POCO_ENOERR 0
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+	#include "Poco/UnWindows.h"
+	#include <winsock2.h>
+	#include <ws2tcpip.h>
+	#define POCO_INVALID_SOCKET  INVALID_SOCKET
+	#define poco_socket_t        SOCKET
+	#define poco_socklen_t       int
+	#define poco_ioctl_request_t int
+	#define poco_closesocket(s)  closesocket(s)
+	#define POCO_EINTR           WSAEINTR
+	#define POCO_EACCES          WSAEACCES
+	#define POCO_EFAULT          WSAEFAULT
+	#define POCO_EINVAL          WSAEINVAL
+	#define POCO_EMFILE          WSAEMFILE
+	#define POCO_EAGAIN          WSAEWOULDBLOCK
+	#define POCO_EWOULDBLOCK     WSAEWOULDBLOCK
+	#define POCO_EINPROGRESS     WSAEINPROGRESS
+	#define POCO_EALREADY        WSAEALREADY
+	#define POCO_ENOTSOCK        WSAENOTSOCK
+	#define POCO_EDESTADDRREQ    WSAEDESTADDRREQ
+	#define POCO_EMSGSIZE        WSAEMSGSIZE
+	#define POCO_EPROTOTYPE      WSAEPROTOTYPE
+	#define POCO_ENOPROTOOPT     WSAENOPROTOOPT
+	#define POCO_EPROTONOSUPPORT WSAEPROTONOSUPPORT
+	#define POCO_ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+	#define POCO_ENOTSUP         WSAEOPNOTSUPP
+	#define POCO_EPFNOSUPPORT    WSAEPFNOSUPPORT
+	#define POCO_EAFNOSUPPORT    WSAEAFNOSUPPORT
+	#define POCO_EADDRINUSE      WSAEADDRINUSE
+	#define POCO_EADDRNOTAVAIL   WSAEADDRNOTAVAIL
+	#define POCO_ENETDOWN        WSAENETDOWN
+	#define POCO_ENETUNREACH     WSAENETUNREACH
+	#define POCO_ENETRESET       WSAENETRESET
+	#define POCO_ECONNABORTED    WSAECONNABORTED
+	#define POCO_ECONNRESET      WSAECONNRESET
+	#define POCO_ENOBUFS         WSAENOBUFS
+	#define POCO_EISCONN         WSAEISCONN
+	#define POCO_ENOTCONN        WSAENOTCONN
+	#define POCO_ESHUTDOWN       WSAESHUTDOWN
+	#define POCO_ETIMEDOUT       WSAETIMEDOUT
+	#define POCO_ECONNREFUSED    WSAECONNREFUSED
+	#define POCO_EHOSTDOWN       WSAEHOSTDOWN
+	#define POCO_EHOSTUNREACH    WSAEHOSTUNREACH
+	#define POCO_ESYSNOTREADY    WSASYSNOTREADY
+	#define POCO_ENOTINIT        WSANOTINITIALISED
+	#define POCO_HOST_NOT_FOUND  WSAHOST_NOT_FOUND
+	#define POCO_TRY_AGAIN       WSATRY_AGAIN
+	#define POCO_NO_RECOVERY     WSANO_RECOVERY
+	#define POCO_NO_DATA         WSANO_DATA
+	#ifndef ADDRESS_FAMILY
+		#define ADDRESS_FAMILY USHORT
+	#endif
+#elif defined(POCO_VXWORKS)
+	#include <hostLib.h>
+	#include <ifLib.h>
+	#include <inetLib.h>
+	#include <ioLib.h>
+	#include <resolvLib.h>
+	#include <types.h>
+	#include <socket.h>
+	#include <netinet/tcp.h>
+	#define POCO_INVALID_SOCKET  -1
+	#define poco_socket_t        int
+	#define poco_socklen_t       int
+	#define poco_ioctl_request_t int
+	#define poco_closesocket(s)  ::close(s)
+	#define POCO_EINTR           EINTR
+	#define POCO_EACCES          EACCES
+	#define POCO_EFAULT          EFAULT
+	#define POCO_EINVAL          EINVAL
+	#define POCO_EMFILE          EMFILE
+	#define POCO_EAGAIN          EAGAIN
+	#define POCO_EWOULDBLOCK     EWOULDBLOCK
+	#define POCO_EINPROGRESS     EINPROGRESS
+	#define POCO_EALREADY        EALREADY
+	#define POCO_ENOTSOCK        ENOTSOCK
+	#define POCO_EDESTADDRREQ    EDESTADDRREQ
+	#define POCO_EMSGSIZE        EMSGSIZE
+	#define POCO_EPROTOTYPE      EPROTOTYPE
+	#define POCO_ENOPROTOOPT     ENOPROTOOPT
+	#define POCO_EPROTONOSUPPORT EPROTONOSUPPORT
+	#define POCO_ESOCKTNOSUPPORT ESOCKTNOSUPPORT
+	#define POCO_ENOTSUP         ENOTSUP
+	#define POCO_EPFNOSUPPORT    EPFNOSUPPORT
+	#define POCO_EAFNOSUPPORT    EAFNOSUPPORT
+	#define POCO_EADDRINUSE      EADDRINUSE
+	#define POCO_EADDRNOTAVAIL   EADDRNOTAVAIL
+	#define POCO_ENETDOWN        ENETDOWN
+	#define POCO_ENETUNREACH     ENETUNREACH
+	#define POCO_ENETRESET       ENETRESET
+	#define POCO_ECONNABORTED    ECONNABORTED
+	#define POCO_ECONNRESET      ECONNRESET
+	#define POCO_ENOBUFS         ENOBUFS
+	#define POCO_EISCONN         EISCONN
+	#define POCO_ENOTCONN        ENOTCONN
+	#define POCO_ESHUTDOWN       ESHUTDOWN
+	#define POCO_ETIMEDOUT       ETIMEDOUT
+	#define POCO_ECONNREFUSED    ECONNREFUSED
+	#define POCO_EHOSTDOWN       EHOSTDOWN
+	#define POCO_EHOSTUNREACH    EHOSTUNREACH
+	#define POCO_ESYSNOTREADY    -4
+	#define POCO_ENOTINIT        -5
+	#define POCO_HOST_NOT_FOUND  HOST_NOT_FOUND
+	#define POCO_TRY_AGAIN       TRY_AGAIN
+	#define POCO_NO_RECOVERY     NO_RECOVERY
+	#define POCO_NO_DATA         NO_DATA
+#elif defined(POCO_OS_FAMILY_UNIX)
+	#include <unistd.h>
+	#include <errno.h>
+	#include <sys/types.h>
+	#include <sys/socket.h>
+	#include <sys/un.h>
+	#include <fcntl.h>
+	#if POCO_OS != POCO_OS_HPUX
+		#include <sys/select.h>
+	#endif
+	#include <sys/ioctl.h>
+	#include <arpa/inet.h>
+	#include <netinet/in.h>
+	#include <netinet/tcp.h>
+	#include <netdb.h>
+	#if defined(POCO_OS_FAMILY_UNIX)
+		#if (POCO_OS == POCO_OS_LINUX) || (POCO_OS == POCO_OS_ANDROID)
+			// Net/src/NetworkInterface.cpp changed #include <linux/if.h> to #include <net/if.h>
+			// no more conflict, can use #include <net/if.h> here
+			#include <net/if.h>
+		#elif (POCO_OS == POCO_OS_HPUX)
+			extern "C"
+			{
+				#include <net/if.h>
+			}
+		#else
+			#include <net/if.h>
+		#endif
+	#endif
+	#if (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_MAC_OS_X)
+		#include <sys/sockio.h>
+		#include <sys/filio.h>
+	#endif
+	#define POCO_INVALID_SOCKET  -1
+	#define poco_socket_t        int
+	#define poco_socklen_t       socklen_t
+	#define poco_fcntl_request_t int
+	#if defined(POCO_OS_FAMILY_BSD)
+		#define poco_ioctl_request_t unsigned long
+	#else
+		#define poco_ioctl_request_t int
+	#endif
+	#define poco_closesocket(s)  ::close(s)
+	#define POCO_EINTR           EINTR
+	#define POCO_EACCES          EACCES
+	#define POCO_EFAULT          EFAULT
+	#define POCO_EINVAL          EINVAL
+	#define POCO_EMFILE          EMFILE
+	#define POCO_EAGAIN          EAGAIN
+	#define POCO_EWOULDBLOCK     EWOULDBLOCK
+	#define POCO_EINPROGRESS     EINPROGRESS
+	#define POCO_EALREADY        EALREADY
+	#define POCO_ENOTSOCK        ENOTSOCK
+	#define POCO_EDESTADDRREQ    EDESTADDRREQ
+	#define POCO_EMSGSIZE        EMSGSIZE
+	#define POCO_EPROTOTYPE      EPROTOTYPE
+	#define POCO_ENOPROTOOPT     ENOPROTOOPT
+	#define POCO_EPROTONOSUPPORT EPROTONOSUPPORT
+	#if defined(ESOCKTNOSUPPORT)
+		#define POCO_ESOCKTNOSUPPORT ESOCKTNOSUPPORT
+	#else
+		#define POCO_ESOCKTNOSUPPORT -1
+	#endif
+	#define POCO_ENOTSUP         ENOTSUP
+	#define POCO_EPFNOSUPPORT    EPFNOSUPPORT
+	#define POCO_EAFNOSUPPORT    EAFNOSUPPORT
+	#define POCO_EADDRINUSE      EADDRINUSE
+	#define POCO_EADDRNOTAVAIL   EADDRNOTAVAIL
+	#define POCO_ENETDOWN        ENETDOWN
+	#define POCO_ENETUNREACH     ENETUNREACH
+	#define POCO_ENETRESET       ENETRESET
+	#define POCO_ECONNABORTED    ECONNABORTED
+	#define POCO_ECONNRESET      ECONNRESET
+	#define POCO_ENOBUFS         ENOBUFS
+	#define POCO_EISCONN         EISCONN
+	#define POCO_ENOTCONN        ENOTCONN
+	#if defined(ESHUTDOWN)
+		#define POCO_ESHUTDOWN   ESHUTDOWN
+	#else
+		#define POCO_ESHUTDOWN   -2
+	#endif
+	#define POCO_ETIMEDOUT       ETIMEDOUT
+	#define POCO_ECONNREFUSED    ECONNREFUSED
+	#if defined(EHOSTDOWN)
+		#define POCO_EHOSTDOWN   EHOSTDOWN
+	#else
+		#define POCO_EHOSTDOWN   -3
+	#endif
+	#define POCO_EHOSTUNREACH    EHOSTUNREACH
+	#define POCO_ESYSNOTREADY    -4
+	#define POCO_ENOTINIT        -5
+	#define POCO_HOST_NOT_FOUND  HOST_NOT_FOUND
+	#define POCO_TRY_AGAIN       TRY_AGAIN
+	#define POCO_NO_RECOVERY     NO_RECOVERY
+	#define POCO_NO_DATA         NO_DATA
+#endif
+
+
+#if defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_TRU64) || (POCO_OS == POCO_OS_AIX) || (POCO_OS == POCO_OS_IRIX) || (POCO_OS == POCO_OS_QNX) || (POCO_OS == POCO_OS_VXWORKS)
+	#define POCO_HAVE_SALEN 1
+#endif
+
+
+#if POCO_OS != POCO_OS_VXWORKS && !defined(POCO_NET_NO_ADDRINFO)
+	#define POCO_HAVE_ADDRINFO 1
+#endif
+
+
+#if (POCO_OS == POCO_OS_HPUX) || (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_WINDOWS_CE) || (POCO_OS == POCO_OS_CYGWIN)
+	#define POCO_BROKEN_TIMEOUTS 1
+#endif
+
+
+#if defined(POCO_HAVE_ADDRINFO)
+	#ifndef AI_PASSIVE
+		#define AI_PASSIVE 0
+	#endif
+	#ifndef AI_CANONNAME
+		#define AI_CANONNAME 0
+	#endif
+	#ifndef AI_NUMERICHOST
+		#define AI_NUMERICHOST 0
+	#endif
+	#ifndef AI_NUMERICSERV
+		#define AI_NUMERICSERV 0
+	#endif
+	#ifndef AI_ALL
+		#define AI_ALL 0
+	#endif
+	#ifndef AI_ADDRCONFIG
+		#define AI_ADDRCONFIG 0
+	#endif
+	#ifndef AI_V4MAPPED
+		#define AI_V4MAPPED 0
+	#endif
+#endif
+
+
+#if defined(POCO_HAVE_SALEN)
+	#define poco_set_sa_len(pSA, len) (pSA)->sa_len = (len)
+	#define poco_set_sin_len(pSA) (pSA)->sin_len = sizeof(struct sockaddr_in)
+	#if defined(POCO_HAVE_IPv6)
+		#define poco_set_sin6_len(pSA) (pSA)->sin6_len = sizeof(struct sockaddr_in6)
+	#endif
+	#if defined(POCO_OS_FAMILY_UNIX)
+		#define poco_set_sun_len(pSA, len) (pSA)->sun_len = (len)
+	#endif
+#else
+	#define poco_set_sa_len(pSA, len)  (void) 0
+	#define poco_set_sin_len(pSA)      (void) 0
+	#define poco_set_sin6_len(pSA)     (void) 0
+	#define poco_set_sun_len(pSA, len) (void) 0
+#endif
+
+
+#ifndef INADDR_NONE
+	#define INADDR_NONE 0xffffffff
+#endif
+
+#ifndef INADDR_ANY
+	#define INADDR_ANY 0x00000000
+#endif
+
+#ifndef INADDR_BROADCAST
+	#define INADDR_BROADCAST 0xffffffff
+#endif
+
+#ifndef INADDR_LOOPBACK
+	#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+#ifndef INADDR_UNSPEC_GROUP
+	#define INADDR_UNSPEC_GROUP 0xe0000000
+#endif
+
+#ifndef INADDR_ALLHOSTS_GROUP
+	#define INADDR_ALLHOSTS_GROUP 0xe0000001
+#endif
+
+#ifndef INADDR_ALLRTRS_GROUP
+	#define INADDR_ALLRTRS_GROUP 0xe0000002
+#endif
+
+#ifndef INADDR_MAX_LOCAL_GROUP
+	#define INADDR_MAX_LOCAL_GROUP 0xe00000ff
+#endif
+
+#if defined(POCO_ARCH_BIG_ENDIAN)
+	#define poco_ntoh_16(x) (x)
+	#define poco_ntoh_32(x) (x)
+#else
+	#define poco_ntoh_16(x) \
+		((((x) >> 8) & 0x00ff) | (((x) << 8) & 0xff00))
+	#define poco_ntoh_32(x) \
+		((((x) >> 24) & 0x000000ff) | (((x) >> 8) & 0x0000ff00) | (((x) << 8) & 0x00ff0000) | (((x) << 24) & 0xff000000))
+#endif
+#define poco_hton_16(x) poco_ntoh_16(x)
+#define poco_hton_32(x) poco_ntoh_32(x)
+
+
+#if !defined(s6_addr16)
+	#if defined(POCO_OS_FAMILY_WINDOWS)
+		#define s6_addr16 u.Word
+	#else
+		#define s6_addr16 __u6_addr.__u6_addr16
+	#endif
+#endif
+
+
+#if !defined(s6_addr32)
+	#if defined(POCO_OS_FAMILY_UNIX)
+		#if (POCO_OS == POCO_OS_SOLARIS)
+			#define s6_addr32 _S6_un._S6_u32
+		#else
+			#define s6_addr32 __u6_addr.__u6_addr32
+		#endif
+	#endif
+#endif
+
+
+namespace Poco {
+namespace Net {
+
+
+struct AddressFamily
+	/// AddressFamily::Family replaces the previously used IPAddress::Family
+	/// enumeration and is now used for IPAddress::Family and SocketAddress::Family.
+{
+	enum Family
+		/// Possible address families for socket addresses.
+	{
+		IPv4,
+			/// IPv4 address family.
+	#if defined(POCO_HAVE_IPv6)
+		IPv6,
+			/// IPv6 address family.
+	#endif
+	#if defined(POCO_OS_FAMILY_UNIX)
+		UNIX_LOCAL
+			/// UNIX domain socket address family. Available on UNIX/POSIX platforms only.
+	#endif
+	};
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketDefs_INCLUDED
diff --git a/Poco/Net/SocketImpl.h b/Poco/Net/SocketImpl.h
new file mode 100644
index 0000000..20462f0
--- /dev/null
+++ b/Poco/Net/SocketImpl.h
@@ -0,0 +1,500 @@
+//
+// SocketImpl.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  SocketImpl
+//
+// Definition of the SocketImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketImpl_INCLUDED
+#define Net_SocketImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API SocketImpl: public Poco::RefCountedObject
+	/// This class encapsulates the Berkeley sockets API.
+	///
+	/// Subclasses implement specific socket types like
+	/// stream or datagram sockets.
+	///
+	/// You should not create any instances of this class.
+{
+public:
+	enum SelectMode
+	{
+		SELECT_READ  = 1,
+		SELECT_WRITE = 2,
+		SELECT_ERROR = 4
+	};
+
+	virtual SocketImpl* acceptConnection(SocketAddress& clientAddr);
+		/// Get the next completed connection from the
+		/// socket's completed connection queue.
+		///
+		/// If the queue is empty, waits until a connection
+		/// request completes.
+		///
+		/// Returns a new TCP socket for the connection
+		/// with the client.
+		///
+		/// The client socket's address is returned in clientAddr.
+
+	virtual void connect(const SocketAddress& address);
+		/// Initializes the socket and establishes a connection to
+		/// the TCP server at the given address.
+		///
+		/// Can also be used for UDP sockets. In this case, no
+		/// connection is established. Instead, incoming and outgoing
+		/// packets are restricted to the specified address.
+
+	virtual void connect(const SocketAddress& address, const Poco::Timespan& timeout);
+		/// Initializes the socket, sets the socket timeout and
+		/// establishes a connection to the TCP server at the given address.
+
+	virtual void connectNB(const SocketAddress& address);
+		/// Initializes the socket and establishes a connection to
+		/// the TCP server at the given address. Prior to opening the
+		/// connection the socket is set to nonblocking mode.
+
+	virtual void bind(const SocketAddress& address, bool reuseAddress = false);
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+
+	virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort );
+		/// Bind a local address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+
+	virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
+		/// Bind a local IPv6 address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// The given address must be an IPv6 address. The
+		/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
+		/// according to the ipV6Only parameter.
+		///
+		/// If the library has not been built with IPv6 support,
+		/// a Poco::NotImplementedException will be thrown.
+
+	virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort,  bool ipV6Only);
+		/// Bind a local IPv6 address to the socket.
+		///
+		/// This is usually only done when establishing a server
+		/// socket. TCP clients should not bind a socket to a
+		/// specific address.
+		///
+		/// If reuseAddress is true, sets the SO_REUSEADDR
+		/// socket option.
+		///
+		/// If reusePort is true, sets the SO_REUSEPORT
+		/// socket option.
+		///
+		/// The given address must be an IPv6 address. The
+		/// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket
+		/// according to the ipV6Only parameter.
+		///
+		/// If the library has not been built with IPv6 support,
+		/// a Poco::NotImplementedException will be thrown.
+
+	virtual void listen(int backlog = 64);
+		/// Puts the socket into listening state.
+		///
+		/// The socket becomes a passive socket that
+		/// can accept incoming connection requests.
+		///
+		/// The backlog argument specifies the maximum
+		/// number of connections that can be queued
+		/// for this socket.
+
+	virtual void close();
+		/// Close the socket.
+
+	virtual void shutdownReceive();
+		/// Shuts down the receiving part of the socket connection.
+
+	virtual void shutdownSend();
+		/// Shuts down the sending part of the socket connection.
+
+	virtual void shutdown();
+		/// Shuts down both the receiving and the sending part
+		/// of the socket connection.
+
+	virtual int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+		///
+		/// Certain socket implementations may also return a negative
+		/// value denoting a certain condition.
+
+	virtual int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		///
+		/// Returns the number of bytes received.
+		///
+		/// Certain socket implementations may also return a negative
+		/// value denoting a certain condition.
+
+	virtual int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket to the given address.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+
+	virtual int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		/// Stores the address of the sender in address.
+		///
+		/// Returns the number of bytes received.
+
+	virtual void sendUrgent(unsigned char data);
+		/// Sends one byte of urgent data through
+		/// the socket.
+		///
+		/// The data is sent with the MSG_OOB flag.
+		///
+		/// The preferred way for a socket to receive urgent data
+		/// is by enabling the SO_OOBINLINE option.
+
+	virtual int available();
+		/// Returns the number of bytes available that can be read
+		/// without causing the socket to block.
+
+	virtual bool poll(const Poco::Timespan& timeout, int mode);
+		/// Determines the status of the socket, using a
+		/// call to select().
+		///
+		/// The mode argument is constructed by combining the values
+		/// of the SelectMode enumeration.
+		///
+		/// Returns true if the next operation corresponding to
+		/// mode will not block, false otherwise.
+
+	virtual void setSendBufferSize(int size);
+		/// Sets the size of the send buffer.
+
+	virtual int getSendBufferSize();
+		/// Returns the size of the send buffer.
+		///
+		/// The returned value may be different than the
+		/// value previously set with setSendBufferSize(),
+		/// as the system is free to adjust the value.
+
+	virtual void setReceiveBufferSize(int size);
+		/// Sets the size of the receive buffer.
+
+	virtual int getReceiveBufferSize();
+		/// Returns the size of the receive buffer.
+		///
+		/// The returned value may be different than the
+		/// value previously set with setReceiveBufferSize(),
+		/// as the system is free to adjust the value.
+
+	virtual void setSendTimeout(const Poco::Timespan& timeout);
+		/// Sets the send timeout for the socket.
+
+	virtual Poco::Timespan getSendTimeout();
+		/// Returns the send timeout for the socket.
+		///
+		/// The returned timeout may be different than the
+		/// timeout previously set with setSendTimeout(),
+		/// as the system is free to adjust the value.
+
+	virtual void setReceiveTimeout(const Poco::Timespan& timeout);
+		/// Sets the send timeout for the socket.
+		///
+		/// On systems that do not support SO_RCVTIMEO, a
+		/// workaround using poll() is provided.
+
+	virtual Poco::Timespan getReceiveTimeout();
+		/// Returns the receive timeout for the socket.
+		///
+		/// The returned timeout may be different than the
+		/// timeout previously set with setReceiveTimeout(),
+		/// as the system is free to adjust the value.
+
+	virtual SocketAddress address();
+		/// Returns the IP address and port number of the socket.
+
+	virtual SocketAddress peerAddress();
+		/// Returns the IP address and port number of the peer socket.
+
+	void setOption(int level, int option, int value);
+		/// Sets the socket option specified by level and option
+		/// to the given integer value.
+
+	void setOption(int level, int option, unsigned value);
+		/// Sets the socket option specified by level and option
+		/// to the given integer value.
+
+	void setOption(int level, int option, unsigned char value);
+		/// Sets the socket option specified by level and option
+		/// to the given integer value.
+
+	void setOption(int level, int option, const Poco::Timespan& value);
+		/// Sets the socket option specified by level and option
+		/// to the given time value.
+
+	void setOption(int level, int option, const IPAddress& value);
+		/// Sets the socket option specified by level and option
+		/// to the given time value.
+
+	virtual void setRawOption(int level, int option, const void* value, poco_socklen_t length);
+		/// Sets the socket option specified by level and option
+		/// to the given time value.
+
+	void getOption(int level, int option, int& value);
+		/// Returns the value of the socket option
+		/// specified by level and option.
+
+	void getOption(int level, int option, unsigned& value);
+		/// Returns the value of the socket option
+		/// specified by level and option.
+
+	void getOption(int level, int option, unsigned char& value);
+		/// Returns the value of the socket option
+		/// specified by level and option.
+
+	void getOption(int level, int option, Poco::Timespan& value);
+		/// Returns the value of the socket option
+		/// specified by level and option.
+
+	void getOption(int level, int option, IPAddress& value);
+		/// Returns the value of the socket option
+		/// specified by level and option.
+
+	virtual void getRawOption(int level, int option, void* value, poco_socklen_t& length);
+		/// Returns the value of the socket option
+		/// specified by level and option.
+
+	void setLinger(bool on, int seconds);
+		/// Sets the value of the SO_LINGER socket option.
+
+	void getLinger(bool& on, int& seconds);
+		/// Returns the value of the SO_LINGER socket option.
+
+	void setNoDelay(bool flag);
+		/// Sets the value of the TCP_NODELAY socket option.
+
+	bool getNoDelay();
+		/// Returns the value of the TCP_NODELAY socket option.
+
+	void setKeepAlive(bool flag);
+		/// Sets the value of the SO_KEEPALIVE socket option.
+
+	bool getKeepAlive();
+		/// Returns the value of the SO_KEEPALIVE socket option.
+
+	void setReuseAddress(bool flag);
+		/// Sets the value of the SO_REUSEADDR socket option.
+
+	bool getReuseAddress();
+		/// Returns the value of the SO_REUSEADDR socket option.
+
+	void setReusePort(bool flag);
+		/// Sets the value of the SO_REUSEPORT socket option.
+		/// Does nothing if the socket implementation does not
+		/// support SO_REUSEPORT.
+
+	bool getReusePort();
+		/// Returns the value of the SO_REUSEPORT socket option.
+		///
+		/// Returns false if the socket implementation does not
+		/// support SO_REUSEPORT.
+
+	void setOOBInline(bool flag);
+		/// Sets the value of the SO_OOBINLINE socket option.
+
+	bool getOOBInline();
+		/// Returns the value of the SO_OOBINLINE socket option.
+
+	void setBroadcast(bool flag);
+		/// Sets the value of the SO_BROADCAST socket option.
+
+	bool getBroadcast();
+		/// Returns the value of the SO_BROADCAST socket option.
+
+	virtual void setBlocking(bool flag);
+		/// Sets the socket in blocking mode if flag is true,
+		/// disables blocking mode if flag is false.
+
+	virtual bool getBlocking() const;
+		/// Returns the blocking mode of the socket.
+		/// This method will only work if the blocking modes of
+		/// the socket are changed via the setBlocking method!
+
+	virtual bool secure() const;
+		/// Returns true iff the socket's connection is secure
+		/// (using SSL or TLS).
+
+	int socketError();
+		/// Returns the value of the SO_ERROR socket option.
+
+	poco_socket_t sockfd() const;
+		/// Returns the socket descriptor for the
+		/// underlying native socket.
+
+	void ioctl(poco_ioctl_request_t request, int& arg);
+		/// A wrapper for the ioctl system call.
+
+	void ioctl(poco_ioctl_request_t request, void* arg);
+		/// A wrapper for the ioctl system call.
+
+#if defined(POCO_OS_FAMILY_UNIX)
+	int fcntl(poco_fcntl_request_t request);
+		/// A wrapper for the fcntl system call.
+
+	int fcntl(poco_fcntl_request_t request, long arg);
+		/// A wrapper for the fcntl system call.
+#endif
+
+	bool initialized() const;
+		/// Returns true iff the underlying socket is initialized.
+
+protected:
+	SocketImpl();
+		/// Creates a SocketImpl.
+
+	SocketImpl(poco_socket_t sockfd);
+		/// Creates a SocketImpl using the given native socket.
+
+	virtual ~SocketImpl();
+		/// Destroys the SocketImpl.
+		/// Closes the socket if it is still open.
+
+	virtual void init(int af);
+		/// Creates the underlying native socket.
+		///
+		/// Subclasses must implement this method so
+		/// that it calls initSocket() with the
+		/// appropriate arguments.
+		///
+		/// The default implementation creates a
+		/// stream socket.
+
+	void initSocket(int af, int type, int proto = 0);
+		/// Creates the underlying native socket.
+		///
+		/// The first argument, af, specifies the address family
+		/// used by the socket, which should be either AF_INET or
+		/// AF_INET6.
+		///
+		/// The second argument, type, specifies the type of the
+		/// socket, which can be one of SOCK_STREAM, SOCK_DGRAM
+		/// or SOCK_RAW.
+		///
+		/// The third argument, proto, is normally set to 0,
+		/// except for raw sockets.
+
+	void reset(poco_socket_t fd = POCO_INVALID_SOCKET);
+		/// Allows subclasses to set the socket manually, iff no valid socket is set yet.
+
+	static int lastError();
+		/// Returns the last error code.
+
+	static void error();
+		/// Throws an appropriate exception for the last error.
+
+	static void error(const std::string& arg);
+		/// Throws an appropriate exception for the last error.
+
+	static void error(int code);
+		/// Throws an appropriate exception for the given error code.
+
+	static void error(int code, const std::string& arg);
+		/// Throws an appropriate exception for the given error code.
+
+private:
+	SocketImpl(const SocketImpl&);
+	SocketImpl& operator = (const SocketImpl&);
+
+	poco_socket_t _sockfd;
+	Poco::Timespan _recvTimeout;
+	Poco::Timespan _sndTimeout;
+	bool          _blocking;
+	bool          _isBrokenTimeout;
+
+	friend class Socket;
+	friend class SecureSocketImpl;
+	friend class PollSetImpl;
+};
+
+
+//
+// inlines
+//
+inline poco_socket_t SocketImpl::sockfd() const
+{
+	return _sockfd;
+}
+
+
+inline bool SocketImpl::initialized() const
+{
+	return _sockfd != POCO_INVALID_SOCKET;
+}
+
+
+inline int SocketImpl::lastError()
+{
+#if defined(_WIN32)
+	return WSAGetLastError();
+#else
+	return errno;
+#endif
+}
+
+
+inline bool SocketImpl::getBlocking() const
+{
+	return _blocking;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketImpl_INCLUDED
diff --git a/Poco/Net/SocketNotification.h b/Poco/Net/SocketNotification.h
new file mode 100644
index 0000000..7b857ec
--- /dev/null
+++ b/Poco/Net/SocketNotification.h
@@ -0,0 +1,153 @@
+//
+// SocketNotification.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  SocketNotification
+//
+// Definition of the SocketNotification class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketNotification_INCLUDED
+#define Net_SocketNotification_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/Notification.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class SocketReactor;
+
+
+class Net_API SocketNotification: public Poco::Notification
+	/// The base class for all notifications generated by
+	/// the SocketReactor.
+{
+public:
+	explicit SocketNotification(SocketReactor* pReactor);
+		/// Creates the SocketNotification for the given SocketReactor.
+
+	virtual ~SocketNotification();
+		/// Destroys the SocketNotification.
+		
+	SocketReactor& source() const;
+		/// Returns the SocketReactor that generated the notification.	
+		
+	Socket socket() const;
+		/// Returns the socket that caused the notification.
+
+private:
+	void setSocket(const Socket& socket);
+	
+	SocketReactor* _pReactor;
+	Socket         _socket;
+	
+	friend class SocketNotifier;
+};
+
+
+class Net_API ReadableNotification: public SocketNotification
+	/// This notification is sent if a socket has become readable.
+{
+public:
+	ReadableNotification(SocketReactor* pReactor);
+		/// Creates the ReadableNotification for the given SocketReactor.
+
+	~ReadableNotification();
+		/// Destroys the ReadableNotification.
+};
+
+
+class Net_API WritableNotification: public SocketNotification
+	/// This notification is sent if a socket has become writable.
+{
+public:
+	WritableNotification(SocketReactor* pReactor);
+		/// Creates the WritableNotification for the given SocketReactor.
+
+	~WritableNotification();
+		/// Destroys the WritableNotification.
+};
+
+
+class Net_API ErrorNotification: public SocketNotification
+	/// This notification is sent if a socket has signalled an error.
+{
+public:
+	ErrorNotification(SocketReactor* pReactor);
+		/// Creates the ErrorNotification for the given SocketReactor.
+
+	~ErrorNotification();
+		/// Destroys the ErrorNotification.
+};
+
+
+class Net_API TimeoutNotification: public SocketNotification
+	/// This notification is sent if no other event has occurred
+	/// for a specified time.
+{
+public:
+	TimeoutNotification(SocketReactor* pReactor);
+		/// Creates the TimeoutNotification for the given SocketReactor.
+
+	~TimeoutNotification();
+		/// Destroys the TimeoutNotification.
+};
+
+
+class Net_API IdleNotification: public SocketNotification
+	/// This notification is sent when the SocketReactor does
+	/// not have any sockets to react to.
+{
+public:
+	IdleNotification(SocketReactor* pReactor);
+		/// Creates the IdleNotification for the given SocketReactor.
+
+	~IdleNotification();
+		/// Destroys the IdleNotification.
+};
+
+
+class Net_API ShutdownNotification: public SocketNotification
+	/// This notification is sent when the SocketReactor is
+	/// about to shut down.
+{
+public:
+	ShutdownNotification(SocketReactor* pReactor);
+		/// Creates the ShutdownNotification for the given SocketReactor.
+
+	~ShutdownNotification();
+		/// Destroys the ShutdownNotification.
+};
+
+
+//
+// inlines
+//
+inline SocketReactor& SocketNotification::source() const
+{
+	return *_pReactor;
+}
+
+	
+inline Socket SocketNotification::socket() const
+{
+	return _socket;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketNotification_INCLUDED
diff --git a/Poco/Net/SocketNotifier.h b/Poco/Net/SocketNotifier.h
new file mode 100644
index 0000000..a98e407
--- /dev/null
+++ b/Poco/Net/SocketNotifier.h
@@ -0,0 +1,110 @@
+//
+// SocketNotifier.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  SocketNotifier
+//
+// Definition of the SocketNotifier class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketNotifier_INCLUDED
+#define Net_SocketNotifier_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/NotificationCenter.h"
+#include "Poco/Observer.h"
+#include <set>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Socket;
+class SocketReactor;
+class SocketNotification;
+
+
+class Net_API SocketNotifier: public Poco::RefCountedObject
+	/// This class is used internally by SocketReactor
+	/// to notify registered event handlers of socket events.
+{
+public:
+	explicit SocketNotifier(const Socket& socket);
+		/// Creates the SocketNotifier for the given socket.
+		
+	void addObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer);
+		/// Adds the given observer. 
+		
+	void removeObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer);
+		/// Removes the given observer. 
+		
+	bool hasObserver(const Poco::AbstractObserver& observer) const;
+		/// Returns true if the given observer is registered.
+		
+	bool accepts(SocketNotification* pNotification);
+		/// Returns true if there is at least one observer for the given notification.
+		
+	void dispatch(SocketNotification* pNotification);
+		/// Dispatches the notification to all observers.
+		
+	bool hasObservers() const;
+		/// Returns true if there are subscribers.
+		
+	std::size_t countObservers() const;
+		/// Returns the number of subscribers;
+
+protected:
+	~SocketNotifier();
+		/// Destroys the SocketNotifier.
+
+private:
+	typedef std::multiset<SocketNotification*> EventSet;
+
+	EventSet                 _events;
+	Poco::NotificationCenter _nc;
+	Socket                   _socket;
+};
+
+
+//
+// inlines
+//
+inline bool SocketNotifier::accepts(SocketNotification* pNotification)
+{
+	return _events.find(pNotification) != _events.end();
+}
+
+
+inline bool SocketNotifier::hasObserver(const Poco::AbstractObserver& observer) const
+{
+	return _nc.hasObserver(observer);
+}
+
+
+inline bool SocketNotifier::hasObservers() const
+{
+	return _nc.hasObservers();
+}
+
+
+inline std::size_t SocketNotifier::countObservers() const
+{
+	return _nc.countObservers();
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketNotifier_INCLUDED
diff --git a/Poco/Net/SocketReactor.h b/Poco/Net/SocketReactor.h
new file mode 100644
index 0000000..06c40bb
--- /dev/null
+++ b/Poco/Net/SocketReactor.h
@@ -0,0 +1,235 @@
+//
+// SocketReactor.h
+//
+// Library: Net
+// Package: Reactor
+// Module:  SocketReactor
+//
+// Definition of the SocketReactor class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketReactor_INCLUDED
+#define Net_SocketReactor_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/Runnable.h"
+#include "Poco/Timespan.h"
+#include "Poco/Observer.h"
+#include "Poco/AutoPtr.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Thread;
+
+
+namespace Net {
+
+
+class Socket;
+class SocketNotification;
+class SocketNotifier;
+
+
+class Net_API SocketReactor: public Poco::Runnable
+	/// This class, which is part of the Reactor pattern,
+	/// implements the "Initiation Dispatcher".
+	///
+	/// The Reactor pattern has been described in the book
+	/// "Pattern Languages of Program Design" by Jim Coplien
+	/// and Douglas C. Schmidt (Addison Wesley, 1995).
+	///
+	/// The Reactor design pattern handles service requests that
+	/// are delivered concurrently to an application by one or more
+	/// clients. Each service in an application may consist of several
+	/// methods and is represented by a separate event handler. The event
+	/// handler is responsible for servicing service-specific requests.
+	/// The SocketReactor dispatches the event handlers.
+	///
+	/// Event handlers (any class can be an event handler - there
+	/// is no base class for event handlers) can be registered
+	/// with the addEventHandler() method and deregistered with
+	/// the removeEventHandler() method.
+	/// 
+	/// An event handler is always registered for a certain socket,
+	/// which is given in the call to addEventHandler(). Any method
+	/// of the event handler class can be registered to handle the
+	/// event - the only requirement is that the method takes
+	/// a pointer to an instance of SocketNotification (or a subclass of it)
+	/// as argument.
+	///
+	/// Once started, the SocketReactor waits for events
+	/// on the registered sockets, using Socket::select().
+	/// If an event is detected, the corresponding event handler
+	/// is invoked. There are five event types (and corresponding
+	/// notification classes) defined: ReadableNotification, WritableNotification,
+	/// ErrorNotification, TimeoutNotification, IdleNotification and 
+	/// ShutdownNotification.
+	/// 
+	/// The ReadableNotification will be dispatched if a socket becomes
+	/// readable. The WritableNotification will be dispatched if a socket
+	/// becomes writable. The ErrorNotification will be dispatched if
+	/// there is an error condition on a socket.
+	///
+	/// If the timeout expires and no event has occurred, a
+	/// TimeoutNotification will be dispatched to all event handlers
+	/// registered for it. This is done in the onTimeout() method
+	/// which can be overridden by subclasses to perform custom
+	/// timeout processing.
+	///
+	/// If there are no sockets for the SocketReactor to pass to
+	/// Socket::select(), an IdleNotification will be dispatched to
+	/// all event handlers registered for it. This is done in the
+	/// onIdle() method which can be overridden by subclasses
+	/// to perform custom idle processing. Since onIdle() will be
+	/// called repeatedly in a loop, it is recommended to do a
+	/// short sleep or yield in the event handler.
+	///
+	/// Finally, when the SocketReactor is about to shut down (as a result 
+	/// of stop() being called), it dispatches a ShutdownNotification
+	/// to all event handlers. This is done in the onShutdown() method
+	/// which can be overridded by subclasses to perform custom
+	/// shutdown processing.
+	///
+	/// The SocketReactor is implemented so that it can 
+	/// run in its own thread. It is also possible to run
+	/// multiple SocketReactors in parallel, as long as
+	/// they work on different sockets.
+	///
+	/// It is safe to call addEventHandler() and removeEventHandler()
+	/// from another thread while the SocketReactor is running. Also,
+	/// it is safe to call addEventHandler() and removeEventHandler()
+	/// from event handlers.
+{
+public:
+	SocketReactor();
+		/// Creates the SocketReactor.
+
+	explicit SocketReactor(const Poco::Timespan& timeout);
+		/// Creates the SocketReactor, using the given timeout.
+
+	virtual ~SocketReactor();
+		/// Destroys the SocketReactor.
+
+	void run();
+		/// Runs the SocketReactor. The reactor will run
+		/// until stop() is called (in a separate thread).
+		
+	void stop();
+		/// Stops the SocketReactor.
+		///
+		/// The reactor will be stopped when the next event
+		/// (including a timeout event) occurs.
+
+	void wakeUp();
+		/// Wakes up idle reactor.
+
+	void setTimeout(const Poco::Timespan& timeout);
+		/// Sets the timeout. 
+		///
+		/// If no other event occurs for the given timeout 
+		/// interval, a timeout event is sent to all event listeners.
+		///
+		/// The default timeout is 250 milliseconds;
+		///
+		/// The timeout is passed to the Socket::select()
+		/// method.
+		
+	const Poco::Timespan& getTimeout() const;
+		/// Returns the timeout.
+
+	void addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer);
+		/// Registers an event handler with the SocketReactor.
+		///
+		/// Usage:
+		///     Poco::Observer<MyEventHandler, SocketNotification> obs(*this, &MyEventHandler::handleMyEvent);
+		///     reactor.addEventHandler(obs);
+
+	bool hasEventHandler(const Socket& socket, const Poco::AbstractObserver& observer);
+		/// Returns true if the observer is registered with SocketReactor for the given socket.
+
+	void removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer);
+		/// Unregisters an event handler with the SocketReactor.
+		///
+		/// Usage:
+		///     Poco::Observer<MyEventHandler, SocketNotification> obs(*this, &MyEventHandler::handleMyEvent);
+		///     reactor.removeEventHandler(obs);
+
+protected:
+	virtual void onTimeout();
+		/// Called if the timeout expires and no other events are available.
+		///
+		/// Can be overridden by subclasses. The default implementation
+		/// dispatches the TimeoutNotification and thus should be called by overriding
+		/// implementations.
+
+	virtual void onIdle();
+		/// Called if no sockets are available to call select() on.
+		///
+		/// Can be overridden by subclasses. The default implementation
+		/// dispatches the IdleNotification and thus should be called by overriding
+		/// implementations.
+
+	virtual void onShutdown();
+		/// Called when the SocketReactor is about to terminate.
+		///
+		/// Can be overridden by subclasses. The default implementation
+		/// dispatches the ShutdownNotification and thus should be called by overriding
+		/// implementations.
+
+	virtual void onBusy();
+		/// Called when the SocketReactor is busy and at least one notification
+		/// has been dispatched.
+		///
+		/// Can be overridden by subclasses to perform additional
+		/// periodic tasks. The default implementation does nothing.
+
+	void dispatch(const Socket& socket, SocketNotification* pNotification);
+		/// Dispatches the given notification to all observers
+		/// registered for the given socket.
+		
+	void dispatch(SocketNotification* pNotification);
+		/// Dispatches the given notification to all observers.
+
+private:
+	typedef Poco::AutoPtr<SocketNotifier>     NotifierPtr;
+	typedef Poco::AutoPtr<SocketNotification> NotificationPtr;
+	typedef std::map<Socket, NotifierPtr>     EventHandlerMap;
+
+	void dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification);
+
+	enum
+	{
+		DEFAULT_TIMEOUT = 250000
+	};
+
+	bool            _stop;
+	Poco::Timespan  _timeout;
+	EventHandlerMap _handlers;
+	NotificationPtr _pReadableNotification;
+	NotificationPtr _pWritableNotification;
+	NotificationPtr _pErrorNotification;
+	NotificationPtr _pTimeoutNotification;
+	NotificationPtr _pIdleNotification;
+	NotificationPtr _pShutdownNotification;
+	Poco::FastMutex _mutex;
+	Poco::Thread*   _pThread;
+	
+	friend class SocketNotifier;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketReactor_INCLUDED
diff --git a/Poco/Net/SocketStream.h b/Poco/Net/SocketStream.h
new file mode 100644
index 0000000..5a9a62c
--- /dev/null
+++ b/Poco/Net/SocketStream.h
@@ -0,0 +1,177 @@
+//
+// SocketStream.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  SocketStream
+//
+// Definition of the SocketStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_SocketStream_INCLUDED
+#define Net_SocketStream_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/BufferedBidirectionalStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class StreamSocketImpl;
+
+
+class Net_API SocketStreamBuf: public Poco::BufferedBidirectionalStreamBuf
+	/// This is the streambuf class used for reading from and writing to a socket.
+{
+public:
+	SocketStreamBuf(const Socket& socket);
+		/// Creates a SocketStreamBuf with the given socket.
+		///
+		/// The socket's SocketImpl must be a StreamSocketImpl,
+		/// otherwise an InvalidArgumentException is thrown.
+
+	~SocketStreamBuf();
+		/// Destroys the SocketStreamBuf.
+		
+	StreamSocketImpl* socketImpl() const;
+		/// Returns the internal SocketImpl.
+	
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE = 1024
+	};
+
+	StreamSocketImpl* _pImpl;
+};
+
+
+class Net_API SocketIOS: public virtual std::ios
+	/// The base class for SocketStream, SocketInputStream and
+	/// SocketOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	SocketIOS(const Socket& socket);
+		/// Creates the SocketIOS with the given socket.
+		///
+		/// The socket's SocketImpl must be a StreamSocketImpl,
+		/// otherwise an InvalidArgumentException is thrown.
+		
+	~SocketIOS();
+		/// Destroys the SocketIOS.
+		///
+		/// Flushes the buffer, but does not close the socket.
+		
+	SocketStreamBuf* rdbuf();
+		/// Returns a pointer to the internal SocketStreamBuf.
+		
+	void close();
+		/// Flushes the stream and closes the socket.
+		
+	StreamSocket socket() const;
+		/// Returns the underlying socket.
+
+protected:
+	SocketStreamBuf _buf;
+};
+
+
+class Net_API SocketOutputStream: public SocketIOS, public std::ostream
+	/// An output stream for writing to a socket.
+{
+public:
+	explicit SocketOutputStream(const Socket& socket);
+		/// Creates the SocketOutputStream with the given socket.
+		///
+		/// The socket's SocketImpl must be a StreamSocketImpl,
+		/// otherwise an InvalidArgumentException is thrown.
+
+	~SocketOutputStream();
+		/// Destroys the SocketOutputStream.
+		///
+		/// Flushes the buffer, but does not close the socket.
+};
+
+
+class Net_API SocketInputStream: public SocketIOS, public std::istream
+	/// An input stream for reading from a socket.
+	///
+	/// When using formatted input from a SocketInputStream,
+	/// always ensure that a receive timeout is set for the
+	/// socket. Otherwise your program might unexpectedly
+	/// hang.
+	///
+	/// However, using formatted input from a SocketInputStream
+	/// is not recommended, due to the read-ahead behavior of
+	/// istream with formatted reads.
+{
+public:
+	explicit SocketInputStream(const Socket& socket);
+		/// Creates the SocketInputStream with the given socket.
+		///
+		/// The socket's SocketImpl must be a StreamSocketImpl,
+		/// otherwise an InvalidArgumentException is thrown.
+
+	~SocketInputStream();
+		/// Destroys the SocketInputStream.
+};
+
+
+class Net_API SocketStream: public SocketIOS, public std::iostream
+	/// An bidirectional stream for reading from and writing to a socket.
+	///
+	/// When using formatted input from a SocketStream,
+	/// always ensure that a receive timeout is set for the
+	/// socket. Otherwise your program might unexpectedly
+	/// hang.
+	///
+	/// However, using formatted input from a SocketStream
+	/// is not recommended, due to the read-ahead behavior of
+	/// istream with formatted reads.
+{
+public:
+	explicit SocketStream(const Socket& socket);
+		/// Creates the SocketStream with the given socket.
+		///
+		/// The socket's SocketImpl must be a StreamSocketImpl,
+		/// otherwise an InvalidArgumentException is thrown.
+
+	~SocketStream();
+		/// Destroys the SocketStream.
+		///
+		/// Flushes the buffer, but does not close the socket.
+};
+
+
+//
+// inlines
+//
+inline StreamSocketImpl* SocketStreamBuf::socketImpl() const
+{
+	return _pImpl;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_SocketStream_INCLUDED
diff --git a/Poco/Net/StreamSocket.h b/Poco/Net/StreamSocket.h
new file mode 100644
index 0000000..46374d8
--- /dev/null
+++ b/Poco/Net/StreamSocket.h
@@ -0,0 +1,180 @@
+//
+// StreamSocket.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  StreamSocket
+//
+// Definition of the StreamSocket class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_StreamSocket_INCLUDED
+#define Net_StreamSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/Socket.h"
+#include "Poco/FIFOBuffer.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class StreamSocketImpl;
+
+
+class Net_API StreamSocket: public Socket
+	/// This class provides an interface to a
+	/// TCP stream socket.
+{
+public:
+	StreamSocket();
+		/// Creates an unconnected stream socket.
+		///
+		/// Before sending or receiving data, the socket
+		/// must be connected with a call to connect().
+
+	explicit StreamSocket(const SocketAddress& address);
+		/// Creates a stream socket and connects it to
+		/// the socket specified by address.
+
+	explicit StreamSocket(SocketAddress::Family family);
+		/// Creates an unconnected stream socket
+		/// for the given address family.
+		///
+		/// This is useful if certain socket options
+		/// (like send and receive buffer) sizes, that must 
+		/// be set before connecting the socket, will be
+		/// set later on.
+
+	StreamSocket(const Socket& socket);
+		/// Creates the StreamSocket with the SocketImpl
+		/// from another socket. The SocketImpl must be
+		/// a StreamSocketImpl, otherwise an InvalidArgumentException
+		/// will be thrown.
+
+	virtual ~StreamSocket();
+		/// Destroys the StreamSocket.
+
+	StreamSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// Releases the socket's SocketImpl and
+		/// attaches the SocketImpl from the other socket and
+		/// increments the reference count of the SocketImpl.	
+
+	void connect(const SocketAddress& address);
+		/// Initializes the socket and establishes a connection to 
+		/// the TCP server at the given address.
+		///
+		/// Can also be used for UDP sockets. In this case, no
+		/// connection is established. Instead, incoming and outgoing
+		/// packets are restricted to the specified address.
+
+	void connect(const SocketAddress& address, const Poco::Timespan& timeout);
+		/// Initializes the socket, sets the socket timeout and 
+		/// establishes a connection to the TCP server at the given address.
+
+	void connectNB(const SocketAddress& address);
+		/// Initializes the socket and establishes a connection to 
+		/// the TCP server at the given address. Prior to opening the
+		/// connection the socket is set to nonblocking mode.
+
+	void shutdownReceive();
+		/// Shuts down the receiving part of the socket connection.
+		
+	void shutdownSend();
+		/// Shuts down the sending part of the socket connection.
+		
+	void shutdown();
+		/// Shuts down both the receiving and the sending part
+		/// of the socket connection.
+	
+	int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Sends the contents of the given buffer through
+		/// the socket.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+		///
+		/// Certain socket implementations may also return a negative
+		/// value denoting a certain condition.
+
+	int sendBytes(Poco::FIFOBuffer& buffer);
+		/// Sends the contents of the given buffer through
+		/// the socket. FIFOBuffer has writable/readable transition
+		/// notifications which may be enabled to notify the caller when
+		/// the buffer transitions between empty, partially full and
+		/// full states.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+		///
+		/// Certain socket implementations may also return a negative
+		/// value denoting a certain condition.
+
+	int receiveBytes(void* buffer, int length, int flags = 0);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received.
+		///
+		/// Returns the number of bytes received. 
+		/// A return value of 0 means a graceful shutdown 
+		/// of the connection from the peer.
+		///
+		/// Throws a TimeoutException if a receive timeout has
+		/// been set and nothing is received within that interval.
+		/// Throws a NetException (or a subclass) in case of other errors.
+
+	int receiveBytes(Poco::FIFOBuffer& buffer);
+		/// Receives data from the socket and stores it
+		/// in buffer. Up to length bytes are received. FIFOBuffer has 
+		/// writable/readable transition notifications which may be enabled 
+		/// to notify the caller when the buffer transitions between empty, 
+		/// partially full and full states.
+		///
+		/// Returns the number of bytes received. 
+		/// A return value of 0 means a graceful shutdown 
+		/// of the connection from the peer.
+		///
+		/// Throws a TimeoutException if a receive timeout has
+		/// been set and nothing is received within that interval.
+		/// Throws a NetException (or a subclass) in case of other errors.
+
+	void sendUrgent(unsigned char data);
+		/// Sends one byte of urgent data through
+		/// the socket.
+		///
+		/// The data is sent with the MSG_OOB flag.
+		///
+		/// The preferred way for a socket to receive urgent data
+		/// is by enabling the SO_OOBINLINE option.
+
+	StreamSocket(SocketImpl* pImpl);
+		/// Creates the Socket and attaches the given SocketImpl.
+		/// The socket takes ownership of the SocketImpl.
+		///
+		/// The SocketImpl must be a StreamSocketImpl, otherwise
+		/// an InvalidArgumentException will be thrown.
+
+private:
+	enum
+	{
+		BUFFER_SIZE = 1024
+	};
+
+	friend class ServerSocket;
+	friend class SocketIOS;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_StreamSocket_INCLUDED
diff --git a/Poco/Net/StreamSocketImpl.h b/Poco/Net/StreamSocketImpl.h
new file mode 100644
index 0000000..eb41969
--- /dev/null
+++ b/Poco/Net/StreamSocketImpl.h
@@ -0,0 +1,59 @@
+//
+// StreamSocketImpl.h
+//
+// Library: Net
+// Package: Sockets
+// Module:  StreamSocketImpl
+//
+// Definition of the StreamSocketImpl class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_StreamSocketImpl_INCLUDED
+#define Net_StreamSocketImpl_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/SocketImpl.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API StreamSocketImpl: public SocketImpl
+	/// This class implements a TCP socket.
+{
+public:
+	StreamSocketImpl();
+		/// Creates a StreamSocketImpl.
+
+	explicit StreamSocketImpl(SocketAddress::Family addressFamily);
+		/// Creates a SocketImpl, with the underlying
+		/// socket initialized for the given address family.
+		
+	StreamSocketImpl(poco_socket_t sockfd);
+		/// Creates a StreamSocketImpl using the given native socket.
+		
+	virtual int sendBytes(const void* buffer, int length, int flags = 0);
+		/// Ensures that all data in buffer is sent if the socket
+		/// is blocking. In case of a non-blocking socket, sends as
+		/// many bytes as possible.
+		///
+		/// Returns the number of bytes sent. The return value may also be
+		/// negative to denote some special condition.
+
+protected:
+	virtual ~StreamSocketImpl();
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_StreamSocketImpl_INCLUDED
diff --git a/Poco/Net/StringPartSource.h b/Poco/Net/StringPartSource.h
new file mode 100644
index 0000000..8f2b478
--- /dev/null
+++ b/Poco/Net/StringPartSource.h
@@ -0,0 +1,71 @@
+//
+// StringPartSource.h
+//
+// Library: Net
+// Package: Messages
+// Module:  StringPartSource
+//
+// Definition of the StringPartSource class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_StringPartSource_INCLUDED
+#define Net_StringPartSource_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/PartSource.h"
+#include <sstream>
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API StringPartSource: public PartSource
+	/// An implementation of PartSource for strings.
+{
+public:
+	StringPartSource(const std::string& str);
+		/// Creates the StringPartSource for the given string.
+		///
+		/// The MIME type is set to text/plain.
+	
+	StringPartSource(const std::string& str, const std::string& mediaType);
+		/// Creates the StringPartSource for the given
+		/// string and MIME type.
+
+	StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename);
+		/// Creates the StringPartSource for the given
+		/// string, MIME type and filename.
+
+	~StringPartSource();
+		/// Destroys the StringPartSource.
+
+	std::istream& stream();
+		/// Returns a string input stream for the string.
+		
+	const std::string& filename() const;
+		/// Returns the filename portion of the path.
+
+	std::streamsize getContentLength() const;
+		/// Returns the string size.
+
+private:
+	std::istringstream _istr;
+	std::string        _filename;
+	
+	StringPartSource(const StringPartSource&);
+	StringPartSource& operator = (const StringPartSource&);
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_StringPartSource_INCLUDED
diff --git a/Poco/Net/TCPServer.h b/Poco/Net/TCPServer.h
new file mode 100644
index 0000000..973bdde
--- /dev/null
+++ b/Poco/Net/TCPServer.h
@@ -0,0 +1,258 @@
+//
+// TCPServer.h
+//
+// Library: Net
+// Package: TCPServer
+// Module:  TCPServer
+//
+// Definition of the TCPServer class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_TCPServer_INCLUDED
+#define Net_TCPServer_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Net/TCPServerConnectionFactory.h"
+#include "Poco/Net/TCPServerParams.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Runnable.h"
+#include "Poco/Thread.h"
+#include "Poco/ThreadPool.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class TCPServerDispatcher;
+class StreamSocket;
+
+
+class Net_API TCPServerConnectionFilter: public Poco::RefCountedObject
+	/// A TCPServerConnectionFilter can be used to reject incoming connections
+	/// before passing them on to the TCPServerDispatcher and
+	/// starting a thread to handle them.
+	///
+	/// An example use case is white-list or black-list IP address filtering.
+	///
+	/// Subclasses must override the accept() method.
+{
+public:
+	typedef Poco::AutoPtr<TCPServerConnectionFilter> Ptr;
+	
+	virtual bool accept(const StreamSocket& socket) = 0;
+		/// Returns true if the given StreamSocket connection should
+		/// be handled, and passed on to the TCPServerDispatcher.
+		///
+		/// Returns false if the socket should be closed immediately.
+		///
+		/// The socket can be prevented from being closed immediately
+		/// if false is returned by creating a copy of the socket.
+		/// This can be used to handle certain socket connections in
+		/// a special way, outside the TCPServer framework.
+
+protected:
+	virtual ~TCPServerConnectionFilter();
+};
+
+
+class Net_API TCPServer: public Poco::Runnable
+	/// This class implements a multithreaded TCP server.
+	///
+	/// The server uses a ServerSocket to listen for incoming
+	/// connections. The ServerSocket must have been bound to
+	/// an address before it is passed to the TCPServer constructor.
+	/// Additionally, the ServerSocket must be put into listening
+	/// state before the TCPServer is started by calling the start()
+	/// method.
+	///
+	/// The server uses a thread pool to assign threads to incoming
+	/// connections. Before incoming connections are assigned to
+	/// a connection thread, they are put into a queue.
+	/// Connection threads fetch new connections from the queue as soon
+	/// as they become free. Thus, a connection thread may serve more
+	/// than one connection.
+	///
+	/// As soon as a connection thread fetches the next connection from
+	/// the queue, it creates a TCPServerConnection object for it
+	/// (using the TCPServerConnectionFactory passed to the constructor)
+	/// and calls the TCPServerConnection's start() method. When the
+	/// start() method returns, the connection object is deleted.
+	///
+	/// The number of connection threads is adjusted dynamically, depending
+	/// on the number of connections waiting to be served.
+	///
+	/// It is possible to specify a maximum number of queued connections.
+	/// This prevents the connection queue from overflowing in the 
+	/// case of an extreme server load. In such a case, connections that
+	/// cannot be queued are silently and immediately closed.
+	///
+	/// TCPServer uses a separate thread to accept incoming connections.
+	/// Thus, the call to start() returns immediately, and the server
+	/// continues to run in the background.
+	///
+	/// To stop the server from accepting new connections, call stop().
+	///
+	/// After calling stop(), no new connections will be accepted and
+	/// all queued connections will be discarded.
+	/// Already served connections, however, will continue being served.
+{
+public:
+	TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber = 0, TCPServerParams::Ptr pParams = 0);
+		/// Creates the TCPServer, with ServerSocket listening on the given port.
+		/// Default port is zero, allowing any available port. The port number
+		/// can be queried through TCPServer::port() member.
+		///
+		/// The server takes ownership of the TCPServerConnectionFactory
+		/// and deletes it when it's no longer needed.
+		///
+		/// The server also takes ownership of the TCPServerParams object.
+		/// If no TCPServerParams object is given, the server's TCPServerDispatcher
+		/// creates its own one.
+		///
+		/// New threads are taken from the default thread pool.
+
+	TCPServer(TCPServerConnectionFactory::Ptr pFactory, const ServerSocket& socket, TCPServerParams::Ptr pParams = 0);
+		/// Creates the TCPServer, using the given ServerSocket.
+		///
+		/// The server takes ownership of the TCPServerConnectionFactory
+		/// and deletes it when it's no longer needed.
+		///
+		/// The server also takes ownership of the TCPServerParams object.
+		/// If no TCPServerParams object is given, the server's TCPServerDispatcher
+		/// creates its own one.
+		///
+		/// New threads are taken from the default thread pool.
+
+	TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams::Ptr pParams = 0);
+		/// Creates the TCPServer, using the given ServerSocket.
+		///
+		/// The server takes ownership of the TCPServerConnectionFactory
+		/// and deletes it when it's no longer needed.
+		///
+		/// The server also takes ownership of the TCPServerParams object.
+		/// If no TCPServerParams object is given, the server's TCPServerDispatcher
+		/// creates its own one.
+		///
+		/// New threads are taken from the given thread pool.
+
+	virtual ~TCPServer();
+		/// Destroys the TCPServer and its TCPServerConnectionFactory.
+
+	const TCPServerParams& params() const;
+		/// Returns a const reference to the TCPServerParam object
+		/// used by the server's TCPServerDispatcher.	
+
+	void start();
+		/// Starts the server. A new thread will be
+		/// created that waits for and accepts incoming
+		/// connections.
+		///
+		/// Before start() is called, the ServerSocket passed to
+		/// TCPServer must have been bound and put into listening state.
+
+	void stop();
+		/// Stops the server.
+		///
+		/// No new connections will be accepted.
+		/// Already handled connections will continue to be served.
+		///
+		/// Once the server has been stopped, it cannot be restarted.
+		
+	int currentThreads() const;
+		/// Returns the number of currently used connection threads.
+
+	int maxThreads() const;
+		/// Returns the maximum number of threads available.
+
+	int totalConnections() const;
+		/// Returns the total number of handled connections.
+		
+	int currentConnections() const;
+		/// Returns the number of currently handled connections.
+
+	int maxConcurrentConnections() const;
+		/// Returns the maximum number of concurrently handled connections.	
+		
+	int queuedConnections() const;
+		/// Returns the number of queued connections.
+
+	int refusedConnections() const;
+		/// Returns the number of refused connections.
+
+	const ServerSocket& socket() const;
+		/// Returns the underlying server socket.
+
+	Poco::UInt16 port() const;
+		/// Returns the port the server socket listens on.
+
+	void setConnectionFilter(const TCPServerConnectionFilter::Ptr& pFilter);
+		/// Sets a TCPServerConnectionFilter. Can also be used to remove
+		/// a filter by passing a null pointer.
+		///
+		/// To avoid a potential race condition, the filter must
+		/// be set before the TCPServer is started. Trying to set
+		/// the filter after start() has been called will trigger
+		/// an assertion.
+		
+	TCPServerConnectionFilter::Ptr getConnectionFilter() const;
+		/// Returns the TCPServerConnectionFilter set with setConnectionFilter(), 
+		/// or null pointer if no filter has been set.
+
+protected:
+	void run();
+		/// Runs the server. The server will run until
+		/// the stop() method is called, or the server
+		/// object is destroyed, which implicitly calls
+		/// the stop() method.
+
+	static std::string threadName(const ServerSocket& socket);
+		/// Returns a thread name for the server thread.
+
+private:
+	TCPServer();
+	TCPServer(const TCPServer&);
+	TCPServer& operator = (const TCPServer&);
+	
+	ServerSocket _socket;
+	TCPServerDispatcher* _pDispatcher;
+	TCPServerConnectionFilter::Ptr _pConnectionFilter;
+	Poco::Thread _thread;
+	bool _stopped;
+};
+
+
+//
+// inlines
+//
+inline const ServerSocket& TCPServer::socket() const
+{
+	return _socket;
+}
+
+
+inline Poco::UInt16 TCPServer::port() const
+{
+	return _socket.address().port();
+}
+
+
+inline TCPServerConnectionFilter::Ptr TCPServer::getConnectionFilter() const
+{
+	return _pConnectionFilter;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_TCPServer_INCLUDED
diff --git a/Poco/Net/TCPServerConnection.h b/Poco/Net/TCPServerConnection.h
new file mode 100644
index 0000000..380edcc
--- /dev/null
+++ b/Poco/Net/TCPServerConnection.h
@@ -0,0 +1,86 @@
+//
+// TCPServerConnection.h
+//
+// Library: Net
+// Package: TCPServer
+// Module:  TCPServerConnection
+//
+// Definition of the TCPServerConnection class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_TCPServerConnection_INCLUDED
+#define Net_TCPServerConnection_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Runnable.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API TCPServerConnection: public Poco::Runnable
+	/// The abstract base class for TCP server connections
+	/// created by TCPServer.
+	///
+	/// Derived classes must override the run() method
+	/// (inherited from Runnable). Furthermore, a
+	/// TCPServerConnectionFactory must be provided for the subclass.
+	///
+	/// The run() method must perform the complete handling
+	/// of the client connection. As soon as the run() method
+	/// returns, the server connection object is destroyed and
+	/// the connection is automatically closed.
+	///
+	/// A new TCPServerConnection object will be created for
+	/// each new client connection that is accepted by
+	/// TCPServer.
+{
+public:
+	TCPServerConnection(const StreamSocket& socket);
+		/// Creates the TCPServerConnection using the given
+		/// stream socket.
+
+	virtual ~TCPServerConnection();
+		/// Destroys the TCPServerConnection.
+
+protected:
+	StreamSocket& socket();
+		/// Returns a reference to the underlying socket.
+
+	void start();
+		/// Calls run() and catches any exceptions that
+		/// might be thrown by run().
+
+private:
+	TCPServerConnection();
+	TCPServerConnection(const TCPServerConnection&);
+	TCPServerConnection& operator = (const TCPServerConnection&);
+	
+	StreamSocket _socket;
+	
+	friend class TCPServerDispatcher;
+};
+
+
+//
+// inlines
+//
+inline StreamSocket& TCPServerConnection::socket()
+{
+	return _socket;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_TCPServerConnection_INCLUDED
diff --git a/Poco/Net/TCPServerConnectionFactory.h b/Poco/Net/TCPServerConnectionFactory.h
new file mode 100644
index 0000000..8fc4d6b
--- /dev/null
+++ b/Poco/Net/TCPServerConnectionFactory.h
@@ -0,0 +1,89 @@
+//
+// TCPServerConnectionFactory.h
+//
+// Library: Net
+// Package: TCPServer
+// Module:  TCPServerConnectionFactory
+//
+// Definition of the TCPServerConnectionFactory class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_TCPServerConnectionFactory_INCLUDED
+#define Net_TCPServerConnectionFactory_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/TCPServerConnection.h"
+#include "Poco/SharedPtr.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API TCPServerConnectionFactory
+	/// A factory for TCPServerConnection objects.
+	///
+	/// The TCPServer class uses a TCPServerConnectionFactory
+	/// to create a connection object for each new connection
+	/// it accepts.
+	///
+	/// Subclasses must override the createConnection()
+	/// method.
+	///
+	/// The TCPServerConnectionFactoryImpl template class
+	/// can be used to automatically instantiate a
+	/// TCPServerConnectionFactory for a given subclass
+	/// of TCPServerConnection.
+{
+public:
+	typedef Poco::SharedPtr<TCPServerConnectionFactory> Ptr;
+	
+	virtual ~TCPServerConnectionFactory();
+		/// Destroys the TCPServerConnectionFactory.
+
+	virtual TCPServerConnection* createConnection(const StreamSocket& socket) = 0;
+		/// Creates an instance of a subclass of TCPServerConnection,
+		/// using the given StreamSocket.
+
+protected:
+	TCPServerConnectionFactory();
+		/// Creates the TCPServerConnectionFactory.
+
+private:
+	TCPServerConnectionFactory(const TCPServerConnectionFactory&);
+	TCPServerConnectionFactory& operator = (const TCPServerConnectionFactory&);
+};
+
+
+template <class S>
+class TCPServerConnectionFactoryImpl: public TCPServerConnectionFactory
+	/// This template provides a basic implementation of
+	/// TCPServerConnectionFactory.
+{
+public:
+	TCPServerConnectionFactoryImpl()
+	{
+	}
+	
+	~TCPServerConnectionFactoryImpl()
+	{
+	}
+	
+	TCPServerConnection* createConnection(const StreamSocket& socket)
+	{
+		return new S(socket);
+	}
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_TCPServerConnectionFactory_INCLUDED
diff --git a/Poco/Net/TCPServerDispatcher.h b/Poco/Net/TCPServerDispatcher.h
new file mode 100644
index 0000000..3c46d0f
--- /dev/null
+++ b/Poco/Net/TCPServerDispatcher.h
@@ -0,0 +1,130 @@
+//
+// TCPServerDispatcher.h
+//
+// Library: Net
+// Package: TCPServer
+// Module:  TCPServerDispatcher
+//
+// Definition of the TCPServerDispatcher class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_TCPServerDispatcher_INCLUDED
+#define Net_TCPServerDispatcher_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/TCPServerConnectionFactory.h"
+#include "Poco/Net/TCPServerParams.h"
+#include "Poco/Runnable.h"
+#include "Poco/NotificationQueue.h"
+#include "Poco/ThreadPool.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API TCPServerDispatcher: public Poco::Runnable
+	/// A helper class for TCPServer that dispatches
+	/// connections to server connection threads.
+{
+public:
+	TCPServerDispatcher(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, TCPServerParams::Ptr pParams);
+		/// Creates the TCPServerDispatcher.
+		///
+		/// The dispatcher takes ownership of the TCPServerParams object.
+		/// If no TCPServerParams object is supplied, the TCPServerDispatcher
+		/// creates one.
+
+	void duplicate();
+		/// Increments the object's reference count.
+
+	void release();
+		/// Decrements the object's reference count
+		/// and deletes the object if the count
+		/// reaches zero.	
+
+	void run();
+		/// Runs the dispatcher.
+		
+	void enqueue(const StreamSocket& socket);
+		/// Queues the given socket connection.
+
+	void stop();
+		/// Stops the dispatcher.
+			
+	int currentThreads() const;
+		/// Returns the number of currently used threads.
+
+	int maxThreads() const;
+		/// Returns the maximum number of threads available.
+		
+	int totalConnections() const;
+		/// Returns the total number of handled connections.
+		
+	int currentConnections() const;
+		/// Returns the number of currently handled connections.	
+
+	int maxConcurrentConnections() const;
+		/// Returns the maximum number of concurrently handled connections.	
+		
+	int queuedConnections() const;
+		/// Returns the number of queued connections.	
+	
+	int refusedConnections() const;
+		/// Returns the number of refused connections.
+
+	const TCPServerParams& params() const;
+		/// Returns a const reference to the TCPServerParam object.
+
+protected:
+	~TCPServerDispatcher();
+		/// Destroys the TCPServerDispatcher.
+
+	void beginConnection();
+		/// Updates the performance counters.
+		
+	void endConnection();
+		/// Updates the performance counters.
+
+private:
+	TCPServerDispatcher();
+	TCPServerDispatcher(const TCPServerDispatcher&);
+	TCPServerDispatcher& operator = (const TCPServerDispatcher&);
+
+	int _rc;
+	TCPServerParams::Ptr _pParams;
+	int  _currentThreads;
+	int  _totalConnections;
+	int  _currentConnections;
+	int  _maxConcurrentConnections;
+	int  _refusedConnections;
+	bool _stopped;
+	Poco::NotificationQueue         _queue;
+	TCPServerConnectionFactory::Ptr _pConnectionFactory;
+	Poco::ThreadPool&               _threadPool;
+	mutable Poco::FastMutex         _mutex;
+};
+
+
+//
+// inlines
+//
+inline const TCPServerParams& TCPServerDispatcher::params() const
+{
+	return *_pParams;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_TCPServerDispatcher_INCLUDED
diff --git a/Poco/Net/TCPServerParams.h b/Poco/Net/TCPServerParams.h
new file mode 100644
index 0000000..1c2057e
--- /dev/null
+++ b/Poco/Net/TCPServerParams.h
@@ -0,0 +1,137 @@
+//
+// TCPServerParams.h
+//
+// Library: Net
+// Package: TCPServer
+// Module:  TCPServerParams
+//
+// Definition of the TCPServerParams class.
+//
+// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_TCPServerParams_INCLUDED
+#define Net_TCPServerParams_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Timespan.h"
+#include "Poco/Thread.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class Net_API TCPServerParams: public Poco::RefCountedObject
+	/// This class is used to specify parameters to both the
+	/// TCPServer, as well as to TCPServerDispatcher objects.
+	///
+	/// Subclasses may add new parameters to the class.
+{
+public:
+	typedef Poco::AutoPtr<TCPServerParams> Ptr;
+	
+	TCPServerParams();
+		/// Creates the TCPServerParams.
+		///
+		/// Sets the following default values:
+		///   - threadIdleTime:       10 seconds
+		///   - maxThreads:           0
+		///   - maxQueued:            64
+
+	void setThreadIdleTime(const Poco::Timespan& idleTime);
+		/// Sets the maximum idle time for a thread before
+		/// it is terminated.
+		///
+		/// The default idle time is 10 seconds;
+		
+	const Poco::Timespan& getThreadIdleTime() const;
+		/// Returns the maximum thread idle time.
+
+	void setMaxQueued(int count);
+		/// Sets the maximum number of queued connections.
+		/// Must be greater than 0.
+		///
+		/// If there are already the maximum number of connections
+		/// in the queue, new connections will be silently discarded.
+		///
+		/// The default number is 64.
+		
+	int getMaxQueued() const;
+		/// Returns the maximum number of queued connections.
+
+	void setMaxThreads(int count);
+		/// Sets the maximum number of simultaneous threads
+		/// available for this TCPServerDispatcher.
+		///
+		/// Must be greater than or equal to 0.
+		/// If 0 is specified, the TCPServerDispatcher will
+		/// set this parameter to the number of available threads
+		/// in its thread pool.
+		///
+		/// The thread pool used by the TCPServerDispatcher
+		/// must at least have the capacity for the given
+		/// number of threads.
+		
+	int getMaxThreads() const;
+		/// Returns the maximum number of simultaneous threads
+		/// available for this TCPServerDispatcher.	
+		
+	void setThreadPriority(Poco::Thread::Priority prio);
+		/// Sets the priority of TCP server threads 
+		/// created by TCPServer.
+		
+	Poco::Thread::Priority getThreadPriority() const;
+		/// Returns the priority of TCP server threads
+		/// created by TCPServer. 
+
+protected:
+	virtual ~TCPServerParams();
+		/// Destroys the TCPServerParams.
+
+private:
+	Poco::Timespan _threadIdleTime;
+	int _maxThreads;
+	int _maxQueued;
+	Poco::Thread::Priority _threadPriority;
+};
+
+
+//
+// inlines
+//
+inline const Poco::Timespan& TCPServerParams::getThreadIdleTime() const
+{
+	return _threadIdleTime;
+}
+
+
+inline int TCPServerParams::getMaxThreads() const
+{
+	return _maxThreads;
+}
+
+
+inline int TCPServerParams::getMaxQueued() const
+{
+	return _maxQueued;
+}
+
+
+inline Poco::Thread::Priority TCPServerParams::getThreadPriority() const
+{
+	return _threadPriority;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_TCPServerParams_INCLUDED
diff --git a/Poco/Net/Utility.h b/Poco/Net/Utility.h
new file mode 100644
index 0000000..b1d0073
--- /dev/null
+++ b/Poco/Net/Utility.h
@@ -0,0 +1,52 @@
+//
+// Utility.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  Utility
+//
+// Definition of the Utility class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_Utility_INCLUDED
+#define NetSSL_Utility_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/Context.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API Utility
+	/// This class provides various helper functions for working
+	/// with the OpenSSL library.
+{
+public:
+	static Context::VerificationMode convertVerificationMode(const std::string& verMode);
+		/// Non-case sensitive conversion of a string to a VerificationMode enum.
+		/// If verMode is illegal an InvalidArgumentException is thrown.
+
+	static std::string convertCertificateError(long errCode);
+		/// Converts an SSL certificate handling error code into an error message.
+
+	static std::string getLastError();
+		/// Returns the last error from the error stack
+
+	static void clearErrorStack();
+		/// Clears the error stack
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_Utility_INCLUDED
diff --git a/Poco/Net/VerificationErrorArgs.h b/Poco/Net/VerificationErrorArgs.h
new file mode 100644
index 0000000..55ef897
--- /dev/null
+++ b/Poco/Net/VerificationErrorArgs.h
@@ -0,0 +1,108 @@
+//
+// VerificationErrorArgs.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  VerificationErrorArgs
+//
+// Definition of the VerificationErrorArgs class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_VerificationErrorArgs_INCLUDED
+#define NetSSL_VerificationErrorArgs_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/X509Certificate.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class NetSSL_API VerificationErrorArgs
+	/// A utility class for certificate error handling.
+{
+public:
+	VerificationErrorArgs(const X509Certificate& cert, int errDepth, int errNum, const std::string& errMsg);
+		/// Creates the VerificationErrorArgs. _ignoreError is per default set to false.
+
+	~VerificationErrorArgs();
+		/// Destroys the VerificationErrorArgs.
+
+	const X509Certificate& certificate() const;
+		/// Returns the certificate that caused the error.
+
+	int errorDepth() const;
+		/// Returns the position of the certificate in the certificate chain.
+
+	int errorNumber() const;
+		/// Returns the id of the error
+
+	const std::string& errorMessage() const;
+		/// Returns the textual presentation of the errorNumber.
+
+	void setIgnoreError(bool ignoreError);
+		/// setIgnoreError to true, if a verification error is judged non-fatal by the user.
+
+	bool getIgnoreError() const;
+		/// returns the value of _ignoreError
+
+private:
+	X509Certificate	_cert;
+	int             _errorDepth;
+	int             _errorNumber;
+	std::string     _errorMessage; /// Textual representation of the _errorNumber
+	bool            _ignoreError;
+};
+
+
+//
+// inlines
+//
+inline const X509Certificate& VerificationErrorArgs::certificate() const
+{
+	return _cert;
+}
+
+
+inline int VerificationErrorArgs::errorDepth() const
+{
+	return _errorDepth;
+}
+
+
+inline int VerificationErrorArgs::errorNumber() const
+{
+	return _errorNumber;
+}
+
+
+inline const std::string& VerificationErrorArgs::errorMessage() const
+{
+	return _errorMessage;
+}
+
+
+inline void VerificationErrorArgs::setIgnoreError(bool ignoreError)
+{
+	_ignoreError = ignoreError;
+}
+
+
+inline bool VerificationErrorArgs::getIgnoreError() const
+{
+	return _ignoreError;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_VerificationErrorArgs_INCLUDED
diff --git a/Poco/Net/WebSocket.h b/Poco/Net/WebSocket.h
new file mode 100644
index 0000000..5d3f05d
--- /dev/null
+++ b/Poco/Net/WebSocket.h
@@ -0,0 +1,297 @@
+//
+// WebSocket.h
+//
+// Library: Net
+// Package: WebSocket
+// Module:  WebSocket
+//
+// Definition of the WebSocket class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_WebSocket_INCLUDED
+#define Net_WebSocket_INCLUDED
+
+
+#include "Poco/Net/Net.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/HTTPCredentials.h"
+#include "Poco/Buffer.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class WebSocketImpl;
+class HTTPServerRequest;
+class HTTPServerResponse;
+class HTTPClientSession;
+
+
+class Net_API WebSocket: public StreamSocket
+	/// This class implements a WebSocket according
+	/// to the WebSocket protocol specification in RFC 6455.
+	///
+	/// Both client-side and server-side WebSockets
+	/// are supported.
+	///
+	/// Server-side WebSockets are usually created from within
+	/// a HTTPRequestHandler.
+	///
+	/// Client-side WebSockets are created using a HTTPClientSession.
+	///
+	/// Note that special frames like PING must be handled at
+	/// application level. In the case of a PING, a PONG message
+	/// must be returned.
+{
+public:
+	enum Mode
+	{
+		WS_SERVER, /// Server-side WebSocket.
+		WS_CLIENT  /// Client-side WebSocket.
+	};
+
+	enum FrameFlags
+		/// Frame header flags.
+	{
+		FRAME_FLAG_FIN  = 0x80, /// FIN bit: final fragment of a multi-fragment message.
+		FRAME_FLAG_RSV1 = 0x40, /// Reserved for future use. Must be zero.
+		FRAME_FLAG_RSV2 = 0x20, /// Reserved for future use. Must be zero.
+		FRAME_FLAG_RSV3 = 0x10  /// Reserved for future use. Must be zero.
+	};
+
+	enum FrameOpcodes
+		/// Frame header opcodes.
+	{
+		FRAME_OP_CONT    = 0x00, /// Continuation frame.
+		FRAME_OP_TEXT    = 0x01, /// Text frame.
+		FRAME_OP_BINARY  = 0x02, /// Binary frame.
+		FRAME_OP_CLOSE   = 0x08, /// Close connection.
+		FRAME_OP_PING    = 0x09, /// Ping frame.
+		FRAME_OP_PONG    = 0x0a, /// Pong frame.
+		FRAME_OP_BITMASK = 0x0f, /// Bit mask for opcodes.
+		FRAME_OP_SETRAW  = 0x100 /// Set raw flags (for use with sendBytes() and FRAME_OP_CONT).
+	};
+
+	enum SendFlags
+		/// Combined header flags and opcodes for use with sendFrame().
+	{
+		FRAME_TEXT   = FRAME_FLAG_FIN | FRAME_OP_TEXT,
+			/// Use this for sending a single text (UTF-8) payload frame.
+		FRAME_BINARY = FRAME_FLAG_FIN | FRAME_OP_BINARY
+			/// Use this for sending a single binary payload frame.
+	};
+
+	enum StatusCodes
+		/// StatusCodes for CLOSE frames sent with shutdown().
+	{
+		WS_NORMAL_CLOSE            = 1000,
+		WS_ENDPOINT_GOING_AWAY     = 1001,
+		WS_PROTOCOL_ERROR          = 1002,
+		WS_PAYLOAD_NOT_ACCEPTABLE  = 1003,
+		WS_RESERVED                = 1004,
+		WS_RESERVED_NO_STATUS_CODE = 1005,
+		WS_RESERVED_ABNORMAL_CLOSE = 1006,
+		WS_MALFORMED_PAYLOAD       = 1007,
+		WS_POLICY_VIOLATION        = 1008,
+		WS_PAYLOAD_TOO_BIG         = 1009,
+		WS_EXTENSION_REQUIRED      = 1010,
+		WS_UNEXPECTED_CONDITION    = 1011,
+		WS_RESERVED_TLS_FAILURE    = 1015
+	};
+
+	enum ErrorCodes
+		/// These error codes can be obtained from a WebSocketException
+		/// to determine the exact cause of the error.
+	{
+		WS_ERR_NO_HANDSHAKE                   = 1,
+			/// No Connection: Upgrade or Upgrade: websocket header in handshake request.
+		WS_ERR_HANDSHAKE_NO_VERSION           = 2,
+			/// No Sec-WebSocket-Version header in handshake request.
+		WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION  = 3,
+			/// Unsupported WebSocket version requested by client.
+		WS_ERR_HANDSHAKE_NO_KEY               = 4,
+			/// No Sec-WebSocket-Key header in handshake request.
+		WS_ERR_HANDSHAKE_ACCEPT               = 5,
+			/// No Sec-WebSocket-Accept header or wrong value.
+		WS_ERR_UNAUTHORIZED                   = 6,
+			/// The server rejected the username or password for authentication.
+		WS_ERR_PAYLOAD_TOO_BIG                = 10,
+			/// Payload too big for supplied buffer.
+		WS_ERR_INCOMPLETE_FRAME               = 11
+			/// Incomplete frame received.
+	};
+
+	WebSocket(HTTPServerRequest& request, HTTPServerResponse& response);
+		/// Creates a server-side WebSocket from within a
+		/// HTTPRequestHandler.
+		///
+		/// First verifies that the request is a valid WebSocket upgrade
+		/// request. If so, completes the handshake by sending
+		/// a proper 101 response.
+		///
+		/// Throws an exception if the request is not a proper WebSocket
+		/// upgrade request.
+
+	WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response);
+		/// Creates a client-side WebSocket, using the given
+		/// HTTPClientSession and HTTPRequest for the initial handshake
+		/// (HTTP Upgrade request).
+		///
+		/// Additional HTTP headers for the initial handshake request
+		/// (such as Origin or Sec-WebSocket-Protocol) can be given
+		/// in the request object.
+		///
+		/// The result of the handshake can be obtained from the response
+		/// object.
+
+	WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials);
+		/// Creates a client-side WebSocket, using the given
+		/// HTTPClientSession and HTTPRequest for the initial handshake
+		/// (HTTP Upgrade request).
+		///
+		/// The given credentials are used for authentication
+		/// if requested by the server.
+		///
+		/// Additional HTTP headers for the initial handshake request
+		/// (such as Origin or Sec-WebSocket-Protocol) can be given
+		/// in the request object.
+		///
+		/// The result of the handshake can be obtained from the response
+		/// object.
+
+	WebSocket(const Socket& socket);
+		/// Creates a WebSocket from another Socket, which must be a WebSocket,
+		/// otherwise a Poco::InvalidArgumentException will be thrown.
+
+	virtual ~WebSocket();
+		/// Destroys the StreamSocket.
+
+	WebSocket& operator = (const Socket& socket);
+		/// Assignment operator.
+		///
+		/// The other socket must be a WebSocket, otherwise a Poco::InvalidArgumentException
+		/// will be thrown.
+
+	void shutdown();
+		/// Sends a Close control frame to the server end of
+		/// the connection to initiate an orderly shutdown
+		/// of the connection.
+
+	void shutdown(Poco::UInt16 statusCode, const std::string& statusMessage = "");
+		/// Sends a Close control frame to the server end of
+		/// the connection to initiate an orderly shutdown
+		/// of the connection.
+
+	int sendFrame(const void* buffer, int length, int flags = FRAME_TEXT);
+		/// Sends the contents of the given buffer through
+		/// the socket as a single frame.
+		///
+		/// Values from the FrameFlags, FrameOpcodes and SendFlags enumerations
+		/// can be specified in flags.
+		///
+		/// Returns the number of bytes sent, which may be
+		/// less than the number of bytes specified.
+		///
+		/// Certain socket implementations may also return a negative
+		/// value denoting a certain condition.
+
+	int receiveFrame(void* buffer, int length, int& flags);
+		/// Receives a frame from the socket and stores it
+		/// in buffer. Up to length bytes are received. If
+		/// the frame's payload is larger, a WebSocketException
+		/// is thrown and the WebSocket connection must be
+		/// terminated.
+		///
+		/// The frame's payload size must not exceed the
+		/// maximum payload size set with setMaxPayloadSize().
+		/// If it does, a WebSocketException (WS_ERR_PAYLOAD_TOO_BIG)
+		/// is thrown and the WebSocket connection must be
+		/// terminated.
+		///
+		/// A WebSocketException will also be thrown if a malformed
+		/// or incomplete frame is received.
+		///
+		/// Returns the number of bytes received.
+		/// A return value of 0 means that the peer has
+		/// shut down or closed the connection.
+		///
+		/// Throws a TimeoutException if a receive timeout has
+		/// been set and nothing is received within that interval.
+		/// Throws a NetException (or a subclass) in case of other errors.
+		///
+		/// The frame flags and opcode (FrameFlags and FrameOpcodes)
+		/// is stored in flags.
+
+	int receiveFrame(Poco::Buffer<char>& buffer, int& flags);
+		/// Receives a frame from the socket and stores it
+		/// after any previous content in buffer.
+		/// The buffer will be grown as necessary.
+		///
+		/// The frame's payload size must not exceed the
+		/// maximum payload size set with setMaxPayloadSize().
+		/// If it does, a WebSocketException (WS_ERR_PAYLOAD_TOO_BIG)
+		/// is thrown and the WebSocket connection must be
+		/// terminated.
+		///
+		/// A WebSocketException will also be thrown if a malformed
+		/// or incomplete frame is received.
+		///
+		/// If this method is used, a reasonable maximum payload size should
+		/// be set with setMaxPayloadSize() to prevent a potential
+		/// DoS attack (memory exhaustion) by sending a WebSocket frame
+		/// header with a huge payload size.
+		///
+		/// Returns the number of bytes received.
+		/// A return value of 0 means that the peer has
+		/// shut down or closed the connection.
+		///
+		/// Throws a TimeoutException if a receive timeout has
+		/// been set and nothing is received within that interval.
+		/// Throws a NetException (or a subclass) in case of other errors.
+		///
+		/// The frame flags and opcode (FrameFlags and FrameOpcodes)
+		/// is stored in flags.
+
+	Mode mode() const;
+		/// Returns WS_SERVER if the WebSocket is a server-side
+		/// WebSocket, or WS_CLIENT otherwise.
+
+	void setMaxPayloadSize(int maxPayloadSize);
+		/// Sets the maximum payload size for receiveFrame().
+		///
+		/// The default is std::numeric_limits<int>::max().
+
+	int getMaxPayloadSize() const;
+		/// Returns the maximum payload size for receiveFrame().
+		///
+		/// The default is std::numeric_limits<int>::max().
+
+	static const std::string WEBSOCKET_VERSION;
+		/// The WebSocket protocol version supported (13).
+
+protected:
+	static WebSocketImpl* accept(HTTPServerRequest& request, HTTPServerResponse& response);
+	static WebSocketImpl* connect(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials);
+	static WebSocketImpl* completeHandshake(HTTPClientSession& cs, HTTPResponse& response, const std::string& key);
+	static std::string computeAccept(const std::string& key);
+	static std::string createKey();
+
+private:
+	WebSocket();
+
+	static const std::string WEBSOCKET_GUID;
+	static HTTPCredentials _defaultCreds;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_WebSocket_INCLUDED
diff --git a/Poco/Net/WebSocketImpl.h b/Poco/Net/WebSocketImpl.h
new file mode 100644
index 0000000..a2471c3
--- /dev/null
+++ b/Poco/Net/WebSocketImpl.h
@@ -0,0 +1,142 @@
+//
+// WebSocketImpl.h
+//
+// Library: Net
+// Package: WebSocket
+// Module:  WebSocketImpl
+//
+// Definition of the StreamSocketImpl class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Net_WebSocketImpl_INCLUDED
+#define Net_WebSocketImpl_INCLUDED
+
+
+#include "Poco/Net/StreamSocketImpl.h"
+#include "Poco/Buffer.h"
+#include "Poco/Random.h"
+#include "Poco/Buffer.h"
+
+
+namespace Poco {
+namespace Net {
+
+
+class HTTPSession;
+
+
+class Net_API WebSocketImpl: public StreamSocketImpl
+	/// This class implements a WebSocket, according
+	/// to the WebSocket protocol described in RFC 6455.
+{
+public:
+	WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload);
+		/// Creates a WebSocketImpl.
+
+	// StreamSocketImpl
+	virtual int sendBytes(const void* buffer, int length, int flags);
+		/// Sends a WebSocket protocol frame.
+
+	virtual int receiveBytes(void* buffer, int length, int flags);
+		/// Receives a WebSocket protocol frame.
+
+	virtual int receiveBytes(Poco::Buffer<char>& buffer, int flags);
+		/// Receives a WebSocket protocol frame.
+
+	virtual SocketImpl* acceptConnection(SocketAddress& clientAddr);
+	virtual void connect(const SocketAddress& address);
+	virtual void connect(const SocketAddress& address, const Poco::Timespan& timeout);
+	virtual void connectNB(const SocketAddress& address);
+	virtual void bind(const SocketAddress& address, bool reuseAddress = false);
+	virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort);
+	virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
+	virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only);
+	virtual void listen(int backlog = 64);
+	virtual void close();
+	virtual void shutdownReceive();
+	virtual void shutdownSend();
+	virtual void shutdown();
+	virtual int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0);
+	virtual int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0);
+	virtual void sendUrgent(unsigned char data);
+	virtual int available();
+	virtual bool secure() const;
+	virtual void setSendTimeout(const Poco::Timespan& timeout);
+	virtual Poco::Timespan getSendTimeout();
+	virtual void setReceiveTimeout(const Poco::Timespan& timeout);
+	virtual Poco::Timespan getReceiveTimeout();
+
+	// Internal
+	int frameFlags() const;
+		/// Returns the frame flags of the most recently received frame.
+
+	bool mustMaskPayload() const;
+		/// Returns true if the payload must be masked.
+
+	void setMaxPayloadSize(int maxPayloadSize);
+		/// Sets the maximum payload size for receiveFrame().
+		///
+		/// The default is std::numeric_limits<int>::max().
+
+	int getMaxPayloadSize() const;
+		/// Returns the maximum payload size for receiveFrame().
+		///
+		/// The default is std::numeric_limits<int>::max().
+
+protected:
+	enum
+	{
+		FRAME_FLAG_MASK   = 0x80,
+		MAX_HEADER_LENGTH = 14
+	};
+
+	int receiveHeader(char mask[4], bool& useMask);
+	int receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask);
+	int receiveNBytes(void* buffer, int bytes);
+	int receiveSomeBytes(char* buffer, int bytes);
+	virtual ~WebSocketImpl();
+
+private:
+	WebSocketImpl();
+
+	StreamSocketImpl* _pStreamSocketImpl;
+	int _maxPayloadSize;
+	Poco::Buffer<char> _buffer;
+	int _bufferOffset;
+	int _frameFlags;
+	bool _mustMaskPayload;
+	Poco::Random _rnd;
+};
+
+
+//
+// inlines
+//
+inline int WebSocketImpl::frameFlags() const
+{
+	return _frameFlags;
+}
+
+
+inline bool WebSocketImpl::mustMaskPayload() const
+{
+	return _mustMaskPayload;
+}
+
+
+inline int WebSocketImpl::getMaxPayloadSize() const
+{
+	return _maxPayloadSize;
+}
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_WebSocketImpl_INCLUDED
diff --git a/Poco/Net/X509Certificate.h b/Poco/Net/X509Certificate.h
new file mode 100644
index 0000000..a810b29
--- /dev/null
+++ b/Poco/Net/X509Certificate.h
@@ -0,0 +1,102 @@
+//
+// X509Certificate.h
+//
+// Library: NetSSL_OpenSSL
+// Package: SSLCore
+// Module:  X509Certificate
+//
+// Definition of the X509Certificate class.
+//
+// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef NetSSL_X509Certificate_INCLUDED
+#define NetSSL_X509Certificate_INCLUDED
+
+
+#include "Poco/Net/NetSSL.h"
+#include "Poco/Net/SocketDefs.h"
+#include "Poco/Crypto/X509Certificate.h"
+#include "Poco/DateTime.h"
+#include "Poco/SharedPtr.h"
+#include <set>
+
+
+namespace Poco {
+namespace Net {
+
+
+class HostEntry;
+
+
+class NetSSL_API X509Certificate: public Poco::Crypto::X509Certificate
+	/// This class extends Poco::Crypto::X509Certificate with the
+	/// feature to validate a certificate.
+{
+public:
+	explicit X509Certificate(std::istream& istr);
+		/// Creates the X509Certificate object by reading
+		/// a certificate in PEM format from a stream.
+
+	explicit X509Certificate(const std::string& path);
+		/// Creates the X509Certificate object by reading
+		/// a certificate in PEM format from a file.
+
+	explicit X509Certificate(X509* pCert);
+		/// Creates the X509Certificate from an existing
+		/// OpenSSL certificate. Ownership is taken of 
+		/// the certificate.
+
+	X509Certificate(X509* pCert, bool shared);
+		/// Creates the X509Certificate from an existing
+		/// OpenSSL certificate. Ownership is taken of 
+		/// the certificate. If shared is true, the 
+		/// certificate's reference count is incremented.
+
+	X509Certificate(const Poco::Crypto::X509Certificate& cert);
+		/// Creates the certificate by copying another one.
+
+	X509Certificate& operator = (const Poco::Crypto::X509Certificate& cert);
+		/// Assigns a certificate.
+
+	~X509Certificate();
+		/// Destroys the X509Certificate.
+
+	bool verify(const std::string& hostName) const;
+		/// Verifies the validity of the certificate against the host name.
+		///
+		/// For this check to be successful, the certificate must contain
+		/// a domain name that matches the domain name
+		/// of the host.
+		/// 
+		/// Returns true if verification succeeded, or false otherwise.
+		
+	static bool verify(const Poco::Crypto::X509Certificate& cert, const std::string& hostName);
+		/// Verifies the validity of the certificate against the host name.
+		///
+		/// For this check to be successful, the certificate must contain
+		/// a domain name that matches the domain name
+		/// of the host.
+		///
+		/// Returns true if verification succeeded, or false otherwise.
+		
+protected:
+	static bool containsWildcards(const std::string& commonName);
+	static bool matchWildcard(const std::string& alias, const std::string& hostName);
+	
+private:
+	enum
+	{
+		NAME_BUFFER_SIZE = 256
+	};
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // NetSSL_X509Certificate_INCLUDED
diff --git a/Poco/Notification.h b/Poco/Notification.h
new file mode 100644
index 0000000..f5f20a1
--- /dev/null
+++ b/Poco/Notification.h
@@ -0,0 +1,55 @@
+//
+// Notification.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  Notification
+//
+// Definition of the Notification class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Notification_INCLUDED
+#define Foundation_Notification_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Notification: public RefCountedObject
+	/// The base class for all notification classes used
+	/// with the NotificationCenter and the NotificationQueue
+	/// classes.
+	/// The Notification class can be used with the AutoPtr
+	/// template class.
+{
+public:
+	typedef AutoPtr<Notification> Ptr;
+	
+	Notification();
+		/// Creates the notification.
+
+	virtual std::string name() const;
+		/// Returns the name of the notification.
+		/// The default implementation returns the class name.
+
+protected:
+	virtual ~Notification();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Notification_INCLUDED
diff --git a/Poco/NotificationCenter.h b/Poco/NotificationCenter.h
new file mode 100644
index 0000000..411bba8
--- /dev/null
+++ b/Poco/NotificationCenter.h
@@ -0,0 +1,139 @@
+//
+// NotificationCenter.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  NotificationCenter
+//
+// Definition of the NotificationCenter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NotificationCenter_INCLUDED
+#define Foundation_NotificationCenter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Notification.h"
+#include "Poco/Mutex.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class AbstractObserver;
+
+
+class Foundation_API NotificationCenter
+	/// A NotificationCenter is essentially a notification dispatcher. 
+	/// It notifies all observers of notifications meeting specific criteria.
+	/// This information is encapsulated in Notification objects.
+	/// Client objects register themselves with the notification center as observers of 
+	/// specific notifications posted by other objects. When an event occurs, an object 
+	/// posts an appropriate notification to the notification center. The notification  
+	/// center invokes the registered method on each matching observer, passing the notification 
+	/// as argument.
+	///
+	/// The order in which observers receive notifications is undefined. 
+	/// It is possible for the posting object and the observing object to be the same.
+	/// The NotificationCenter delivers notifications to observers synchronously. 
+	/// In other words the postNotification() method does not return until all observers have 
+	/// received and processed the notification. 
+	/// If an observer throws an exception while handling a notification, the NotificationCenter
+	/// stops dispatching the notification and postNotification() rethrows the exception.
+	///
+	/// In a multithreaded scenario, notifications are always delivered in the thread in which the 
+	/// notification was posted, which may not be the same thread in which an observer registered itself.
+	///
+	/// The NotificationCenter class is basically a C++ implementation of the NSNotificationCenter class
+	/// found in Apple's Cocoa (or OpenStep).
+	///
+	/// While handling a notification, an observer can unregister itself from the notification center,
+	/// or it can register or unregister other observers. Observers added during a dispatch cycle
+	/// will not receive the current notification.
+	///
+	/// The method receiving the notification must be implemented as
+	///     void handleNotification(MyNotification* pNf);
+	/// The handler method gets co-ownership of the Notification object
+	/// and must release it when done. This is best done with an AutoPtr:
+	///     void MyClass::handleNotification(MyNotification* pNf)
+	///     {
+	///         AutoPtr<MyNotification> nf(pNf);
+	///         ...
+	///     }
+	///
+	/// Alternatively, the NObserver class template can be used to register a callback
+	/// method. In this case, the callback method receives the Notification in an
+	/// AutoPtr and thus does not have to deal with object ownership issues:
+	///     void MyClass::handleNotification(const AutoPtr<MyNotification>& pNf)
+	///     {
+	///         ...
+	///     }
+{
+public:
+	NotificationCenter();
+		/// Creates the NotificationCenter.
+
+	~NotificationCenter();
+		/// Destroys the NotificationCenter.
+
+	void addObserver(const AbstractObserver& observer);
+		/// Registers an observer with the NotificationCenter.
+		/// Usage:
+		///     Observer<MyClass, MyNotification> obs(*this, &MyClass::handleNotification);
+		///     notificationCenter.addObserver(obs);
+		///
+		/// Alternatively, the NObserver template class can be used instead of Observer.
+
+	void removeObserver(const AbstractObserver& observer);
+		/// Unregisters an observer with the NotificationCenter.
+
+	bool hasObserver(const AbstractObserver& observer) const;
+		/// Returns true if the observer is registered with this NotificationCenter.
+
+	void postNotification(Notification::Ptr pNotification);
+		/// Posts a notification to the NotificationCenter.
+		/// The NotificationCenter then delivers the notification
+		/// to all interested observers.
+		/// If an observer throws an exception, dispatching terminates
+		/// and the exception is rethrown to the caller.
+		/// Ownership of the notification object is claimed and the
+		/// notification is released before returning. Therefore,
+		/// a call like
+		///    notificationCenter.postNotification(new MyNotification);
+		/// does not result in a memory leak.
+
+	bool hasObservers() const;
+		/// Returns true iff there is at least one registered observer.
+		///
+		/// Can be used to improve performance if an expensive notification
+		/// shall only be created and posted if there are any observers.
+		
+	std::size_t countObservers() const;
+		/// Returns the number of registered observers.
+		
+	static NotificationCenter& defaultCenter();
+		/// Returns a reference to the default
+		/// NotificationCenter.
+
+private:
+	typedef SharedPtr<AbstractObserver> AbstractObserverPtr;
+	typedef std::vector<AbstractObserverPtr> ObserverList;
+
+	ObserverList  _observers;
+	mutable Mutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NotificationCenter_INCLUDED
diff --git a/Poco/NotificationQueue.h b/Poco/NotificationQueue.h
new file mode 100644
index 0000000..3194ddd
--- /dev/null
+++ b/Poco/NotificationQueue.h
@@ -0,0 +1,155 @@
+//
+// NotificationQueue.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  NotificationQueue
+//
+// Definition of the NotificationQueue class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NotificationQueue_INCLUDED
+#define Foundation_NotificationQueue_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Notification.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+#include <deque>
+
+
+namespace Poco {
+
+
+class NotificationCenter;
+
+
+class Foundation_API NotificationQueue
+	/// A NotificationQueue object provides a way to implement asynchronous
+	/// notifications. This is especially useful for sending notifications
+	/// from one thread to another, for example from a background thread to 
+	/// the main (user interface) thread. 
+	/// 
+	/// The NotificationQueue can also be used to distribute work from
+	/// a controlling thread to one or more worker threads. Each worker thread
+	/// repeatedly calls waitDequeueNotification() and processes the
+	/// returned notification. Special care must be taken when shutting
+	/// down a queue with worker threads waiting for notifications.
+	/// The recommended sequence to shut down and destroy the queue is to
+	///   1. set a termination flag for every worker thread
+	///   2. call the wakeUpAll() method
+	///   3. join each worker thread
+	///   4. destroy the notification queue.
+{
+public:
+	NotificationQueue();
+		/// Creates the NotificationQueue.
+
+	~NotificationQueue();
+		/// Destroys the NotificationQueue.
+
+	void enqueueNotification(Notification::Ptr pNotification);
+		/// Enqueues the given notification by adding it to
+		/// the end of the queue (FIFO).
+		/// The queue takes ownership of the notification, thus
+		/// a call like
+		///     notificationQueue.enqueueNotification(new MyNotification);
+		/// does not result in a memory leak.
+		
+	void enqueueUrgentNotification(Notification::Ptr pNotification);
+		/// Enqueues the given notification by adding it to
+		/// the front of the queue (LIFO). The event therefore gets processed
+		/// before all other events already in the queue.
+		/// The queue takes ownership of the notification, thus
+		/// a call like
+		///     notificationQueue.enqueueUrgentNotification(new MyNotification);
+		/// does not result in a memory leak.
+
+	Notification* dequeueNotification();
+		/// Dequeues the next pending notification.
+		/// Returns 0 (null) if no notification is available.
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	Notification* waitDequeueNotification();
+		/// Dequeues the next pending notification.
+		/// If no notification is available, waits for a notification
+		/// to be enqueued. 
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		/// This method returns 0 (null) if wakeUpWaitingThreads()
+		/// has been called by another thread.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	Notification* waitDequeueNotification(long milliseconds);
+		/// Dequeues the next pending notification.
+		/// If no notification is available, waits for a notification
+		/// to be enqueued up to the specified time.
+		/// Returns 0 (null) if no notification is available.
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	void dispatch(NotificationCenter& notificationCenter);
+		/// Dispatches all queued notifications to the given
+		/// notification center.
+
+	void wakeUpAll();
+		/// Wakes up all threads that wait for a notification.
+	
+	bool empty() const;
+		/// Returns true iff the queue is empty.
+		
+	int size() const;
+		/// Returns the number of notifications in the queue.
+
+	void clear();
+		/// Removes all notifications from the queue.
+		
+	bool hasIdleThreads() const;	
+		/// Returns true if the queue has at least one thread waiting 
+		/// for a notification.
+		
+	static NotificationQueue& defaultQueue();
+		/// Returns a reference to the default
+		/// NotificationQueue.
+
+protected:
+	Notification::Ptr dequeueOne();
+	
+private:
+	typedef std::deque<Notification::Ptr> NfQueue;
+	struct WaitInfo
+	{
+		Notification::Ptr pNf;
+		Event             nfAvailable;
+	};
+	typedef std::deque<WaitInfo*> WaitQueue;
+
+	NfQueue           _nfQueue;
+	WaitQueue         _waitQueue;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NotificationQueue_INCLUDED
diff --git a/Poco/NotificationStrategy.h b/Poco/NotificationStrategy.h
new file mode 100644
index 0000000..d36fbe2
--- /dev/null
+++ b/Poco/NotificationStrategy.h
@@ -0,0 +1,112 @@
+//
+// NotificationStrategy.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  NotificationStrategy
+//
+// Definition of the NotificationStrategy interface.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NotificationStrategy_INCLUDED
+#define Foundation_NotificationStrategy_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class TArgs, class TDelegate> 
+class NotificationStrategy
+	/// The interface that all notification strategies must implement.
+	/// 
+	/// Note: Event is based on policy-driven design, so every strategy implementation
+	/// must provide all the methods from this interface (otherwise: compile errors)
+	/// but does not need to inherit from NotificationStrategy.
+{
+public:
+	typedef TDelegate* DelegateHandle;
+
+	NotificationStrategy()
+	{
+	}
+
+	virtual ~NotificationStrategy()
+	{
+	}
+
+	virtual void notify(const void* sender, TArgs& arguments) = 0;
+		/// Sends a notification to all registered delegates.
+
+	virtual DelegateHandle add(const TDelegate& delegate) = 0;
+		/// Adds a delegate to the strategy.
+
+	virtual void remove(const TDelegate& delegate) = 0;
+		/// Removes a delegate from the strategy, if found.
+		/// Does nothing if the delegate has not been added.
+
+	virtual void remove(DelegateHandle delegateHandle) = 0;
+		/// Removes a delegate from the strategy, if found.
+		/// Does nothing if the delegate has not been added.
+
+	virtual void clear() = 0;
+		/// Removes all delegates from the strategy.
+
+	virtual bool empty() const = 0;
+		/// Returns false if the strategy contains at least one delegate.
+};
+
+
+template <class TDelegate> 
+class NotificationStrategy<void, TDelegate>
+	/// The interface that all notification strategies must implement.
+	/// 
+	/// Note: Event is based on policy-driven design, so every strategy implementation
+	/// must provide all the methods from this interface (otherwise: compile errors)
+	/// but does not need to inherit from NotificationStrategy.
+{
+public:
+	typedef TDelegate* DelegateHandle;
+
+	NotificationStrategy()
+	{
+	}
+
+	virtual ~NotificationStrategy()
+	{
+	}
+
+	virtual void notify(const void* sender) = 0;
+		/// Sends a notification to all registered delegates.
+
+	virtual DelegateHandle add(const TDelegate& delegate) = 0;
+		/// Adds a delegate to the strategy.
+
+	virtual void remove(const TDelegate& delegate) = 0;
+		/// Removes a delegate from the strategy, if found.
+		/// Does nothing if the delegate has not been added.
+
+	virtual void remove(DelegateHandle delegateHandle) = 0;
+		/// Removes a delegate from the strategy, if found.
+		/// Does nothing if the delegate has not been added.
+
+	virtual void clear() = 0;
+		/// Removes all delegates from the strategy.
+
+	virtual bool empty() const = 0;
+		/// Returns false if the strategy contains at least one delegate.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NotificationStrategy_INCLUDED
diff --git a/Poco/NullChannel.h b/Poco/NullChannel.h
new file mode 100644
index 0000000..8384dcf
--- /dev/null
+++ b/Poco/NullChannel.h
@@ -0,0 +1,55 @@
+//
+// NullChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  NullChannel
+//
+// Definition of the NullChannel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NullChannel_INCLUDED
+#define Foundation_NullChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NullChannel: public Channel
+	/// The NullChannel is the /dev/null of Channels.
+	///
+	/// A NullChannel discards all information sent to it.
+	/// Furthermore, its setProperty() method ignores 
+	/// all properties, so it the NullChannel has the
+	/// nice feature that it can stand in for any
+	/// other channel class in a logging configuration.
+{
+public:
+	NullChannel();
+		/// Creates the NullChannel.
+
+	~NullChannel();
+		/// Destroys the NullChannel.
+
+	void log(const Message& msg);
+		/// Does nothing.
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Ignores both name and value.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NullChannel_INCLUDED
diff --git a/Poco/NullStream.h b/Poco/NullStream.h
new file mode 100644
index 0000000..52c292d
--- /dev/null
+++ b/Poco/NullStream.h
@@ -0,0 +1,90 @@
+//
+// NullStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  NullStream
+//
+// Definition of the NullStreamBuf, NullInputStream and NullOutputStream classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NullStream_INCLUDED
+#define Foundation_NullStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API NullStreamBuf: public UnbufferedStreamBuf
+	/// This stream buffer discards all characters written to it.
+	/// Any read operation immediately yields EOF.
+{
+public:
+	NullStreamBuf();
+		/// Creates a NullStreamBuf.
+	
+	~NullStreamBuf();
+		/// Destroys the NullStreamBuf.
+		
+protected:
+	int readFromDevice();
+	int writeToDevice(char c);
+};
+
+
+class Foundation_API NullIOS: public virtual std::ios
+	/// The base class for NullInputStream and NullOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	NullIOS();
+	~NullIOS();
+
+protected:
+	NullStreamBuf _buf;
+};
+
+
+class Foundation_API NullInputStream: public NullIOS, public std::istream
+	/// Any read operation from this stream immediately
+	/// yields EOF.
+{
+public:
+	NullInputStream();
+		/// Creates the NullInputStream.
+
+	~NullInputStream();
+		/// Destroys the NullInputStream.
+};
+
+
+class Foundation_API NullOutputStream: public NullIOS, public std::ostream
+	/// This stream discards all characters written to it.
+{
+public:
+	NullOutputStream();
+		/// Creates the NullOutputStream.
+	
+	~NullOutputStream();
+		/// Destroys the NullOutputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NullStream_INCLUDED
diff --git a/Poco/Nullable.h b/Poco/Nullable.h
new file mode 100644
index 0000000..d113256
--- /dev/null
+++ b/Poco/Nullable.h
@@ -0,0 +1,323 @@
+//
+// Nullable.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Nullable
+//
+// Definition of the Nullable template class.
+//
+// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Nullable_INCLUDED
+#define Foundation_Nullable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <algorithm>
+#include <iostream>
+
+
+namespace Poco {
+
+
+enum NullType
+{
+	NULL_GENERIC = 0
+};
+
+
+template <typename C>
+class Nullable
+	/// Nullable is a simple wrapper class for value types
+	/// that allows objects or native type variables 
+	/// to have "null" value.
+	///
+	/// The class is useful for passing parameters to functions
+	/// when parameters are optional and no default values 
+	/// should be used or when a non-assigned state is needed,
+	/// such as in e.g. fetching null values from database.
+	///
+	/// A Nullable can be default constructed. In this case, 
+	/// the Nullable will have a Null value and isNull() will
+	/// return true. Calling value() (without default value) on
+	/// a Null object will throw a NullValueException.
+	///
+	/// A Nullable can also be constructed from a value.
+	/// It is possible to assign a value to a Nullable, and
+	/// to reset a Nullable to contain a Null value by calling
+	/// clear().
+	///
+	/// For use with Nullable, the value type should support
+	/// default construction.
+{
+public:
+	Nullable(): 
+		/// Creates an empty Nullable.
+		_value(),
+		_isNull(true),
+		_null()
+	{
+	}
+
+	Nullable(const NullType&): 
+		/// Creates an empty Nullable.
+		_value(),
+		_isNull(true),
+		_null()
+	{
+	}
+
+	Nullable(const C& value): 
+		/// Creates a Nullable with the given value.
+		_value(value), 
+		_isNull(false),
+		_null()
+	{
+	}
+	
+	Nullable(const Nullable& other):
+		/// Creates a Nullable by copying another one.
+		_value(other._value),
+		_isNull(other._isNull),
+		_null()
+	{
+	}
+
+	~Nullable()
+		/// Destroys the Nullable.
+	{
+	}
+
+	Nullable& assign(const C& value)
+		/// Assigns a value to the Nullable.
+	{
+		_value  = value;
+		_isNull = false;
+		return *this;
+	}
+	
+	Nullable& assign(const Nullable& other)
+		/// Assigns another Nullable.
+	{
+		Nullable tmp(other);
+		swap(tmp);
+		return *this;
+	}
+	
+	Nullable& assign(NullType)
+		/// Sets value to null.
+	{
+		_isNull = true;
+		return *this;
+	}
+	
+	Nullable& operator = (const C& value)
+		/// Assigns a value to the Nullable.
+	{
+		return assign(value);
+	}
+
+	Nullable& operator = (const Nullable& other)
+		/// Assigns another Nullable.
+	{
+		return assign(other);
+	}
+
+	Nullable& operator = (NullType)
+		/// Assigns another Nullable.
+	{
+		_isNull = true;
+		return *this;
+	}
+
+	void swap(Nullable& other)
+		/// Swaps this Nullable with other.
+	{
+		std::swap(_value, other._value);
+		std::swap(_isNull, other._isNull);
+	}
+
+	bool operator == (const Nullable<C>& other) const
+		/// Compares two Nullables for equality
+	{
+		return (_isNull && other._isNull) || (_isNull == other._isNull && _value == other._value);
+	}
+
+	bool operator == (const C& value) const
+		/// Compares Nullable with value for equality
+	{
+		return (!_isNull && _value == value);
+	}
+
+	bool operator == (const NullType&) const
+		/// Compares Nullable with NullData for equality
+	{
+		return _isNull;
+	}
+
+	bool operator != (const C& value) const
+		/// Compares Nullable with value for non equality
+	{
+		return !(*this == value);
+	}
+
+	bool operator != (const Nullable<C>& other) const
+		/// Compares two Nullables for non equality
+	{
+		return !(*this == other);
+	}
+
+	bool operator != (const NullType&) const
+		/// Compares with NullData for non equality
+	{
+		return !_isNull;
+	}
+
+	bool operator < (const Nullable<C>& other) const
+		/// Compares two Nullable objects. Return true if this object's
+		/// value is smaler than the other object's value.
+		/// Null value is smaller than a non-null value.
+	{
+		if (_isNull && other._isNull) return false;
+
+		if (!_isNull && !other._isNull)
+			return (_value < other._value);
+
+		if (_isNull && !other._isNull) return true;
+
+		return false;
+	}
+
+	bool operator > (const Nullable<C>& other) const
+		/// Compares two Nullable objects. Return true if this object's
+		/// value is greater than the other object's value.
+		/// A non-null value is greater than a null value.
+	{
+		return !(*this == other) && !(*this < other);
+	}
+
+	C& value()
+		/// Returns the Nullable's value.
+		///
+		/// Throws a NullValueException if the Nullable is empty.
+	{
+		if (!_isNull)
+			return _value;
+		else
+			throw NullValueException();
+	}
+
+	const C& value() const
+		/// Returns the Nullable's value.
+		///
+		/// Throws a NullValueException if the Nullable is empty.
+	{
+		if (!_isNull)
+			return _value;
+		else
+			throw NullValueException();
+	}
+
+	const C& value(const C& deflt) const
+		/// Returns the Nullable's value, or the
+		/// given default value if the Nullable is empty.
+	{
+		return _isNull ? deflt : _value;
+	}
+
+	operator C& ()
+		/// Get reference to the value
+	{
+		return value();
+	}
+
+	operator const C& () const
+		/// Get const reference to the value
+	{
+		return value();
+	}
+
+	operator NullType& ()
+		/// Get reference to the value
+	{
+
+		return _null;
+	}
+
+	bool isNull() const
+		/// Returns true if the Nullable is empty.
+	{
+		return _isNull;
+	}
+	
+	void clear()
+		/// Clears the Nullable.
+	{
+		_isNull = true;
+	}
+
+private:
+	C        _value;
+	bool     _isNull;
+	NullType _null;
+};
+
+
+template <typename C>
+inline void swap(Nullable<C>& n1, Nullable<C>& n2)
+{
+	n1.swap(n2);
+}
+
+
+template <typename C>
+std::ostream& operator<<(std::ostream& out, const Nullable<C>& obj) 
+{
+	if (!obj.isNull()) out << obj.value();
+	return out;
+}
+
+
+template <typename C>
+bool operator == (const NullType&, const Nullable<C>& n)
+	/// Returns true if this Nullable is null.
+{
+	return n.isNull();
+}
+
+
+template <typename C>
+bool operator != (const C& c, const Nullable<C>& n)
+	/// Compares Nullable with value for non equality
+{
+	return !(n == c);
+}
+
+
+template <typename C>
+bool operator == (const C& c, const Nullable<C>& n)
+	/// Compares Nullable with NullData for equality
+{
+	return (n == c);
+}
+
+
+template <typename C>
+bool operator != (const NullType&, const Nullable<C>& n)
+	/// Returns true if this Nullable is not null.
+{
+	return !n.isNull();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Nullable_INCLUDED
diff --git a/Poco/NumberFormatter.h b/Poco/NumberFormatter.h
new file mode 100644
index 0000000..ff8d13c
--- /dev/null
+++ b/Poco/NumberFormatter.h
@@ -0,0 +1,907 @@
+//
+// NumberFormatter.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  NumberFormatter
+//
+// Definition of the NumberFormatter class.
+//
+// Copyright (c) 2004-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NumberFormatter_INCLUDED
+#define Foundation_NumberFormatter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/NumericString.h"
+
+
+namespace Poco {
+
+
+class Foundation_API NumberFormatter
+	/// The NumberFormatter class provides static methods
+	/// for formatting numeric values into strings.
+	///
+	/// There are two kind of static member functions:
+	///    * format* functions return a std::string containing
+	///      the formatted value.
+	///    * append* functions append the formatted value to
+	///      an existing string.
+{
+public:
+	enum BoolFormat
+	{
+		FMT_TRUE_FALSE,
+		FMT_YES_NO,
+		FMT_ON_OFF
+	};
+
+	static const unsigned NF_MAX_INT_STRING_LEN = 32; // increase for 64-bit binary formatting support
+	static const unsigned NF_MAX_FLT_STRING_LEN = POCO_MAX_FLT_STRING_LEN;
+
+	static std::string format(int value);
+		/// Formats an integer value in decimal notation.
+
+	static std::string format(int value, int width);
+		/// Formats an integer value in decimal notation,
+		/// right justified in a field having at least
+		/// the specified width.
+
+	static std::string format0(int value, int width);
+		/// Formats an integer value in decimal notation,
+		/// right justified and zero-padded in a field
+		/// having at least the specified width.
+
+	static std::string formatHex(int value, bool prefix = false);
+		/// Formats an int value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+		/// The value is treated as unsigned.
+
+	static std::string formatHex(int value, int width, bool prefix = false);
+		/// Formats a int value in hexadecimal notation,
+		/// right justified and zero-padded in
+		/// a field having at least the specified width.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+		/// The value is treated as unsigned.
+
+	static std::string format(unsigned value);
+		/// Formats an unsigned int value in decimal notation.
+
+	static std::string format(unsigned value, int width);
+		/// Formats an unsigned long int in decimal notation,
+		/// right justified in a field having at least the
+		/// specified width.
+
+	static std::string format0(unsigned int value, int width);
+		/// Formats an unsigned int value in decimal notation,
+		/// right justified and zero-padded in a field having at
+		/// least the specified width.
+
+	static std::string formatHex(unsigned value, bool prefix = false);
+		/// Formats an unsigned int value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+
+	static std::string formatHex(unsigned value, int width, bool prefix = false);
+		/// Formats a int value in hexadecimal notation,
+		/// right justified and zero-padded in
+		/// a field having at least the specified width.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+
+	static std::string format(long value);
+		/// Formats a long value in decimal notation.
+
+	static std::string format(long value, int width);
+		/// Formats a long value in decimal notation,
+		/// right justified in a field having at least the
+		/// specified width.
+
+	static std::string format0(long value, int width);
+		/// Formats a long value in decimal notation,
+		/// right justified and zero-padded in a field
+		/// having at least the specified width.
+
+	static std::string formatHex(long value, bool prefix = false);
+		/// Formats an unsigned long value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+		/// The value is treated as unsigned.
+
+	static std::string formatHex(long value, int width, bool prefix = false);
+		/// Formats an unsigned long value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+		/// The value is treated as unsigned.
+
+	static std::string format(unsigned long value);
+		/// Formats an unsigned long value in decimal notation.
+
+	static std::string format(unsigned long value, int width);
+		/// Formats an unsigned long value in decimal notation,
+		/// right justified in a field having at least the specified
+		/// width.
+
+	static std::string format0(unsigned long value, int width);
+		/// Formats an unsigned long value in decimal notation,
+		/// right justified and zero-padded
+		/// in a field having at least the specified width.
+
+	static std::string formatHex(unsigned long value, bool prefix = false);
+		/// Formats an unsigned long value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+
+	static std::string formatHex(unsigned long value, int width, bool prefix = false);
+		/// Formats an unsigned long value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+
+#ifdef POCO_HAVE_INT64
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	static std::string format(long long value);
+		/// Formats a 64-bit integer value in decimal notation.
+
+	static std::string format(long long value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static std::string format0(long long value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+
+	static std::string formatHex(long long value, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+		/// The value is treated as unsigned.
+
+	static std::string formatHex(long long value, int width, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+		/// The value is treated as unsigned.
+		/// If prefix is true, "0x" prefix is prepended to the resulting string.
+
+	static std::string format(unsigned long long value);
+		/// Formats an unsigned 64-bit integer value in decimal notation.
+
+	static std::string format(unsigned long long value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static std::string format0(unsigned long long value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+
+	static std::string formatHex(unsigned long long value, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+
+	static std::string formatHex(unsigned long long value, int width, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width. If prefix is true, "0x" prefix is
+		/// prepended to the resulting string.
+
+#else // ifndef POCO_LONG_IS_64_BIT
+
+	static std::string format(Int64 value);
+		/// Formats a 64-bit integer value in decimal notation.
+
+	static std::string format(Int64 value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static std::string format0(Int64 value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+
+	static std::string formatHex(Int64 value, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+		/// The value is treated as unsigned.
+
+	static std::string formatHex(Int64 value, int width, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+		/// The value is treated as unsigned.
+		/// If prefix is true, "0x" prefix is prepended to the resulting string.
+
+	static std::string format(UInt64 value);
+		/// Formats an unsigned 64-bit integer value in decimal notation.
+
+	static std::string format(UInt64 value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static std::string format0(UInt64 value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+
+	static std::string formatHex(UInt64 value, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+		/// If prefix is true, "0x" prefix is prepended to the 
+		/// resulting string.
+
+	static std::string formatHex(UInt64 value, int width, bool prefix = false);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width. If prefix is true, "0x" prefix is
+		/// prepended to the resulting string.
+
+#endif // ifdef POCO_LONG_IS_64_BIT
+
+#endif // ifdef POCO_HAVE_INT64
+
+	static std::string format(float value);
+		/// Formats a float value in decimal floating-point notation,
+		/// according to std::printf's %g format with a precision of 8 fractional digits.
+
+	static std::string format(float value, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// according to std::printf's %f format with the given precision.
+
+	static std::string format(float value, int width, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// right justified in a field of the specified width,
+		/// with the number of fractional digits given in precision.
+
+	static std::string format(double value);
+		/// Formats a double value in decimal floating-point notation,
+		/// according to std::printf's %g format with a precision of 16 fractional digits.
+
+	static std::string format(double value, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// according to std::printf's %f format with the given precision.
+
+	static std::string format(double value, int width, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// right justified in a field of the specified width,
+		/// with the number of fractional digits given in precision.
+
+	static std::string format(const void* ptr);
+		/// Formats a pointer in an eight (32-bit architectures) or
+		/// sixteen (64-bit architectures) characters wide
+		/// field in hexadecimal notation.
+
+	static std::string format(bool value, BoolFormat format = FMT_TRUE_FALSE);
+		/// Formats a bool value in decimal/text notation,
+		/// according to format parameter.
+
+	static void append(std::string& str, int value);
+		/// Formats an integer value in decimal notation.
+
+	static void append(std::string& str, int value, int width);
+		/// Formats an integer value in decimal notation,
+		/// right justified in a field having at least
+		/// the specified width.
+
+	static void append0(std::string& str, int value, int width);
+		/// Formats an integer value in decimal notation,
+		/// right justified and zero-padded in a field
+		/// having at least the specified width.
+
+	static void appendHex(std::string& str, int value);
+		/// Formats an int value in hexadecimal notation.
+		/// The value is treated as unsigned.
+
+	static void appendHex(std::string& str, int value, int width);
+		/// Formats a int value in hexadecimal notation,
+		/// right justified and zero-padded in
+		/// a field having at least the specified width.
+		/// The value is treated as unsigned.
+
+	static void append(std::string& str, unsigned value);
+		/// Formats an unsigned int value in decimal notation.
+
+	static void append(std::string& str, unsigned value, int width);
+		/// Formats an unsigned long int in decimal notation,
+		/// right justified in a field having at least the
+		/// specified width.
+
+	static void append0(std::string& str, unsigned int value, int width);
+		/// Formats an unsigned int value in decimal notation,
+		/// right justified and zero-padded in a field having at
+		/// least the specified width.
+
+	static void appendHex(std::string& str, unsigned value);
+		/// Formats an unsigned int value in hexadecimal notation.
+
+	static void appendHex(std::string& str, unsigned value, int width);
+		/// Formats a int value in hexadecimal notation,
+		/// right justified and zero-padded in
+		/// a field having at least the specified width.
+
+	static void append(std::string& str, long value);
+		/// Formats a long value in decimal notation.
+
+	static void append(std::string& str, long value, int width);
+		/// Formats a long value in decimal notation,
+		/// right justified in a field having at least the
+		/// specified width.
+
+	static void append0(std::string& str, long value, int width);
+		/// Formats a long value in decimal notation,
+		/// right justified and zero-padded in a field
+		/// having at least the specified width.
+
+	static void appendHex(std::string& str, long value);
+		/// Formats an unsigned long value in hexadecimal notation.
+		/// The value is treated as unsigned.
+
+	static void appendHex(std::string& str, long value, int width);
+		/// Formats an unsigned long value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+		/// The value is treated as unsigned.
+
+	static void append(std::string& str, unsigned long value);
+		/// Formats an unsigned long value in decimal notation.
+
+	static void append(std::string& str, unsigned long value, int width);
+		/// Formats an unsigned long value in decimal notation,
+		/// right justified in a field having at least the specified
+		/// width.
+
+	static void append0(std::string& str, unsigned long value, int width);
+		/// Formats an unsigned long value in decimal notation,
+		/// right justified and zero-padded
+		/// in a field having at least the specified width.
+
+	static void appendHex(std::string& str, unsigned long value);
+		/// Formats an unsigned long value in hexadecimal notation.
+
+	static void appendHex(std::string& str, unsigned long value, int width);
+		/// Formats an unsigned long value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+
+#ifdef POCO_HAVE_INT64
+
+#ifdef POCO_LONG_IS_64_BIT
+
+	static void append(std::string& str, long long value);
+		/// Formats a 64-bit integer value in decimal notation.
+
+	static void append(std::string& str, long long value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static void append0(std::string& str, long long value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+
+	static void appendHex(std::string& str, long long value);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+		/// The value is treated as unsigned.
+
+	static void appendHex(std::string& str, long long value, int width);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+		/// The value is treated as unsigned.
+
+	static void append(std::string& str, unsigned long long value);
+		/// Formats an unsigned 64-bit integer value in decimal notation.
+
+	static void append(std::string& str, unsigned long long value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static void append0(std::string& str, unsigned long long value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+
+	static void appendHex(std::string& str, unsigned long long value);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+
+	static void appendHex(std::string& str, unsigned long long value, int width);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+
+#else // ifndef POCO_LONG_IS_64_BIT
+
+	static void append(std::string& str, Int64 value);
+		/// Formats a 64-bit integer value in decimal notation.
+
+	static void append(std::string& str, Int64 value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static void append0(std::string& str, Int64 value, int width);
+		/// Formats a 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+
+	static void appendHex(std::string& str, Int64 value);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+		/// The value is treated as unsigned.
+
+	static void appendHex(std::string& str, Int64 value, int width);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+		/// The value is treated as unsigned.
+
+	static void append(std::string& str, UInt64 value);
+		/// Formats an unsigned 64-bit integer value in decimal notation.
+
+	static void append(std::string& str, UInt64 value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified in a field having at least the specified width.
+
+	static void append0(std::string& str, UInt64 value, int width);
+		/// Formats an unsigned 64-bit integer value in decimal notation,
+		/// right justified and zero-padded in a field having at least the
+		/// specified width.
+
+	static void appendHex(std::string& str, UInt64 value);
+		/// Formats a 64-bit integer value in hexadecimal notation.
+
+	static void appendHex(std::string& str, UInt64 value, int width);
+		/// Formats a 64-bit integer value in hexadecimal notation,
+		/// right justified and zero-padded in a field having at least
+		/// the specified width.
+
+#endif // ifdef POCO_LONG_IS_64_BIT
+
+#endif // ifdef POCO_HAVE_INT64
+
+	static void append(std::string& str, float value);
+		/// Formats a float value in decimal floating-point notation,
+		/// according to std::printf's %g format with a precision of 8 fractional digits.
+
+	static void append(std::string& str, float value, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// according to std::printf's %f format with the given precision.
+
+	static void append(std::string& str, float value, int width, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// right justified in a field of the specified width,
+		/// with the number of fractional digits given in precision.
+
+	static void append(std::string& str, double value);
+		/// Formats a double value in decimal floating-point notation,
+		/// according to std::printf's %g format with a precision of 16 fractional digits.
+
+	static void append(std::string& str, double value, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// according to std::printf's %f format with the given precision.
+
+	static void append(std::string& str, double value, int width, int precision);
+		/// Formats a double value in decimal floating-point notation,
+		/// right justified in a field of the specified width,
+		/// with the number of fractional digits given in precision.
+
+	static void append(std::string& str, const void* ptr);
+		/// Formats a pointer in an eight (32-bit architectures) or
+		/// sixteen (64-bit architectures) characters wide
+		/// field in hexadecimal notation.
+
+private:
+};
+
+
+//
+// inlines
+//
+
+inline std::string NumberFormatter::format(int value)
+{
+	std::string result;
+	intToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(int value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(int value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(int value, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<unsigned int>(value), 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(int value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<unsigned int>(value), 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(unsigned value)
+{
+	std::string result;
+	uIntToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(unsigned value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(unsigned int value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(unsigned value, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(unsigned value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(long value)
+{
+	std::string result;
+	intToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(long value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(long value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(long value, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<unsigned long>(value), 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(long value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<unsigned long>(value), 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(unsigned long value)
+{
+	std::string result;
+	uIntToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(unsigned long value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(unsigned long value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(unsigned long value, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(unsigned long value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+#ifdef POCO_HAVE_INT64
+
+#ifdef POCO_LONG_IS_64_BIT
+
+
+inline std::string NumberFormatter::format(long long value)
+{
+	std::string result;
+	intToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(long long value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(long long value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(long long value, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<unsigned long long>(value), 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(long long value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<unsigned long long>(value), 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(unsigned long long value)
+{
+	std::string result;
+	uIntToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(unsigned long long value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(unsigned long long value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(unsigned long long value, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(unsigned long long value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+#else // ifndef POCO_LONG_IS_64_BIT
+
+
+inline std::string NumberFormatter::format(Int64 value)
+{
+	std::string result;
+	intToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(Int64 value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(Int64 value, int width)
+{
+	std::string result;
+	intToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(Int64 value, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<UInt64>(value), 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(Int64 value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(static_cast<UInt64>(value), 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(UInt64 value)
+{
+	std::string result;
+	uIntToStr(value, 10, result);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(UInt64 value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, ' ');
+	return result;
+}
+
+
+inline std::string NumberFormatter::format0(UInt64 value, int width)
+{
+	std::string result;
+	uIntToStr(value, 10, result, false, width, '0');
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(UInt64 value, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix);
+	return result;
+}
+
+
+inline std::string NumberFormatter::formatHex(UInt64 value, int width, bool prefix)
+{
+	std::string result;
+	uIntToStr(value, 0x10, result, prefix, width, '0');
+	return result;
+}
+
+
+#endif // ifdef POCO_LONG_IS_64_BIT
+
+#endif // ifdef POCO_HAVE_INT64
+
+
+inline std::string NumberFormatter::format(float value)
+{
+	char buffer[POCO_MAX_FLT_STRING_LEN];
+	floatToStr(buffer, POCO_MAX_FLT_STRING_LEN, value);
+	return std::string(buffer);
+}
+
+
+inline std::string NumberFormatter::format(float value, int precision)
+{
+	char buffer[POCO_MAX_FLT_STRING_LEN];
+	floatToFixedStr(buffer, POCO_MAX_FLT_STRING_LEN, value, precision);
+	return std::string(buffer);
+}
+
+
+inline std::string NumberFormatter::format(float value, int width, int precision)
+{
+	std::string result;
+	floatToFixedStr(result, value, precision, width);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(double value)
+{
+	char buffer[POCO_MAX_FLT_STRING_LEN];
+	doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, value);
+	return std::string(buffer);
+}
+
+
+inline std::string NumberFormatter::format(double value, int precision)
+{
+	char buffer[POCO_MAX_FLT_STRING_LEN];
+	doubleToFixedStr(buffer, POCO_MAX_FLT_STRING_LEN, value, precision);
+	return std::string(buffer);
+}
+
+
+inline std::string NumberFormatter::format(double value, int width, int precision)
+{
+	std::string result;
+	doubleToFixedStr(result, value, precision, width);
+	return result;
+}
+
+
+inline std::string NumberFormatter::format(const void* ptr)
+{
+	std::string result;
+	append(result, ptr);
+	return result;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NumberFormatter_INCLUDED
diff --git a/Poco/NumberParser.h b/Poco/NumberParser.h
new file mode 100644
index 0000000..c58ed4f
--- /dev/null
+++ b/Poco/NumberParser.h
@@ -0,0 +1,156 @@
+//
+// NumberParser.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  NumberParser
+//
+// Definition of the NumberParser class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NumberParser_INCLUDED
+#define Foundation_NumberParser_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <string>
+#undef min
+#undef max
+#include <limits>
+
+
+namespace Poco {
+
+
+class Foundation_API NumberParser
+	/// The NumberParser class provides static methods
+	/// for parsing numbers out of strings.
+	///
+	/// Note that leading or trailing whitespace is not allowed
+	/// in the string. Poco::trim() or Poco::trimInPlace()
+	/// can be used to remove leading or trailing whitespace.
+{
+public:
+	static const unsigned short NUM_BASE_OCT = 010;
+	static const unsigned short NUM_BASE_DEC = 10;
+	static const unsigned short NUM_BASE_HEX = 0x10;
+
+	static int parse(const std::string& s, char thousandSeparator = ',');
+		/// Parses an integer value in decimal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in decimal notation.
+	
+	static bool tryParse(const std::string& s, int& value, char thousandSeparator = ',');
+		/// Parses an integer value in decimal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+	
+	static unsigned parseUnsigned(const std::string& s, char thousandSeparator = ',');
+		/// Parses an unsigned integer value in decimal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in decimal notation.
+
+	static bool tryParseUnsigned(const std::string& s, unsigned& value, char thousandSeparator = ',');
+		/// Parses an unsigned integer value in decimal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+	static unsigned parseHex(const std::string& s);
+		/// Parses an integer value in hexadecimal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in
+		/// hexadecimal notation.
+
+	static bool tryParseHex(const std::string& s, unsigned& value);
+		/// Parses an unsigned integer value in hexadecimal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+	static unsigned parseOct(const std::string& s);
+		/// Parses an integer value in octal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in
+		/// hexadecimal notation.
+
+	static bool tryParseOct(const std::string& s, unsigned& value);
+		/// Parses an unsigned integer value in octal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+#if defined(POCO_HAVE_INT64)
+
+	static Int64 parse64(const std::string& s, char thousandSeparator = ',');
+		/// Parses a 64-bit integer value in decimal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in decimal notation.
+
+	static bool tryParse64(const std::string& s, Int64& value, char thousandSeparator = ',');
+		/// Parses a 64-bit integer value in decimal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+	static UInt64 parseUnsigned64(const std::string& s, char thousandSeparator = ',');
+		/// Parses an unsigned 64-bit integer value in decimal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in decimal notation.
+
+	static bool tryParseUnsigned64(const std::string& s, UInt64& value, char thousandSeparator = ',');
+		/// Parses an unsigned 64-bit integer value in decimal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+	static UInt64 parseHex64(const std::string& s);
+		/// Parses a 64 bit-integer value in hexadecimal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in hexadecimal notation.
+
+	static bool tryParseHex64(const std::string& s, UInt64& value);
+		/// Parses an unsigned 64-bit integer value in hexadecimal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+	static UInt64 parseOct64(const std::string& s);
+		/// Parses a 64 bit-integer value in octal notation from the given string.
+		/// Throws a SyntaxException if the string does not hold a number in hexadecimal notation.
+
+	static bool tryParseOct64(const std::string& s, UInt64& value);
+		/// Parses an unsigned 64-bit integer value in octal notation from the given string.
+		/// Returns true if a valid integer has been found, false otherwise. 
+		/// If parsing was not successful, value is undefined.
+
+#endif // defined(POCO_HAVE_INT64)
+
+	static double parseFloat(const std::string& s, char decimalSeparator = '.', char thousandSeparator = ',');
+		/// Parses a double value in decimal floating point notation
+		/// from the given string.
+		/// Throws a SyntaxException if the string does not hold a floating-point 
+		/// number in decimal notation.
+		
+	static bool tryParseFloat(const std::string& s, double& value, char decimalSeparator = '.', char thousandSeparator = ',');
+		/// Parses a double value in decimal floating point notation
+		/// from the given string.
+		/// Returns true if a valid floating point number has been found,
+		/// false otherwise.
+		/// If parsing was not successful, value is undefined.
+
+	static bool parseBool(const std::string& s);
+		/// Parses a bool value in decimal or string notation
+		/// from the given string.
+		/// Valid forms are: "0", "1", "true", "on", false", "yes", "no", "off".
+		/// String forms are NOT case sensitive.
+		/// Throws a SyntaxException if the string does not hold a valid bool number
+
+	static bool tryParseBool(const std::string& s, bool& value);
+		/// Parses a bool value in decimal or string notation
+		/// from the given string.
+		/// Valid forms are: "0", "1", "true", "on", false", "yes", "no", "off".
+		/// String forms are NOT case sensitive.
+		/// Returns true if a valid bool number has been found,
+		/// false otherwise.
+		/// If parsing was not successful, value is undefined.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NumberParser_INCLUDED
diff --git a/Poco/NumericString.h b/Poco/NumericString.h
new file mode 100644
index 0000000..5600432
--- /dev/null
+++ b/Poco/NumericString.h
@@ -0,0 +1,560 @@
+//
+// NumericString.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  NumericString
+//
+// Numeric string utility functions.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_NumericString_INCLUDED
+#define Foundation_NumericString_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Buffer.h"
+#include "Poco/FPEnvironment.h"
+#ifdef min
+	#undef min
+#endif
+#ifdef max
+	#undef max
+#endif
+#include <limits>
+#include <cmath>
+#include <cctype>
+#if !defined(POCO_NO_LOCALE)
+	#include <locale>
+#endif
+
+
+// binary numbers are supported, thus 64 (bits) + 1 (string terminating zero)
+#define POCO_MAX_INT_STRING_LEN 65
+// value from strtod.cc (double_conversion::kMaxSignificantDecimalDigits)
+#define POCO_MAX_FLT_STRING_LEN 780
+
+#define POCO_FLT_INF "inf"
+#define POCO_FLT_NAN "nan"
+#define POCO_FLT_EXP 'e'
+
+
+namespace Poco {
+
+
+inline char decimalSeparator()
+	/// Returns decimal separator from global locale or
+	/// default '.' for platforms where locale is unavailable.
+{
+#if !defined(POCO_NO_LOCALE)
+	return std::use_facet<std::numpunct<char> >(std::locale()).decimal_point();
+#else
+	return '.';
+#endif
+}
+
+
+inline char thousandSeparator()
+	/// Returns thousand separator from global locale or
+	/// default ',' for platforms where locale is unavailable.
+{
+#if !defined(POCO_NO_LOCALE)
+	return std::use_facet<std::numpunct<char> >(std::locale()).thousands_sep();
+#else
+	return ',';
+#endif
+}
+
+
+//
+// String to Number Conversions
+//
+
+template <typename I>
+bool strToInt(const char* pStr, I& result, short base, char thSep = ',')
+	/// Converts zero-terminated character array to integer number;
+	/// Thousand separators are recognized for base10 and current locale;
+	/// it is silently skipped but not verified for correct positioning.
+	/// Function returns true if successful. If parsing was unsuccessful,
+	/// the return value is false with the result value undetermined.
+{
+	if (!pStr) return false;
+	while (std::isspace(*pStr)) ++pStr;
+	if (*pStr == '\0') return false;
+	short sign = 1;
+	if ((base == 10) && (*pStr == '-'))
+	{
+		// Unsigned types can't be negative so abort parsing
+		if (std::numeric_limits<I>::min() >= 0) return false;
+		sign = -1;
+		++pStr;
+	}
+	else if (*pStr == '+') ++pStr;
+
+	// parser states:
+	const char STATE_SIGNIFICANT_DIGITS = 1;
+	char state = 0;
+	
+	result = 0;
+	I limitCheck = std::numeric_limits<I>::max() / base;
+	for (; *pStr != '\0'; ++pStr)
+	{
+		switch (*pStr)
+		{
+		case '0': 
+			if (state < STATE_SIGNIFICANT_DIGITS) break;
+
+		case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7':
+			if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
+			if (result > limitCheck) return false;
+			result = result * base + (*pStr - '0');
+
+			break;
+
+		case '8': case '9':
+			if ((base == 10) || (base == 0x10))
+			{
+				if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
+				if (result > limitCheck) return false;
+				result = result * base + (*pStr - '0');
+			}
+			else return false;
+
+			break;
+
+		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+			if (base != 0x10) return false;
+			if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
+			if (result > limitCheck) return false;
+			result = result * base + (10 + *pStr - 'a');
+
+			break;
+
+		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+			if (base != 0x10) return false;
+			if (state < STATE_SIGNIFICANT_DIGITS) state = STATE_SIGNIFICANT_DIGITS;
+			if (result > limitCheck) return false;
+			result = result * base + (10 + *pStr - 'A');
+
+			break;
+
+		case '.':
+			if ((base == 10) && (thSep == '.')) break;
+			else return false;
+
+		case ',':
+			if ((base == 10) && (thSep == ',')) break;
+			else return false;
+
+		case ' ':
+			if ((base == 10) && (thSep == ' ')) break;
+			// fallthrough
+
+		default:
+			return false;
+		}
+	}
+
+	if ((sign < 0) && (base == 10)) result *= sign;
+
+	return true;
+}
+
+
+template <typename I>
+bool strToInt(const std::string& str, I& result, short base, char thSep = ',')
+	/// Converts string to integer number;
+	/// This is a wrapper function, for details see see the
+	/// bool strToInt(const char*, I&, short, char) implementation.
+{
+	return strToInt(str.c_str(), result, base, thSep);
+}
+
+
+//
+// Number to String Conversions
+//
+
+namespace Impl {
+
+	class Ptr
+		/// Utility char pointer wrapper class.
+		/// Class ensures increment/decrement remain within boundaries.
+	{
+	public:
+		Ptr(char* ptr, std::size_t offset): _beg(ptr), _cur(ptr), _end(ptr + offset)
+		{
+		}
+	
+		char*& operator ++ () // prefix
+		{
+			checkBounds(_cur + 1);
+			return ++_cur;
+		}
+
+		char* operator ++ (int) // postfix
+		{
+			checkBounds(_cur + 1);
+			char* tmp = _cur++;
+			return tmp;
+		}
+	
+		char*& operator -- () // prefix
+		{
+			checkBounds(_cur - 1);
+			return --_cur;
+		}
+
+		char* operator -- (int) // postfix
+		{
+			checkBounds(_cur - 1);
+			char* tmp = _cur--;
+			return tmp;
+		}
+
+		char*& operator += (int incr)
+		{
+			checkBounds(_cur + incr);
+			return _cur += incr;
+		}
+
+		char*& operator -= (int decr)
+		{
+			checkBounds(_cur - decr);
+			return _cur -= decr;
+		}
+
+		operator char* () const
+		{
+			return _cur;
+		}
+
+		std::size_t span() const
+		{
+			return _end - _beg;
+		}
+
+	private:
+		void checkBounds(char* ptr)
+		{
+			if (ptr > _end) throw RangeException();
+		}
+
+		const char* _beg;
+		char*       _cur;
+		const char* _end;
+};	
+
+} // namespace Impl
+
+
+template <typename T>
+bool intToStr(T value,
+	unsigned short base,
+	char* result,
+	std::size_t& size,
+	bool prefix = false,
+	int width = -1,
+	char fill = ' ',
+	char thSep = 0)
+	/// Converts integer to string. Numeric bases from binary to hexadecimal are supported.
+	/// If width is non-zero, it pads the return value with fill character to the specified width.
+	/// When padding is zero character ('0'), it is prepended to the number itself; all other
+	/// paddings are prepended to the formatted result with minus sign or base prefix included
+	/// If prefix is true and base is octal or hexadecimal, respective prefix ('0' for octal, 
+	/// "0x" for hexadecimal) is prepended. For all other bases, prefix argument is ignored.
+	/// Formatted string has at least [width] total length.
+{
+	if (base < 2 || base > 0x10)
+	{
+		*result = '\0';
+		return false;
+	}
+
+	Impl::Ptr ptr(result, size);
+	int thCount = 0;
+	T tmpVal;
+	do
+	{
+		tmpVal = value;
+		value /= base;
+		*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)];
+		if (thSep && (base == 10) && (++thCount == 3))
+		{
+			*ptr++ = thSep;
+			thCount = 0;
+		}
+	} while (value);
+
+	if ('0' == fill)
+	{
+		if (tmpVal < 0) --width;
+		if (prefix && base == 010) --width;
+		if (prefix && base == 0x10) width -= 2;
+		while ((ptr - result) < width) *ptr++ = fill;
+	}
+
+	if (prefix && base == 010) *ptr++ = '0';
+	else if (prefix && base == 0x10)
+	{
+		*ptr++ = 'x';
+		*ptr++ = '0';
+	}
+
+	if (tmpVal < 0) *ptr++ = '-';
+
+	if ('0' != fill)
+	{
+		while ((ptr - result) < width) *ptr++ = fill;
+	}
+
+	size = ptr - result;
+	poco_assert_dbg (size <= ptr.span());
+	poco_assert_dbg ((-1 == width) || (size >= std::size_t(width)));
+	*ptr-- = '\0';
+
+	char* ptrr = result;
+	char tmp;
+	while(ptrr < ptr)
+	{
+		 tmp    = *ptr;
+		*ptr--  = *ptrr;
+		*ptrr++ = tmp;
+	}
+
+	return true;
+}
+
+
+template <typename T>
+bool uIntToStr(T value,
+	unsigned short base,
+	char* result,
+	std::size_t& size,
+	bool prefix = false,
+	int width = -1,
+	char fill = ' ',
+	char thSep = 0)
+	/// Converts unsigned integer to string. Numeric bases from binary to hexadecimal are supported.
+	/// If width is non-zero, it pads the return value with fill character to the specified width.
+	/// When padding is zero character ('0'), it is prepended to the number itself; all other
+	/// paddings are prepended to the formatted result with minus sign or base prefix included
+	/// If prefix is true and base is octal or hexadecimal, respective prefix ('0' for octal,
+	/// "0x" for hexadecimal) is prepended. For all other bases, prefix argument is ignored.
+	/// Formatted string has at least [width] total length.
+{
+	if (base < 2 || base > 0x10)
+	{
+		*result = '\0';
+		return false;
+	}
+	
+	Impl::Ptr ptr(result, size);
+	int thCount = 0;
+	T tmpVal;
+	do
+	{
+		tmpVal = value;
+		value /= base;
+		*ptr++ = "FEDCBA9876543210123456789ABCDEF"[15 + (tmpVal - value * base)];
+		if (thSep && (base == 10) && (++thCount == 3))
+		{
+			*ptr++ = thSep;
+			thCount = 0;
+		}
+	} while (value);
+	
+	if ('0' == fill)
+	{
+		if (prefix && base == 010) --width;
+		if (prefix && base == 0x10) width -= 2;
+		while ((ptr - result) < width) *ptr++ = fill;
+	}
+	
+	if (prefix && base == 010) *ptr++ = '0';
+	else if (prefix && base == 0x10)
+	{
+		*ptr++ = 'x';
+		*ptr++ = '0';
+	}
+	
+	if ('0' != fill)
+	{
+		while ((ptr - result) < width) *ptr++ = fill;
+	}
+	
+	size = ptr - result;
+	poco_assert_dbg (size <= ptr.span());
+	poco_assert_dbg ((-1 == width) || (size >= std::size_t(width)));
+	*ptr-- = '\0';
+	
+	char* ptrr = result;
+	char tmp;
+	while(ptrr < ptr)
+	{
+		tmp    = *ptr;
+		*ptr--  = *ptrr;
+		*ptrr++ = tmp;
+	}
+	
+	return true;
+}
+
+
+template <typename T>
+bool intToStr (T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0)
+	/// Converts integer to string; This is a wrapper function, for details see see the
+	/// bool intToStr(T, unsigned short, char*, int, int, char, char) implementation.
+{
+	char res[POCO_MAX_INT_STRING_LEN] = {0};
+	std::size_t size = POCO_MAX_INT_STRING_LEN;
+	bool ret = intToStr(number, base, res, size, prefix, width, fill, thSep);
+	result.assign(res, size);
+	return ret;
+}
+	
+	
+template <typename T>
+bool uIntToStr (T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0)
+	/// Converts unsigned integer to string; This is a wrapper function, for details see see the
+	/// bool uIntToStr(T, unsigned short, char*, int, int, char, char) implementation.
+{
+	char res[POCO_MAX_INT_STRING_LEN] = {0};
+	std::size_t size = POCO_MAX_INT_STRING_LEN;
+	bool ret = uIntToStr(number, base, res, size, prefix, width, fill, thSep);
+	result.assign(res, size);
+	return ret;
+}
+
+
+//
+// Wrappers for double-conversion library (http://code.google.com/p/double-conversion/).
+//
+// Library is the implementation of the algorithm described in Florian Loitsch's paper:
+// http://florian.loitsch.com/publications/dtoa-pldi2010.pdf
+//
+
+
+Foundation_API void floatToStr(char* buffer,
+	int bufferSize,
+	float value,
+	int lowDec = -std::numeric_limits<float>::digits10,
+	int highDec = std::numeric_limits<float>::digits10);
+	/// Converts a float value to string. Converted string must be shorter than bufferSize.
+	/// Conversion is done by computing the shortest string of digits that correctly represents
+	/// the input number. Depending on lowDec and highDec values, the function returns
+	/// decimal or exponential representation.
+
+Foundation_API void floatToFixedStr(char* buffer,
+	int bufferSize,
+	float value,
+	int precision);
+	/// Converts a float value to string. Converted string must be shorter than bufferSize.
+	/// Computes a decimal representation with a fixed number of digits after the
+  	/// decimal point.
+
+
+Foundation_API std::string& floatToStr(std::string& str,
+	float value,
+	int precision = -1,
+	int width = 0,
+	char thSep = 0,
+	char decSep = 0);
+	/// Converts a float value, assigns it to the supplied string and returns the reference.
+	/// This function calls floatToStr(char*, int, float, int, int) and formats the result according to
+	/// precision (total number of digits after the decimal point, -1 means ignore precision argument) 
+	/// and width (total length of formatted string).
+
+
+Foundation_API std::string& floatToFixedStr(std::string& str,
+	float value,
+	int precision,
+	int width = 0,
+	char thSep = 0,
+	char decSep = 0);
+	/// Converts a float value, assigns it to the supplied string and returns the reference.
+	/// This function calls floatToFixedStr(char*, int, float, int) and formats the result according to
+	/// precision (total number of digits after the decimal point) and width (total length of formatted string).
+
+
+Foundation_API void doubleToStr(char* buffer,
+	int bufferSize,
+	double value,
+	int lowDec = -std::numeric_limits<double>::digits10,
+	int highDec = std::numeric_limits<double>::digits10);
+	/// Converts a double value to string. Converted string must be shorter than bufferSize.
+	/// Conversion is done by computing the shortest string of digits that correctly represents
+	/// the input number. Depending on lowDec and highDec values, the function returns
+	/// decimal or exponential representation.
+
+
+Foundation_API void doubleToFixedStr(char* buffer,
+	int bufferSize,
+	double value,
+	int precision);
+	/// Converts a double value to string. Converted string must be shorter than bufferSize.
+	/// Computes a decimal representation with a fixed number of digits after the
+  	/// decimal point.
+
+
+Foundation_API std::string& doubleToStr(std::string& str,
+	double value,
+	int precision = -1,
+	int width = 0,
+	char thSep = 0,
+	char decSep = 0);
+	/// Converts a double value, assigns it to the supplied string and returns the reference.
+	/// This function calls doubleToStr(char*, int, double, int, int) and formats the result according to
+	/// precision (total number of digits after the decimal point, -1 means ignore precision argument) 
+	/// and width (total length of formatted string).
+
+
+Foundation_API std::string& doubleToFixedStr(std::string& str,
+	double value,
+	int precision = -1,
+	int width = 0,
+	char thSep = 0,
+	char decSep = 0);
+	/// Converts a double value, assigns it to the supplied string and returns the reference.
+	/// This function calls doubleToFixedStr(char*, int, double, int) and formats the result according to
+	/// precision (total number of digits after the decimal point) and width (total length of formatted string).
+
+
+Foundation_API float strToFloat(const char* str);
+	/// Converts the string of characters into single-precision floating point number.
+	/// Function uses double_convesrion::DoubleToStringConverter to do the conversion.
+
+
+Foundation_API bool strToFloat(const std::string&, float& result, char decSep = '.', char thSep = ',');
+	/// Converts the string of characters into single-precision floating point number.
+	/// The conversion result is assigned to the result parameter.
+	/// If decimal separator and/or thousand separator are different from defaults, they should be
+	/// supplied to ensure proper conversion.
+	/// 
+	/// Returns true if successful, false otherwise.
+
+
+Foundation_API double strToDouble(const char* str);
+	/// Converts the string of characters into double-precision floating point number.
+
+
+Foundation_API bool strToDouble(const std::string& str, double& result, char decSep = '.', char thSep = ',');
+	/// Converts the string of characters into double-precision floating point number.
+	/// The conversion result is assigned to the result parameter.
+	/// If decimal separator and/or thousand separator are different from defaults, they should be
+	/// supplied to ensure proper conversion.
+	/// 
+	/// Returns true if successful, false otherwise.
+
+
+} // namespace Poco
+
+
+#endif // Foundation_NumericString_INCLUDED
diff --git a/Poco/ObjectPool.h b/Poco/ObjectPool.h
new file mode 100644
index 0000000..af3d7ba
--- /dev/null
+++ b/Poco/ObjectPool.h
@@ -0,0 +1,332 @@
+//
+// ObjectPool.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  ObjectPool
+//
+// Definition of the ObjectPool template class and friends.
+//
+// Copyright (c) 2010-2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ObjectPool_INCLUDED
+#define Foundation_ObjectPool_INCLUDED
+
+
+#include "Poco/Poco.h"
+#include "Poco/Mutex.h"
+#include "Poco/Condition.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+#include <cctype>
+
+
+namespace Poco {
+
+
+template <class C, class P = C*>
+class PoolableObjectFactory
+	/// A PoolableObjectFactory is responsible for creating and resetting
+	/// objects managed by an ObjectPool.
+	///
+	/// Together with an ObjectPool, a PoolableObjectFactory is used as
+	/// a policy class to change the behavior of the ObjectPool when
+	/// creating new objects, returning used objects back to the pool
+	/// and destroying objects, when the pool itself is destroyed or
+	/// shrunk.
+{
+public:
+	P createObject()
+		/// Create and return a new object.
+	{
+		return new C;
+	}
+	
+	bool validateObject(P pObject)
+		/// Checks whether the object is still valid
+		/// and can be reused.
+		///
+		/// Returns true if the object is valid,
+		/// false otherwise.
+		///
+		/// To maintain the integrity of the pool, this method
+		/// must not throw an exception.
+	{
+		return true;
+	}
+	
+	void activateObject(P pObject)
+		/// Called before an object is handed out by the pool.
+		/// Also called for newly created objects, before
+		/// they are given out for the first time.
+	{
+	}
+	
+	void deactivateObject(P pObject)
+		/// Called after an object has been given back to the
+		/// pool and the object is still valid (a prior call
+		/// to validateObject() returned true).
+		///
+		/// To maintain the integrity of the pool, this method
+		/// must not throw an exception.
+	{
+	}
+	
+	void destroyObject(P pObject)
+		/// Destroy an object.
+		///
+		/// To maintain the integrity of the pool, this method
+		/// must not throw an exception.
+	{
+		delete pObject;
+	}
+};
+
+
+template <class C>
+class PoolableObjectFactory <C, Poco::AutoPtr<C> >
+{
+public:
+	Poco::AutoPtr<C> createObject()
+	{
+		return new C;
+	}
+	
+	bool validateObject(Poco::AutoPtr<C> pObject)
+	{
+		return true;
+	}
+	
+	void activateObject(Poco::AutoPtr<C> pObject)
+	{
+	}
+	
+	void deactivateObject(Poco::AutoPtr<C> pObject)
+	{
+	}
+	
+	void destroyObject(Poco::AutoPtr<C> pObject)
+	{
+	}
+};
+
+
+template <class C>
+class PoolableObjectFactory <C, Poco::SharedPtr<C> >
+{
+public:
+	Poco::SharedPtr<C> createObject()
+	{
+		return new C;
+	}
+	
+	bool validateObject(Poco::SharedPtr<C> pObject)
+	{
+		return true;
+	}
+	
+	void activateObject(Poco::SharedPtr<C> pObject)
+	{
+	}
+	
+	void deactivateObject(Poco::SharedPtr<C> pObject)
+	{
+	}
+	
+	void destroyObject(Poco::SharedPtr<C> pObject)
+	{
+	}
+};
+
+
+template <class C, class P = C*, class F = PoolableObjectFactory<C, P> >
+class ObjectPool
+	/// An ObjectPool manages a pool of objects of a certain class.
+	///
+	/// The number of objects managed by the pool can be restricted.
+	///
+	/// When an object is requested from the pool:
+	///   - If an object is available from the pool, an object from the pool is
+	///     removed from the pool, activated (using the factory) and returned.
+	///   - Otherwise, if the peak capacity of the pool has not yet been reached,
+	///     a new object is created and activated, using the object factory, and returned.
+	///   - If the peak capacity has already been reached, null is returned after timeout.
+	///
+	/// When an object is returned to the pool:
+	///   - If the object is valid (checked by calling validateObject()
+	///     from the object factory), the object is deactivated. If the
+	///     number of objects in the pool is below the capacity,
+	///     the object is added to the pool. Otherwise it is destroyed.
+	///   - If the object is not valid, it is destroyed immediately.
+{
+public:
+	ObjectPool(std::size_t capacity, std::size_t peakCapacity):
+		/// Creates a new ObjectPool with the given capacity
+		/// and peak capacity.
+		///
+		/// The PoolableObjectFactory must have a public default constructor.
+		_capacity(capacity),
+		_peakCapacity(peakCapacity),
+		_size(0)
+	{
+		poco_assert (capacity <= peakCapacity);
+	}
+	
+	ObjectPool(const F& factory, std::size_t capacity, std::size_t peakCapacity):
+		/// Creates a new ObjectPool with the given PoolableObjectFactory,
+		/// capacity and peak capacity. The PoolableObjectFactory must have
+		/// a public copy constructor.
+		_factory(factory),
+		_capacity(capacity),
+		_peakCapacity(peakCapacity),
+		_size(0)
+	{
+		poco_assert (capacity <= peakCapacity);
+	}
+	
+	~ObjectPool()
+		/// Destroys the ObjectPool.
+	{
+		try
+		{
+			for (typename std::vector<P>::iterator it = _pool.begin(); it != _pool.end(); ++it)
+			{
+				_factory.destroyObject(*it);
+			}
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+		
+	P borrowObject(long timeoutMilliseconds = 0)
+		/// Obtains an object from the pool, or creates a new object if
+		/// possible.
+		///
+		/// Returns null if no object is available after timeout.
+		///
+		/// If activating the object fails, the object is destroyed and
+		/// the exception is passed on to the caller.
+	{
+		Poco::FastMutex::ScopedLock lock(_mutex);
+
+		if (!_pool.empty())
+		{
+			P pObject = _pool.back();
+			_pool.pop_back();
+			return activateObject(pObject);
+		}
+
+		if (_size >= _peakCapacity)
+		{
+			if (timeoutMilliseconds == 0)
+			{
+				return 0;
+			}
+			while (_size >= _peakCapacity)
+			{
+				if ( !_availableCondition.tryWait(_mutex, timeoutMilliseconds))
+				{
+					// timeout
+					return 0;
+				}
+			}
+		}
+
+		// _size < _peakCapacity
+		P pObject = _factory.createObject();
+		activateObject(pObject);
+		_size++;
+		return pObject;
+	}
+
+	void returnObject(P pObject)
+		/// Returns an object to the pool.
+	{
+		Poco::FastMutex::ScopedLock lock(_mutex);
+
+		if (_factory.validateObject(pObject))
+		{
+			_factory.deactivateObject(pObject);
+			if (_pool.size() < _capacity)
+			{
+				try
+				{
+					_pool.push_back(pObject);
+					return;
+				}
+				catch (...)
+				{
+				}
+			}
+		}
+		_factory.destroyObject(pObject);
+		_size--;
+		_availableCondition.signal();
+	}
+
+	std::size_t capacity() const
+	{
+		return _capacity;
+	}
+	
+	std::size_t peakCapacity() const
+	{
+		return _peakCapacity;
+	}
+	
+	std::size_t size() const
+	{
+		Poco::FastMutex::ScopedLock lock(_mutex);
+		
+		return _size;
+	}
+	
+	std::size_t available() const
+	{
+		Poco::FastMutex::ScopedLock lock(_mutex);
+
+		return _pool.size() + _peakCapacity - _size;
+	}
+
+protected:
+	P activateObject(P pObject)
+	{
+		try
+		{
+			_factory.activateObject(pObject);
+		}
+		catch (...)
+		{
+			_factory.destroyObject(pObject);
+			throw;
+		}
+		return pObject;
+	}
+	
+private:
+	ObjectPool();
+	ObjectPool(const ObjectPool&);
+	ObjectPool& operator = (const ObjectPool&);
+	
+	F _factory;
+	std::size_t _capacity;
+	std::size_t _peakCapacity;
+	std::size_t _size;
+	std::vector<P> _pool;
+	mutable Poco::FastMutex _mutex;
+	Poco::Condition _availableCondition;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ObjectPool_INCLUDED
diff --git a/Poco/Observer.h b/Poco/Observer.h
new file mode 100644
index 0000000..98d94e0
--- /dev/null
+++ b/Poco/Observer.h
@@ -0,0 +1,124 @@
+//
+// Observer.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  NotificationCenter
+//
+// Definition of the Observer class template.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Observer_INCLUDED
+#define Foundation_Observer_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractObserver.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class C, class N>
+class Observer: public AbstractObserver
+	/// This template class implements an adapter that sits between
+	/// a NotificationCenter and an object receiving notifications
+	/// from it. It is quite similar in concept to the 
+	/// RunnableAdapter, but provides some NotificationCenter
+	/// specific additional methods.
+	/// See the NotificationCenter class for information on how
+	/// to use this template class.
+	///
+	/// Instead of the Observer class template, you might want to
+	/// use the NObserver class template, which uses an AutoPtr to
+	/// pass the Notification to the callback function, thus freeing
+	/// you from memory management issues.
+{
+public:
+	typedef void (C::*Callback)(N*);
+
+	Observer(C& object, Callback method): 
+		_pObject(&object), 
+		_method(method)
+	{
+	}
+	
+	Observer(const Observer& observer):
+		AbstractObserver(observer),
+		_pObject(observer._pObject), 
+		_method(observer._method)
+	{
+	}
+	
+	~Observer()
+	{
+	}
+	
+	Observer& operator = (const Observer& observer)
+	{
+		if (&observer != this)
+		{
+			_pObject = observer._pObject;
+			_method  = observer._method;
+		}
+		return *this;
+	}
+	
+	void notify(Notification* pNf) const
+	{
+		Poco::Mutex::ScopedLock lock(_mutex);
+
+		if (_pObject)
+		{
+			N* pCastNf = dynamic_cast<N*>(pNf);
+			if (pCastNf)
+			{
+				pCastNf->duplicate();
+				(_pObject->*_method)(pCastNf);
+			}
+		}
+	}
+	
+	bool equals(const AbstractObserver& abstractObserver) const
+	{
+		const Observer* pObs = dynamic_cast<const Observer*>(&abstractObserver);
+		return pObs && pObs->_pObject == _pObject && pObs->_method == _method;
+	}
+
+	bool accepts(Notification* pNf) const
+	{
+		return dynamic_cast<N*>(pNf) != 0;
+	}
+	
+	AbstractObserver* clone() const
+	{
+		return new Observer(*this);
+	}
+	
+	void disable()
+	{
+		Poco::Mutex::ScopedLock lock(_mutex);
+		
+		_pObject = 0;
+	}
+	
+private:
+	Observer();
+
+	C*       _pObject;
+	Callback _method;
+	mutable Poco::Mutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Observer_INCLUDED
diff --git a/Poco/Optional.h b/Poco/Optional.h
new file mode 100644
index 0000000..54593b1
--- /dev/null
+++ b/Poco/Optional.h
@@ -0,0 +1,161 @@
+//
+// Optional.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Optional
+//
+// Definition of the Optional class template.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Optional_INCLUDED
+#define Foundation_Optional_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <algorithm>
+
+
+namespace Poco {
+
+
+template <typename C>
+class Optional
+	/// Optional is a simple wrapper class for value types
+	/// that allows to introduce a specified/unspecified state
+	/// to value objects.
+	///
+	/// An Optional can be default constructed. In this case, 
+	/// the Optional will have a Null value and isSpecified() will
+	/// return false. Calling value()(without default value) on
+	/// a Null object will throw a NullValueException.
+	///
+	/// An Optional can also be constructed from a value.
+	/// It is possible to assign a value to an Optional, and
+	/// to reset an Optional to contain a Null value by calling
+	/// clear().
+	///
+	/// For use with Optional, the value type should support
+	/// default construction.
+	///
+	/// Note that the Optional class is basically the same as
+	/// Nullable. However, serializers may treat Nullable
+	/// and Optional differently. An example is XML serialization based
+	/// on XML Schema, where Optional would be used for an element with
+	/// minOccurs == 0, whereas Nullable would be used on an element with
+	/// nillable == true.
+{
+public:
+	Optional(): 
+		/// Creates an empty Optional.
+		_value(),
+		_isSpecified(false)
+	{
+	}
+
+	Optional(const C& value): 
+		/// Creates a Optional with the given value.
+		_value(value), 
+		_isSpecified(true)
+	{
+	}
+	
+	Optional(const Optional& other):
+		/// Creates a Optional by copying another one.
+		_value(other._value),
+		_isSpecified(other._isSpecified)
+	{
+	}
+
+	~Optional()
+		/// Destroys the Optional.
+	{
+	}
+
+	Optional& assign(const C& value)
+		/// Assigns a value to the Optional.
+	{
+		_value  = value;
+		_isSpecified = true;
+		return *this;
+	}
+	
+	Optional& assign(const Optional& other)
+		/// Assigns another Optional.
+	{
+		Optional tmp(other);
+		swap(tmp);
+		return *this;
+	}
+	
+	Optional& operator = (const C& value)
+	{
+		return assign(value);
+	}
+
+	Optional& operator = (const Optional& other)
+	{
+		return assign(other);
+	}
+
+	void swap(Optional& other)
+	{
+		std::swap(_value, other._value);
+		std::swap(_isSpecified, other._isSpecified);
+	}
+
+	const C& value() const
+		/// Returns the Optional's value.
+		///
+		/// Throws a Poco::NullValueException if the value has not been specified.
+	{
+		if (_isSpecified)
+			return _value;
+		else
+			throw Poco::NullValueException();
+	}
+
+	const C& value(const C& deflt) const
+		/// Returns the Optional's value, or the
+		/// given default value if the Optional's 
+		/// value has not been specified.
+	{
+		return _isSpecified ? _value : deflt;
+	}
+
+	bool isSpecified() const
+		/// Returns true iff the Optional's value has been specified.
+	{
+		return _isSpecified;
+	}
+	
+	void clear()
+		/// Clears the Optional.
+	{
+		_isSpecified = false;
+	}
+
+private:
+	C _value;
+	bool _isSpecified;
+};
+
+
+template <typename C>
+inline void swap(Optional<C>& n1, Optional<C>& n2)
+{
+	n1.swap(n2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Optional_INCLUDED
diff --git a/Poco/PBKDF2Engine.h b/Poco/PBKDF2Engine.h
new file mode 100644
index 0000000..357d482
--- /dev/null
+++ b/Poco/PBKDF2Engine.h
@@ -0,0 +1,149 @@
+//
+// PBKDF2Engine.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  PBKDF2Engine
+//
+// Definition of the PBKDF2Engine class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PBKDF2Engine_INCLUDED
+#define Foundation_PBKDF2Engine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DigestEngine.h"
+#include "Poco/ByteOrder.h"
+#include <algorithm>
+
+
+namespace Poco {
+
+
+template <class PRF>
+class PBKDF2Engine: public DigestEngine
+	/// This class implementes the Password-Based Key Derivation Function 2,
+	/// as specified in RFC 2898. The underlying DigestEngine (HMACEngine, etc.),
+	/// which must accept the passphrase as constructor argument (std::string), 
+	/// must be given as template argument. 
+	///
+	/// PBKDF2 (Password-Based Key Derivation Function 2) is a key derivation function 
+	/// that is part of RSA Laboratories' Public-Key Cryptography Standards (PKCS) series, 
+	/// specifically PKCS #5 v2.0, also published as Internet Engineering Task Force's 
+	/// RFC 2898. It replaces an earlier standard, PBKDF1, which could only produce 
+	/// derived keys up to 160 bits long.
+	///
+	/// PBKDF2 applies a pseudorandom function, such as a cryptographic hash, cipher, or 
+	/// HMAC to the input password or passphrase along with a salt value and repeats the 
+	/// process many times to produce a derived key, which can then be used as a 
+	/// cryptographic key in subsequent operations. The added computational work makes 
+	/// password cracking much more difficult, and is known as key stretching. 
+	/// When the standard was written in 2000, the recommended minimum number of 
+	/// iterations was 1000, but the parameter is intended to be increased over time as 
+	/// CPU speeds increase. Having a salt added to the password reduces the ability to 
+	/// use precomputed hashes (rainbow tables) for attacks, and means that multiple 
+	/// passwords have to be tested individually, not all at once. The standard 
+	/// recommends a salt length of at least 64 bits. [Wikipedia]
+	///
+	/// The PBKDF2 algorithm is implemented as a DigestEngine. The passphrase is specified
+	/// by calling update().
+	///
+	/// Example (WPA2):
+	///     PBKDF2Engine<HMACEngine<SHA1Engine> > pbkdf2(ssid, 4096, 256);
+	///     pbkdf2.update(passphrase);
+	///     DigestEngine::Digest d = pbkdf2.digest();
+{
+public:
+	enum
+	{
+		PRF_DIGEST_SIZE = PRF::DIGEST_SIZE
+	};
+	
+	PBKDF2Engine(const std::string& salt, unsigned c = 4096, Poco::UInt32 dkLen = PRF_DIGEST_SIZE):
+		_s(salt),
+		_c(c),
+		_dkLen(dkLen)
+	{		
+		_result.reserve(_dkLen + PRF_DIGEST_SIZE);
+	}
+	
+	~PBKDF2Engine()
+	{
+	}
+		
+	std::size_t digestLength() const
+	{
+		return _dkLen;
+	}
+	
+	void reset()
+	{
+		_p.clear();
+		_result.clear();
+	}
+	
+	const DigestEngine::Digest& digest()
+	{
+		Poco::UInt32 i = 1;
+		while (_result.size() < _dkLen)
+		{
+			f(i++);
+		}
+		_result.resize(_dkLen);
+		return _result;
+	}
+
+protected:
+	void updateImpl(const void* data, std::size_t length)
+	{
+		_p.append(reinterpret_cast<const char*>(data), length);
+	}
+	
+	void f(Poco::UInt32 i)
+	{
+		PRF prf(_p);
+		prf.update(_s);
+		Poco::UInt32 iBE = Poco::ByteOrder::toBigEndian(i);
+		prf.update(&iBE, sizeof(iBE));
+		Poco::DigestEngine::Digest up = prf.digest();
+		Poco::DigestEngine::Digest ux = up;
+		poco_assert_dbg(ux.size() == PRF_DIGEST_SIZE);
+		for (unsigned k = 1; k < _c; k++)
+		{
+			prf.reset();
+			prf.update(&up[0], up.size());
+			Poco::DigestEngine::Digest u = prf.digest();
+			poco_assert_dbg(u.size() == PRF_DIGEST_SIZE);
+			for (int ui = 0; ui < PRF_DIGEST_SIZE; ui++)
+			{
+				ux[ui] ^= u[ui];
+			}
+			std::swap(up, u);
+		}
+		_result.insert(_result.end(), ux.begin(), ux.end());
+	}
+
+private:
+	PBKDF2Engine();
+	PBKDF2Engine(const PBKDF2Engine&);
+	PBKDF2Engine& operator = (const PBKDF2Engine&);
+
+	std::string _p;
+	std::string _s;
+	unsigned _c;
+	Poco::UInt32 _dkLen;
+	DigestEngine::Digest _result;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PBKDF2Engine_INCLUDED
diff --git a/Poco/Path.h b/Poco/Path.h
new file mode 100644
index 0000000..c50c1a1
--- /dev/null
+++ b/Poco/Path.h
@@ -0,0 +1,501 @@
+//
+// Path.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  Path
+//
+// Definition of the Path class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Path_INCLUDED
+#define Foundation_Path_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API Path
+	/// This class represents filesystem paths in a 
+	/// platform-independent manner.
+	/// Unix, Windows and OpenVMS all use a different
+	/// syntax for filesystem paths.
+	/// This class can work with all three formats.
+	/// A path is made up of an optional node name
+	/// (only Windows and OpenVMS), an optional
+	/// device name (also only Windows and OpenVMS),
+	/// a list of directory names and an optional
+	/// filename.
+{
+public:
+	enum Style
+	{
+		PATH_UNIX,    /// Unix-style path
+		PATH_WINDOWS, /// Windows-style path
+		PATH_VMS,     /// VMS-style path
+		PATH_NATIVE,  /// The current platform's native style
+		PATH_GUESS    /// Guess the style by examining the path
+	};
+	
+	typedef std::vector<std::string> StringVec;
+
+	Path();
+		/// Creates an empty relative path.
+
+	Path(bool absolute);
+		/// Creates an empty absolute or relative path.
+
+	Path(const char* path);
+		/// Creates a path from a string.
+
+	Path(const char* path, Style style);
+		/// Creates a path from a string.
+
+	Path(const std::string& path);
+		/// Creates a path from a string.
+
+	Path(const std::string& path, Style style);
+		/// Creates a path from a string.
+
+	Path(const Path& path);
+		/// Copy constructor
+
+	Path(const Path& parent, const std::string& fileName);
+		/// Creates a path from a parent path and a filename.
+		/// The parent path is expected to reference a directory.
+
+	Path(const Path& parent, const char* fileName);
+		/// Creates a path from a parent path and a filename.
+		/// The parent path is expected to reference a directory.
+
+	Path(const Path& parent, const Path& relative);
+		/// Creates a path from a parent path and a relative path.
+		/// The parent path is expected to reference a directory.
+		/// The relative path is appended to the parent path.
+
+	~Path();
+		/// Destroys the Path.
+		
+	Path& operator = (const Path& path);
+		/// Assignment operator.
+		
+	Path& operator = (const std::string& path);
+		/// Assigns a string containing a path in native format.
+
+	Path& operator = (const char* path);
+		/// Assigns a string containing a path in native format.
+
+	void swap(Path& path);
+		/// Swaps the path with another one.
+
+	Path& assign(const std::string& path);
+		/// Assigns a string containing a path in native format.
+		
+	Path& assign(const std::string& path, Style style);
+		/// Assigns a string containing a path.
+
+	Path& assign(const Path& path);
+		/// Assigns the given path.
+		
+	Path& assign(const char* path);
+		/// Assigns a string containing a path.
+
+	std::string toString() const;
+		/// Returns a string containing the path in native format.
+		
+	std::string toString(Style style) const;
+		/// Returns a string containing the path in the given format.
+		
+	Path& parse(const std::string& path);
+		/// Same as assign().
+
+	Path& parse(const std::string& path, Style style);
+		/// Assigns a string containing a path.
+
+	bool tryParse(const std::string& path);
+		/// Tries to interpret the given string as a path
+		/// in native format.
+		/// If the path is syntactically valid, assigns the
+		/// path and returns true. Otherwise leaves the 
+		/// object unchanged and returns false.
+
+	bool tryParse(const std::string& path, Style style);
+		/// Tries to interpret the given string as a path,
+		/// according to the given style.
+		/// If the path is syntactically valid, assigns the
+		/// path and returns true. Otherwise leaves the
+		/// object unchanged and returns false.
+
+	Path& parseDirectory(const std::string& path);
+		/// The resulting path always refers to a directory and
+		/// the filename part is empty.
+
+	Path& parseDirectory(const std::string& path, Style style);
+		/// The resulting path always refers to a directory and
+		/// the filename part is empty.
+
+	Path& makeDirectory();
+		/// If the path contains a filename, the filename is appended
+		/// to the directory list and cleared. Thus the resulting path
+		/// always refers to a directory.
+
+	Path& makeFile();
+		/// If the path contains no filename, the last directory
+		/// becomes the filename.
+
+	Path& makeParent();
+		/// Makes the path refer to its parent.
+		
+	Path& makeAbsolute();
+		/// Makes the path absolute if it is relative.
+		/// The current working directory is taken as base directory.
+
+	Path& makeAbsolute(const Path& base);
+		/// Makes the path absolute if it is relative.
+		/// The given path is taken as base. 
+
+	Path& append(const Path& path);
+		/// Appends the given path.
+		
+	Path& resolve(const Path& path);
+		/// Resolves the given path agains the current one.
+		///
+		/// If the given path is absolute, it replaces the current one.
+		/// Otherwise, the relative path is appended to the current path.
+
+	bool isAbsolute() const;
+		/// Returns true iff the path is absolute.
+		
+	bool isRelative() const;
+		/// Returns true iff the path is relative.
+	
+	bool isDirectory() const;
+		/// Returns true iff the path references a directory
+		/// (the filename part is empty).
+		
+	bool isFile() const;
+		/// Returns true iff the path references a file
+		/// (the filename part is not empty).
+	
+	Path& setNode(const std::string& node);
+		/// Sets the node name.
+		/// Setting a non-empty node automatically makes
+		/// the path an absolute one.
+		
+	const std::string& getNode() const;
+		/// Returns the node name.
+		
+	Path& setDevice(const std::string& device);
+		/// Sets the device name.
+		/// Setting a non-empty device automatically makes
+		/// the path an absolute one.
+		
+	const std::string& getDevice() const;
+		/// Returns the device name.
+	
+	int depth() const;
+		/// Returns the number of directories in the directory list.
+
+	const std::string& directory(int n) const;
+		/// Returns the n'th directory in the directory list.
+		/// If n == depth(), returns the filename.
+		
+	const std::string& operator [] (int n) const;
+		/// Returns the n'th directory in the directory list.
+		/// If n == depth(), returns the filename.
+		
+	Path& pushDirectory(const std::string& dir);
+		/// Adds a directory to the directory list.
+		
+	Path& popDirectory();
+		/// Removes the last directory from the directory list.
+		
+	Path& popFrontDirectory();
+		/// Removes the first directory from the directory list.
+		
+	Path& setFileName(const std::string& name);
+		/// Sets the filename.
+		
+	const std::string& getFileName() const;
+		/// Returns the filename.
+
+	Path& setBaseName(const std::string& name);
+		/// Sets the basename part of the filename and
+		/// does not change the extension.
+
+	std::string getBaseName() const;
+		/// Returns the basename (the filename sans
+		/// extension) of the path.
+
+	Path& setExtension(const std::string& extension);
+		/// Sets the filename extension.
+				
+	std::string getExtension() const;
+		/// Returns the filename extension.
+		
+	const std::string& version() const;
+		/// Returns the file version. VMS only.
+		
+	Path& clear();
+		/// Clears all components.
+
+	Path parent() const;
+		/// Returns a path referring to the path's
+		/// directory.
+		
+	Path absolute() const;
+		/// Returns an absolute variant of the path,
+		/// taking the current working directory as base.
+
+	Path absolute(const Path& base) const;
+		/// Returns an absolute variant of the path,
+		/// taking the given path as base.
+
+	static Path forDirectory(const std::string& path);
+		/// Creates a path referring to a directory.
+
+	static Path forDirectory(const std::string& path, Style style);
+		/// Creates a path referring to a directory.
+
+	static char separator();
+		/// Returns the platform's path name separator, which separates
+		/// the components (names) in a path. 
+		///
+		/// On Unix systems, this is the slash '/'. On Windows systems, 
+		/// this is the backslash '\'. On OpenVMS systems, this is the
+		/// period '.'.
+		
+	static char pathSeparator();
+		/// Returns the platform's path separator, which separates
+		/// single paths in a list of paths.
+		///
+		/// On Unix systems, this is the colon ':'. On Windows systems,
+		/// this is the semicolon ';'. On OpenVMS systems, this is the
+		/// comma ','.
+
+	static std::string current();
+		/// Returns the current working directory.
+		
+	static std::string home();
+		/// Returns the user's home directory.
+
+	static std::string configHome();
+		/// Returns the user's config directory.
+		///
+		/// On Unix systems, this is the '~/.config/'. On Windows systems,
+		/// this is '%APPDATA%'.
+
+	static std::string dataHome();
+		/// Returns the user's data directory.
+		///
+		/// On Unix systems, this is the '~/.local/share/'. On Windows systems,
+		/// this is '%APPDATA%'.
+
+	static std::string tempHome();
+		/// Returns the user's temp directory.
+		///
+		/// On Unix systems, this is the '~/.local/temp/'.
+
+	static std::string cacheHome();
+		/// Returns the user's cache directory.
+		///
+		/// On Unix systems, this is the '~/.cache/'. On Windows systems,
+		/// this is '%APPDATA%'.
+
+	static std::string temp();
+		/// Returns the temporary directory.
+		
+	static std::string config();
+		/// Returns the systemwide config directory.
+		///
+		/// On Unix systems, this is the '/etc/'.
+		
+	static std::string null();
+		/// Returns the name of the null device.
+		
+	static std::string expand(const std::string& path);
+		/// Expands all environment variables contained in the path.
+		///
+		/// On Unix, a tilde as first character in the path is
+		/// replaced with the path to user's home directory.
+
+	static void listRoots(std::vector<std::string>& roots);
+		/// Fills the vector with all filesystem roots available on the
+		/// system. On Unix, there is exactly one root, "/".
+		/// On Windows, the roots are the drive letters.
+		/// On OpenVMS, the roots are the mounted disks.
+		
+	static bool find(StringVec::const_iterator it, StringVec::const_iterator end, const std::string& name, Path& path);
+		/// Searches the file with the given name in the locations (paths) specified
+		/// by it and end. A relative path may be given in name.
+		///
+		/// If the file is found in one of the locations, the complete
+		/// path of the file is stored in the path given as argument and true is returned. 
+		/// Otherwise false is returned and the path argument remains unchanged.
+
+	static bool find(const std::string& pathList, const std::string& name, Path& path);
+		/// Searches the file with the given name in the locations (paths) specified
+		/// in pathList. The paths in pathList must be delimited by the platform's
+		/// path separator (see pathSeparator()). A relative path may be given in name.
+		///
+		/// If the file is found in one of the locations, the complete
+		/// path of the file is stored in the path given as argument and true is returned. 
+		/// Otherwise false is returned and the path argument remains unchanged.
+		
+	static std::string transcode(const std::string& path);
+		/// On Windows, if POCO has been compiled with Windows UTF-8 support 
+		/// (POCO_WIN32_UTF8), this function converts a string (usually containing a path) 
+		/// encoded in UTF-8 into a string encoded in the current Windows code page.
+		/// 
+		/// This function should be used for every string passed as a file name to
+		/// a string stream or fopen().
+		///
+		/// On all other platforms, or if POCO has not been compiled with Windows UTF-8
+		/// support, this function returns the string unchanged.
+
+protected:
+	void parseUnix(const std::string& path);
+	void parseWindows(const std::string& path);
+	void parseVMS(const std::string& path);
+	void parseGuess(const std::string& path);
+	std::string buildUnix() const;
+	std::string buildWindows() const;
+	std::string buildVMS() const;
+
+private:
+	std::string _node;
+	std::string _device;
+	std::string _name;
+	std::string _version;
+	StringVec   _dirs;
+	bool        _absolute;
+};
+
+
+//
+// inlines
+//
+inline bool Path::isAbsolute() const
+{
+	return _absolute;
+}
+
+	
+inline bool Path::isRelative() const
+{
+	return !_absolute;
+}
+
+
+inline bool Path::isDirectory() const
+{
+	return _name.empty();
+}
+
+
+inline bool Path::isFile() const
+{
+	return !_name.empty();
+}
+
+
+inline Path& Path::parse(const std::string& path)
+{
+	return assign(path);
+}
+
+
+inline Path& Path::parse(const std::string& path, Style style)
+{
+	return assign(path, style);
+}
+
+
+inline const std::string& Path::getNode() const
+{
+	return _node;
+}
+
+
+inline const std::string& Path::getDevice() const
+{
+	return _device;
+}
+
+
+inline const std::string& Path::getFileName() const
+{
+	return _name;
+}
+
+
+inline int Path::depth() const
+{
+	return int(_dirs.size());
+}
+
+
+inline const std::string& Path::version() const
+{
+	return _version;
+}
+
+
+inline Path Path::forDirectory(const std::string& path)
+{
+	Path p;
+	return p.parseDirectory(path);
+}
+	
+
+inline Path Path::forDirectory(const std::string& path, Style style)
+{
+	Path p;
+	return p.parseDirectory(path, style);
+}
+
+
+inline char Path::separator()
+{
+#if defined(POCO_OS_FAMILY_VMS)
+	return '.';
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+	return '\\';
+#else
+	return '/';
+#endif
+}
+
+
+inline char Path::pathSeparator()
+{
+#if defined(POCO_OS_FAMILY_VMS)
+	return ',';
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+	return ';';
+#else
+	return ':';
+#endif
+}
+
+
+inline void swap(Path& p1, Path& p2)
+{
+	p1.swap(p2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Path_INCLUDED
diff --git a/Poco/Path_UNIX.h b/Poco/Path_UNIX.h
new file mode 100644
index 0000000..50a6478
--- /dev/null
+++ b/Poco/Path_UNIX.h
@@ -0,0 +1,48 @@
+//
+// Path_UNIX.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  Path
+//
+// Definition of the PathImpl class fo rUnix.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Path_UNIX_INCLUDED
+#define Foundation_Path_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class PathImpl
+{
+public:
+	static std::string currentImpl();
+	static std::string homeImpl();
+	static std::string configHomeImpl();
+	static std::string dataHomeImpl();
+	static std::string tempHomeImpl();
+	static std::string cacheHomeImpl();
+	static std::string tempImpl();
+	static std::string configImpl();
+	static std::string nullImpl();
+	static std::string expandImpl(const std::string& path);
+	static void listRootsImpl(std::vector<std::string>& roots);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Path_UNIX_INCLUDED
diff --git a/Poco/Path_WIN32.h b/Poco/Path_WIN32.h
new file mode 100644
index 0000000..02a3a5b
--- /dev/null
+++ b/Poco/Path_WIN32.h
@@ -0,0 +1,49 @@
+//
+// Path_WIN32.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  Path
+//
+// Definition of the PathImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Path_WIN32_INCLUDED
+#define Foundation_Path_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API PathImpl
+{
+public:
+	static std::string currentImpl();
+	static std::string homeImpl();
+	static std::string configHomeImpl();
+	static std::string dataHomeImpl();
+	static std::string cacheHomeImpl();
+	static std::string tempHomeImpl();
+	static std::string tempImpl();
+	static std::string configImpl();
+	static std::string nullImpl();
+	static std::string systemImpl();
+	static std::string expandImpl(const std::string& path);
+	static void listRootsImpl(std::vector<std::string>& roots);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Path_WIN32_INCLUDED
diff --git a/Poco/Path_WIN32U.h b/Poco/Path_WIN32U.h
new file mode 100644
index 0000000..94fca2b
--- /dev/null
+++ b/Poco/Path_WIN32U.h
@@ -0,0 +1,54 @@
+//
+// Path_WIN32U.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  Path
+//
+// Definition of the PathImpl class for WIN32.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Path_WIN32U_INCLUDED
+#define Foundation_Path_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API PathImpl
+{
+public:
+	static std::string currentImpl();
+	static std::string homeImpl();
+	static std::string configHomeImpl();
+	static std::string dataHomeImpl();
+	static std::string cacheHomeImpl();
+	static std::string tempHomeImpl();
+	static std::string tempImpl();
+	static std::string configImpl();
+	static std::string nullImpl();
+	static std::string systemImpl();
+	static std::string expandImpl(const std::string& path);
+	static void listRootsImpl(std::vector<std::string>& roots);
+	
+	enum
+	{
+		MAX_PATH_LEN = 32767
+	};
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Path_WIN32U_INCLUDED
diff --git a/Poco/Path_WINCE.h b/Poco/Path_WINCE.h
new file mode 100644
index 0000000..a32e331
--- /dev/null
+++ b/Poco/Path_WINCE.h
@@ -0,0 +1,54 @@
+//
+// Path_WINCE.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  Path
+//
+// Definition of the PathImpl class for WIN32.
+//
+// Copyright (c) 2006-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Path_WINCE_INCLUDED
+#define Foundation_Path_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API PathImpl
+{
+public:
+	static std::string currentImpl();
+	static std::string homeImpl();
+	static std::string configHomeImpl();
+	static std::string dataHomeImpl();
+	static std::string cacheHomeImpl();
+	static std::string tempHomeImpl();
+	static std::string tempImpl();
+	static std::string configImpl();
+	static std::string nullImpl();
+	static std::string systemImpl();
+	static std::string expandImpl(const std::string& path);
+	static void listRootsImpl(std::vector<std::string>& roots);
+	
+	enum
+	{
+		MAX_PATH_LEN = 32767
+	};
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Path_WINCE_INCLUDED
diff --git a/Poco/PatternFormatter.h b/Poco/PatternFormatter.h
new file mode 100644
index 0000000..cdbb0f0
--- /dev/null
+++ b/Poco/PatternFormatter.h
@@ -0,0 +1,148 @@
+//
+// PatternFormatter.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  PatternFormatter
+//
+// Definition of the PatternFormatter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PatternFormatter_INCLUDED
+#define Foundation_PatternFormatter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Formatter.h"
+#include "Poco/Message.h"
+
+#include <vector>
+
+namespace Poco {
+
+
+class Foundation_API PatternFormatter: public Formatter
+	/// This Formatter allows for custom formatting of
+	/// log messages based on format patterns.
+	///
+	/// The format pattern is used as a template to format the message and
+	/// is copied character by character except for the following special characters,
+	/// which are replaced by the corresponding value.
+	///
+	///   * %s - message source
+	///   * %t - message text
+	///   * %l - message priority level (1 .. 7)
+	///   * %p - message priority (Fatal, Critical, Error, Warning, Notice, Information, Debug, Trace)
+	///   * %q - abbreviated message priority (F, C, E, W, N, I, D, T)
+	///   * %P - message process identifier
+	///   * %T - message thread name
+	///   * %I - message thread identifier (numeric)
+	///   * %N - node or host name
+	///   * %U - message source file path (empty string if not set)
+	///   * %u - message source line number (0 if not set)
+	///   * %w - message date/time abbreviated weekday (Mon, Tue, ...)
+	///   * %W - message date/time full weekday (Monday, Tuesday, ...)
+	///   * %b - message date/time abbreviated month (Jan, Feb, ...)
+	///   * %B - message date/time full month (January, February, ...)
+	///   * %d - message date/time zero-padded day of month (01 .. 31)
+	///   * %e - message date/time day of month (1 .. 31)
+	///   * %f - message date/time space-padded day of month ( 1 .. 31)
+	///   * %m - message date/time zero-padded month (01 .. 12)
+	///   * %n - message date/time month (1 .. 12)
+	///   * %o - message date/time space-padded month ( 1 .. 12)
+	///   * %y - message date/time year without century (70)
+	///   * %Y - message date/time year with century (1970)
+	///   * %H - message date/time hour (00 .. 23)
+	///   * %h - message date/time hour (00 .. 12)
+	///   * %a - message date/time am/pm
+	///   * %A - message date/time AM/PM
+	///   * %M - message date/time minute (00 .. 59)
+	///   * %S - message date/time second (00 .. 59)
+	///   * %i - message date/time millisecond (000 .. 999)
+	///   * %c - message date/time centisecond (0 .. 9)
+	///   * %F - message date/time fractional seconds/microseconds (000000 - 999999)
+	///   * %z - time zone differential in ISO 8601 format (Z or +NN.NN)
+	///   * %Z - time zone differential in RFC format (GMT or +NNNN)
+	///   * %L - convert time to local time (must be specified before any date/time specifier; does not itself output anything)
+	///   * %E - epoch time (UTC, seconds since midnight, January 1, 1970)
+	///   * %v[width] - the message source (%s) but text length is padded/cropped to 'width'
+	///   * %[name] - the value of the message parameter with the given name
+	///   * %% - percent sign
+
+{
+public:
+	PatternFormatter();
+		/// Creates a PatternFormatter.
+		/// The format pattern must be specified with
+		/// a call to setProperty.
+
+	PatternFormatter(const std::string& format);
+		/// Creates a PatternFormatter that uses the
+		/// given format pattern.
+
+	~PatternFormatter();
+		/// Destroys the PatternFormatter.
+
+	void format(const Message& msg, std::string& text);
+		/// Formats the message according to the specified
+		/// format pattern and places the result in text. 
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given name to the given value.
+		///
+		/// The following properties are supported:
+		/// 
+		///     * pattern: The format pattern. See the PatternFormatter class
+		///       for details.
+		///     * times: Specifies whether times are adjusted for local time
+		///       or taken as they are in UTC. Supported values are "local" and "UTC".
+		///
+		/// If any other property name is given, a PropertyNotSupported
+		/// exception is thrown.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name or
+		/// throws a PropertyNotSupported exception if the given
+		/// name is not recognized.
+
+	static const std::string PROP_PATTERN;
+	static const std::string PROP_TIMES;
+
+protected:
+	static const std::string& getPriorityName(int);
+		/// Returns a string for the given priority value.
+	
+private:
+	struct PatternAction
+	{
+		PatternAction(): key(0), length(0) 
+		{
+		}
+
+		char key;
+		int length;
+		std::string property;
+		std::string prepend;
+	};
+
+	void parsePattern();
+		/// Will parse the _pattern string into the vector of PatternActions,
+		/// which contains the message key, any text that needs to be written first
+		/// a proprety in case of %[] and required length.
+
+	std::vector<PatternAction> _patternActions;
+	bool _localTime;
+	std::string _pattern;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PatternFormatter_INCLUDED
diff --git a/Poco/Pipe.h b/Poco/Pipe.h
new file mode 100644
index 0000000..89704b1
--- /dev/null
+++ b/Poco/Pipe.h
@@ -0,0 +1,142 @@
+//
+// Pipe.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Pipe
+//
+// Definition of the Pipe class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Pipe_INCLUDED
+#define Foundation_Pipe_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/PipeImpl.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Pipe
+	/// This class implements an anonymous pipe.
+	///
+	/// Pipes are a common method of inter-process communication -
+	/// on Unix, pipes are the oldest form of IPC.
+	///
+	/// A pipe is a half-duplex communication channel, which means
+	/// that data only flows in one direction.
+	/// Pipes have a read-end and a write-end. One process writes to
+	/// the pipe and another process reads the data written by
+	/// its peer. 
+	/// Read and write operations are always synchronous. A read will
+	/// block until data is available and a write will block until
+	/// the reader reads the data.
+	///
+	/// The sendBytes() and readBytes() methods of Pipe are usually
+	/// used through a PipeOutputStream or PipeInputStream and are
+	/// not called directly.
+	///
+	/// Pipe objects have value semantics; the actual work is delegated
+	/// to a reference-counted PipeImpl object.
+{
+public:
+	typedef PipeImpl::Handle Handle; /// The read/write handle or file descriptor.
+	
+	enum CloseMode /// used by close()
+	{
+		CLOSE_READ  = 0x01, /// Close reading end of pipe.
+		CLOSE_WRITE = 0x02, /// Close writing end of pipe.
+		CLOSE_BOTH  = 0x03  /// Close both ends of pipe.
+	};
+	
+	Pipe();
+		/// Creates the Pipe.
+		///
+		/// Throws a CreateFileException if the pipe cannot be
+		/// created.
+		
+	Pipe(const Pipe& pipe);
+		/// Creates the Pipe using the PipeImpl from another one.
+
+	~Pipe();
+		/// Closes and destroys the Pipe.
+
+	Pipe& operator = (const Pipe& pipe);
+		/// Releases the Pipe's PipeImpl and assigns another one.
+
+	int writeBytes(const void* buffer, int length);
+		/// Sends the contents of the given buffer through
+		/// the pipe. Blocks until the receiver is ready
+		/// to read the data.
+		///
+		/// Returns the number of bytes sent.
+		///
+		/// Throws a WriteFileException if the data cannot be written.
+
+	int readBytes(void* buffer, int length);
+		/// Receives data from the pipe and stores it
+		/// in buffer. Up to length bytes are received.
+		/// Blocks until data becomes available.
+		///
+		/// Returns the number of bytes received, or 0
+		/// if the pipe has been closed.
+		///
+		/// Throws a ReadFileException if nothing can be read.
+
+	Handle readHandle() const;
+		/// Returns the read handle or file descriptor
+		/// for the Pipe. For internal use only.
+		
+	Handle writeHandle() const;
+		/// Returns the write handle or file descriptor
+		/// for the Pipe. For internal use only.
+
+	void close(CloseMode mode = CLOSE_BOTH);
+		/// Depending on the argument, closes either the
+		/// reading end, the writing end, or both ends
+		/// of the Pipe.
+		
+private:
+	PipeImpl* _pImpl;
+};
+
+
+//
+// inlines
+//
+inline int Pipe::writeBytes(const void* buffer, int length)
+{
+	return _pImpl->writeBytes(buffer, length);
+}
+
+
+inline int Pipe::readBytes(void* buffer, int length)
+{
+	return _pImpl->readBytes(buffer, length);
+}
+
+
+inline Pipe::Handle Pipe::readHandle() const
+{
+	return _pImpl->readHandle();
+}
+
+
+inline Pipe::Handle Pipe::writeHandle() const
+{
+	return _pImpl->writeHandle();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Pipe_INCLUDED
diff --git a/Poco/PipeImpl.h b/Poco/PipeImpl.h
new file mode 100644
index 0000000..b0b7183
--- /dev/null
+++ b/Poco/PipeImpl.h
@@ -0,0 +1,37 @@
+//
+// PipeImpl.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  PipeImpl
+//
+// Definition of the PipeImpl class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PipeImpl_INCLUDED
+#define Foundation_PipeImpl_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#if defined(_WIN32_WCE)
+#include "PipeImpl_DUMMY.h"
+#else
+#include "Poco/PipeImpl_WIN32.h"
+#endif
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/PipeImpl_POSIX.h"
+#else
+#include "Poco/PipeImpl_DUMMY.h"
+#endif
+
+
+#endif // Foundation_PipeImpl_INCLUDED
diff --git a/Poco/PipeImpl_DUMMY.h b/Poco/PipeImpl_DUMMY.h
new file mode 100644
index 0000000..e7616ff
--- /dev/null
+++ b/Poco/PipeImpl_DUMMY.h
@@ -0,0 +1,49 @@
+//
+// PipeImpl_DUMMY.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  PipeImpl
+//
+// Definition of the PipeImpl_DUMMY class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PipeImpl_DUMMY_INCLUDED
+#define Foundation_PipeImpl_DUMMY_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Foundation_API PipeImpl: public RefCountedObject
+	/// A dummy implementation of PipeImpl for platforms
+	/// that do not support pipes.
+{
+public:
+	typedef int Handle;
+
+	PipeImpl();
+	~PipeImpl();
+	int writeBytes(const void* buffer, int length);
+	int readBytes(void* buffer, int length);
+	Handle readHandle() const;
+	Handle writeHandle() const;
+	void closeRead();
+	void closeWrite();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PipeImpl_DUMMY_INCLUDED
diff --git a/Poco/PipeImpl_POSIX.h b/Poco/PipeImpl_POSIX.h
new file mode 100644
index 0000000..448e616
--- /dev/null
+++ b/Poco/PipeImpl_POSIX.h
@@ -0,0 +1,53 @@
+//
+// PipeImpl_POSIX.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  PipeImpl
+//
+// Definition of the PipeImpl class for POSIX.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PipeImpl_POSIX_INCLUDED
+#define Foundation_PipeImpl_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Foundation_API PipeImpl: public RefCountedObject
+	/// A dummy implementation of PipeImpl for platforms
+	/// that do not support pipes.
+{
+public:
+	typedef int Handle;
+
+	PipeImpl();
+	~PipeImpl();
+	int writeBytes(const void* buffer, int length);
+	int readBytes(void* buffer, int length);
+	Handle readHandle() const;
+	Handle writeHandle() const;
+	void closeRead();
+	void closeWrite();
+	
+private:
+	int _readfd;
+	int _writefd;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PipeImpl_POSIX_INCLUDED
diff --git a/Poco/PipeImpl_WIN32.h b/Poco/PipeImpl_WIN32.h
new file mode 100644
index 0000000..9368179
--- /dev/null
+++ b/Poco/PipeImpl_WIN32.h
@@ -0,0 +1,54 @@
+//
+// PipeImpl_WIN32.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  PipeImpl
+//
+// Definition of the PipeImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PipeImpl_WIN32_INCLUDED
+#define Foundation_PipeImpl_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API PipeImpl: public RefCountedObject
+	/// A dummy implementation of PipeImpl for platforms
+	/// that do not support pipes.
+{
+public:
+	typedef HANDLE Handle;
+
+	PipeImpl();
+	~PipeImpl();
+	int writeBytes(const void* buffer, int length);
+	int readBytes(void* buffer, int length);
+	Handle readHandle() const;
+	Handle writeHandle() const;
+	void closeRead();
+	void closeWrite();
+	
+private:
+	HANDLE _readHandle;
+	HANDLE _writeHandle;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PipeImpl_WIN32_INCLUDED
diff --git a/Poco/PipeStream.h b/Poco/PipeStream.h
new file mode 100644
index 0000000..96b602a
--- /dev/null
+++ b/Poco/PipeStream.h
@@ -0,0 +1,120 @@
+//
+// PipeStream.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  PipeStream
+//
+// Definition of the PipeStream class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PipeStream_INCLUDED
+#define Foundation_PipeStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Pipe.h"
+#include "Poco/BufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API PipeStreamBuf: public BufferedStreamBuf
+	/// This is the streambuf class used for reading from and writing to a Pipe.
+{
+public:
+	typedef BufferedStreamBuf::openmode openmode;
+	
+	PipeStreamBuf(const Pipe& pipe, openmode mode);
+		/// Creates a PipeStreamBuf with the given Pipe.
+
+	~PipeStreamBuf();
+		/// Destroys the PipeStreamBuf.
+		
+	void close();
+		/// Closes the pipe.
+		
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE = 1024
+	};
+
+	Pipe _pipe;
+};
+
+
+class Foundation_API PipeIOS: public virtual std::ios
+	/// The base class for PipeInputStream and
+	/// PipeOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	PipeIOS(const Pipe& pipe, openmode mode);
+		/// Creates the PipeIOS with the given Pipe.
+		
+	~PipeIOS();
+		/// Destroys the PipeIOS.
+		///
+		/// Flushes the buffer, but does not close the pipe.
+		
+	PipeStreamBuf* rdbuf();
+		/// Returns a pointer to the internal PipeStreamBuf.
+		
+	void close();
+		/// Flushes the stream and closes the pipe.
+
+protected:
+	PipeStreamBuf _buf;
+};
+
+
+class Foundation_API PipeOutputStream: public PipeIOS, public std::ostream
+	/// An output stream for writing to a Pipe.
+{
+public:
+	PipeOutputStream(const Pipe& pipe);
+		/// Creates the PipeOutputStream with the given Pipe.
+
+	~PipeOutputStream();
+		/// Destroys the PipeOutputStream.
+		///
+		/// Flushes the buffer, but does not close the pipe.
+};
+
+
+class Foundation_API PipeInputStream: public PipeIOS, public std::istream
+	/// An input stream for reading from a Pipe.
+	///
+	/// Using formatted input from a PipeInputStream
+	/// is not recommended, due to the read-ahead behavior of
+	/// istream with formatted reads.
+{
+public:
+	PipeInputStream(const Pipe& pipe);
+		/// Creates the PipeInputStream with the given Pipe.
+
+	~PipeInputStream();
+		/// Destroys the PipeInputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PipeStream_INCLUDED
diff --git a/Poco/Platform.h b/Poco/Platform.h
new file mode 100644
index 0000000..0d5ebdf
--- /dev/null
+++ b/Poco/Platform.h
@@ -0,0 +1,284 @@
+//
+// Platform.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Platform
+//
+// Platform and architecture identification macros.
+//
+// NOTE: This file may be included from both C++ and C code, so it
+//       must not contain any C++ specific things.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Platform_INCLUDED
+#define Foundation_Platform_INCLUDED
+
+
+//
+// Platform Identification
+//
+#define POCO_OS_FREE_BSD      0x0001
+#define POCO_OS_AIX           0x0002
+#define POCO_OS_HPUX          0x0003
+#define POCO_OS_TRU64         0x0004
+#define POCO_OS_LINUX         0x0005
+#define POCO_OS_MAC_OS_X      0x0006
+#define POCO_OS_NET_BSD       0x0007
+#define POCO_OS_OPEN_BSD      0x0008
+#define POCO_OS_IRIX          0x0009
+#define POCO_OS_SOLARIS       0x000a
+#define POCO_OS_QNX           0x000b
+#define POCO_OS_VXWORKS       0x000c
+#define POCO_OS_CYGWIN        0x000d
+#define POCO_OS_NACL	      0x000e
+#define POCO_OS_ANDROID       0x000f
+#define POCO_OS_UNKNOWN_UNIX  0x00ff
+#define POCO_OS_WINDOWS_NT    0x1001
+#define POCO_OS_WINDOWS_CE    0x1011
+#define POCO_OS_VMS           0x2001
+
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS_FAMILY_BSD 1
+	#define POCO_OS POCO_OS_FREE_BSD
+#elif defined(_AIX) || defined(__TOS_AIX__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_AIX
+#elif defined(hpux) || defined(_hpux) || defined(__hpux)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_HPUX
+#elif defined(__digital__) || defined(__osf__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_TRU64
+#elif defined(__NACL__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_NACL
+#elif defined(linux) || defined(__linux) || defined(__linux__) || defined(__TOS_LINUX__) || defined(EMSCRIPTEN)
+	#define POCO_OS_FAMILY_UNIX 1
+	#if defined(__ANDROID__)
+		#define POCO_OS POCO_OS_ANDROID
+	#else
+		#define POCO_OS POCO_OS_LINUX
+	#endif
+#elif defined(__APPLE__) || defined(__TOS_MACOS__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS_FAMILY_BSD 1
+	#define POCO_OS POCO_OS_MAC_OS_X
+#elif defined(__NetBSD__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS_FAMILY_BSD 1
+	#define POCO_OS POCO_OS_NET_BSD
+#elif defined(__OpenBSD__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS_FAMILY_BSD 1
+	#define POCO_OS POCO_OS_OPEN_BSD
+#elif defined(sgi) || defined(__sgi)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_IRIX
+#elif defined(sun) || defined(__sun)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_SOLARIS
+#elif defined(__QNX__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_QNX
+#elif defined(__CYGWIN__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_CYGWIN
+#elif defined(POCO_VXWORKS)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_VXWORKS
+#elif defined(unix) || defined(__unix) || defined(__unix__)
+	#define POCO_OS_FAMILY_UNIX 1
+	#define POCO_OS POCO_OS_UNKNOWN_UNIX
+#elif defined(_WIN32_WCE)
+	#define POCO_OS_FAMILY_WINDOWS 1
+	#define POCO_OS POCO_OS_WINDOWS_CE
+#elif defined(_WIN32) || defined(_WIN64)
+	#define POCO_OS_FAMILY_WINDOWS 1
+	#define POCO_OS POCO_OS_WINDOWS_NT
+#elif defined(__VMS)
+	#define POCO_OS_FAMILY_VMS 1
+	#define POCO_OS POCO_OS_VMS
+#endif
+
+
+#if !defined(POCO_OS)
+	#error "Unknown Platform."
+#endif
+
+
+//
+// Hardware Architecture and Byte Order
+//
+#define POCO_ARCH_ALPHA   0x01
+#define POCO_ARCH_IA32    0x02
+#define POCO_ARCH_IA64    0x03
+#define POCO_ARCH_MIPS    0x04
+#define POCO_ARCH_HPPA    0x05
+#define POCO_ARCH_PPC     0x06
+#define POCO_ARCH_POWER   0x07
+#define POCO_ARCH_SPARC   0x08
+#define POCO_ARCH_AMD64   0x09
+#define POCO_ARCH_ARM     0x0a
+#define POCO_ARCH_M68K    0x0b
+#define POCO_ARCH_S390    0x0c
+#define POCO_ARCH_SH      0x0d
+#define POCO_ARCH_NIOS2   0x0e
+#define POCO_ARCH_AARCH64 0x0f
+#define POCO_ARCH_ARM64   0x0f // same as POCO_ARCH_AARCH64
+#define POCO_ARCH_RISCV64 0x10
+
+
+#if defined(__ALPHA) || defined(__alpha) || defined(__alpha__) || defined(_M_ALPHA)
+	#define POCO_ARCH POCO_ARCH_ALPHA
+	#define POCO_ARCH_LITTLE_ENDIAN 1
+#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(EMSCRIPTEN)
+	#define POCO_ARCH POCO_ARCH_IA32
+	#define POCO_ARCH_LITTLE_ENDIAN 1
+#elif defined(_IA64) || defined(__IA64__) || defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
+	#define POCO_ARCH POCO_ARCH_IA64
+	#if defined(hpux) || defined(_hpux)
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#else
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#endif
+#elif defined(__x86_64__) || defined(_M_X64)
+	#define POCO_ARCH POCO_ARCH_AMD64
+	#define POCO_ARCH_LITTLE_ENDIAN 1
+#elif defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(_M_MRX000)
+	#define POCO_ARCH POCO_ARCH_MIPS
+	#if defined(POCO_OS_FAMILY_WINDOWS)
+		// Is this OK? Supports windows only little endian??
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#elif defined(__MIPSEB__) || defined(_MIPSEB) || defined(__MIPSEB)
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#elif defined(__MIPSEL__) || defined(_MIPSEL) || defined(__MIPSEL)
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#else
+		#error "MIPS but neither MIPSEL nor MIPSEB?"
+	#endif
+#elif defined(__hppa) || defined(__hppa__)
+	#define POCO_ARCH POCO_ARCH_HPPA
+	#define POCO_ARCH_BIG_ENDIAN 1
+#elif defined(__PPC) || defined(__POWERPC__) || defined(__powerpc) || defined(__PPC__) || \
+      defined(__powerpc__) || defined(__ppc__) || defined(__ppc) || defined(_ARCH_PPC) || defined(_M_PPC)
+	#define POCO_ARCH POCO_ARCH_PPC
+	#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#else
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#endif
+#elif defined(_POWER) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_ARCH_PWR3) || \
+      defined(_ARCH_PWR4) || defined(__THW_RS6000)
+	#define POCO_ARCH POCO_ARCH_POWER
+	#define POCO_ARCH_BIG_ENDIAN 1
+#elif defined(__sparc__) || defined(__sparc) || defined(sparc)
+	#define POCO_ARCH POCO_ARCH_SPARC
+	#define POCO_ARCH_BIG_ENDIAN 1
+#elif defined(__arm__) || defined(__arm) || defined(ARM) || defined(_ARM_) || defined(__ARM__) || defined(_M_ARM)
+	#define POCO_ARCH POCO_ARCH_ARM
+	#if defined(__ARMEB__)
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#else
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#endif
+#elif defined(__arm64__) || defined(__arm64) || defined(_M_ARM64)
+	#define POCO_ARCH POCO_ARCH_ARM64
+	#if defined(__ARMEB__)
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#else
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#endif
+#elif defined(__m68k__)
+	#define POCO_ARCH POCO_ARCH_M68K
+	#define POCO_ARCH_BIG_ENDIAN 1
+#elif defined(__s390__)
+	#define POCO_ARCH POCO_ARCH_S390
+	#define POCO_ARCH_BIG_ENDIAN 1
+#elif defined(__sh__) || defined(__sh) || defined(SHx) || defined(_SHX_)
+	#define POCO_ARCH POCO_ARCH_SH
+	#if defined(__LITTLE_ENDIAN__) || (POCO_OS == POCO_OS_WINDOWS_CE)
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#else
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#endif
+#elif defined (nios2) || defined(__nios2) || defined(__nios2__)
+	#define POCO_ARCH POCO_ARCH_NIOS2
+	#if defined(__nios2_little_endian) || defined(nios2_little_endian) || defined(__nios2_little_endian__)
+		#define POCO_ARCH_LITTLE_ENDIAN 1
+	#else
+		#define POCO_ARCH_BIG_ENDIAN 1
+	#endif
+#elif defined(__AARCH64EL__)
+	#define POCO_ARCH POCO_ARCH_AARCH64
+	#define POCO_ARCH_LITTLE_ENDIAN 1
+#elif defined(__AARCH64EB__)
+	#define POCO_ARCH POCO_ARCH_AARCH64
+	#define POCO_ARCH_BIG_ENDIAN 1
+#elif defined(__riscv) && (__riscv_xlen == 64)
+	#define POCO_ARCH POCO_ARCH_RISCV64
+	#define POCO_ARCH_LITTLE_ENDIAN 1
+#endif
+
+
+#if defined(__clang__)
+	#define POCO_COMPILER_CLANG
+#elif defined(_MSC_VER)
+	#define POCO_COMPILER_MSVC
+#elif defined (__GNUC__)
+	#define POCO_COMPILER_GCC
+#elif defined (__MINGW32__) || defined (__MINGW64__)
+	#define POCO_COMPILER_MINGW
+#elif defined (__INTEL_COMPILER) || defined(__ICC) || defined(__ECC) || defined(__ICL)
+	#define POCO_COMPILER_INTEL
+#elif defined (__SUNPRO_CC)
+	#define POCO_COMPILER_SUN
+#elif defined (__MWERKS__) || defined(__CWCC__)
+	#define POCO_COMPILER_CODEWARRIOR
+#elif defined (__sgi) || defined(sgi)
+	#define POCO_COMPILER_SGI
+#elif defined (__HP_aCC)
+	#define POCO_COMPILER_HP_ACC
+#elif defined (__BORLANDC__) || defined(__CODEGEARC__)
+	#define POCO_COMPILER_CBUILDER
+#elif defined (__DMC__)
+	#define POCO_COMPILER_DMARS
+#elif defined (__DECCXX)
+	#define POCO_COMPILER_COMPAC
+#elif (defined (__xlc__) || defined (__xlC__)) && defined(__IBMCPP__)
+	#define POCO_COMPILER_IBM_XLC // IBM XL C++
+#elif defined (__IBMCPP__) && defined(__COMPILER_VER__)
+	#define POCO_COMPILER_IBM_XLC_ZOS // IBM z/OS C++
+#endif
+
+
+#ifdef __GNUC__
+#define POCO_UNUSED __attribute__((unused))
+#else
+#define POCO_UNUSED
+#endif // __GNUC__
+
+
+#if !defined(POCO_ARCH)
+	#error "Unknown Hardware Architecture."
+#endif
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+	#define POCO_DEFAULT_NEWLINE_CHARS "\r\n"
+#else
+	#define POCO_DEFAULT_NEWLINE_CHARS "\n"
+#endif
+
+
+#endif // Foundation_Platform_INCLUDED
diff --git a/Poco/Platform_POSIX.h b/Poco/Platform_POSIX.h
new file mode 100644
index 0000000..699735e
--- /dev/null
+++ b/Poco/Platform_POSIX.h
@@ -0,0 +1,53 @@
+//
+// Platform_POSIX.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Platform
+//
+// Platform and architecture identification macros
+// and platform-specific definitions for various POSIX platforms
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Platform_POSIX_INCLUDED
+#define Foundation_Platform_POSIX_INCLUDED
+
+
+//
+// PA-RISC based HP-UX platforms have some issues...
+//
+#if defined(hpux) || defined(_hpux)
+	#if defined(__hppa) || defined(__hppa__)
+		#define POCO_NO_SYS_SELECT_H 1
+		#if defined(__HP_aCC)
+			#define POCO_NO_TEMPLATE_ICOMPARE 1
+		#endif
+	#endif
+#endif
+
+
+//
+// Thread-safety of local static initialization
+//
+#if __cplusplus >= 201103L || __GNUC__ >= 4 || defined(__clang__)
+	#ifndef POCO_LOCAL_STATIC_INIT_IS_THREADSAFE
+		#define POCO_LOCAL_STATIC_INIT_IS_THREADSAFE 1
+	#endif
+#endif
+
+
+//
+// No syslog.h on QNX/BB10
+//
+#if defined(__QNXNTO__)
+	#define POCO_NO_SYSLOGCHANNEL
+#endif
+
+
+#endif // Foundation_Platform_POSIX_INCLUDED
diff --git a/Poco/Platform_VX.h b/Poco/Platform_VX.h
new file mode 100644
index 0000000..f21e822
--- /dev/null
+++ b/Poco/Platform_VX.h
@@ -0,0 +1,29 @@
+//
+// Platform_VX.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Platform
+//
+// Platform and architecture identification macros
+// and platform-specific definitions for VxWorks
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Platform_VX_INCLUDED
+#define Foundation_Platform_VX_INCLUDED
+
+
+#define POCO_NO_SYS_SELECT_H 
+#define POCO_NO_FPENVIRONMENT
+#define POCO_NO_WSTRING 
+#define POCO_NO_SHAREDMEMORY
+#define POCO_NO_SYSLOGCHANNEL
+
+
+#endif // Foundation_Platform_VX_INCLUDED
diff --git a/Poco/Platform_WIN32.h b/Poco/Platform_WIN32.h
new file mode 100644
index 0000000..65bc829
--- /dev/null
+++ b/Poco/Platform_WIN32.h
@@ -0,0 +1,216 @@
+//
+// Platform_WIN32.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Platform
+//
+// Platform and architecture identification macros
+// and platform-specific definitions for Windows.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Platform_WIN32_INCLUDED
+#define Foundation_Platform_WIN32_INCLUDED
+
+
+#include "Poco/UnWindows.h"
+
+
+#ifndef POCO_FORCE_MIN_WINDOWS_OS_SUPPORT
+	// Determine the real version.
+	// This setting can be forced from UnWindows.h
+	#if defined (_WIN32_WINNT_WINBLUE)
+		//Windows 8.1 _WIN32_WINNT_WINBLUE (0x0602)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WINBLUE
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_WINBLUE
+	#elif defined (_WIN32_WINNT_WIN8)
+		//Windows 8	_WIN32_WINNT_WIN8 (0x0602)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WIN8
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_WIN8
+	#elif defined (_WIN32_WINNT_WIN7)
+		//Windows 7	_WIN32_WINNT_WIN7 (0x0601)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WIN7
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_WIN7
+	#elif defined (_WIN32_WINNT_WS08)
+		//Windows Server 2008 _WIN32_WINNT_WS08 (0x0600)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WS08
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_WS08
+	#elif defined (_WIN32_WINNT_VISTA)
+		//Windows Vista	_WIN32_WINNT_VISTA (0x0600)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_VISTA
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_VISTA
+	#elif defined (_WIN32_WINNT_LONGHORN)
+		//Windows Vista	and server 2008 Development _WIN32_WINNT_LONGHORN (0x0600)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_LONGHORN
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION 0x06000000 // hardcoded, VS90 can't find NTDDI_* macros
+	#elif defined (_WIN32_WINNT_WS03)
+		//Windows Server 2003 with SP1,
+		//Windows XP with SP2 _WIN32_WINNT_WS03 (0x0502)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WS03
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_WS03
+	#elif defined (_WIN32_WINNT_WINXP)
+		//Windows Server 2003, Windows XP _WIN32_WINNT_WINXP (0x0501)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WINXP
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION NTDDI_WINXP
+	#elif defined (_WIN32_WINNT_WIN2K)
+		//Windows 2000 _WIN32_WINNT_WIN2K (0x0500)
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT _WIN32_WINNT_WIN2K
+	#elif defined (WINVER)
+		// fail back on WINVER
+		#ifdef _WIN32_WINNT
+			#undef _WIN32_WINNT
+		#endif
+		#define _WIN32_WINNT WINVER
+	#elif !defined(_WIN32_WINNT)
+		// last resort = Win XP, SP1 is minimum supported
+		#define _WIN32_WINNT 0x0501
+		#ifdef NTDDI_VERSION
+			#undef NTDDI_VERSION
+		#endif
+		#define NTDDI_VERSION 0x05010100
+	#endif
+#endif // POCO_FORCE_MIN_WINDOWS_OS_SUPPORT
+
+
+#if defined(_MSC_VER) && !defined(POCO_MSVC_SECURE_WARNINGS) && !defined(_CRT_SECURE_NO_DEPRECATE)
+	#define _CRT_SECURE_NO_DEPRECATE
+#endif 
+
+
+// Verify that we're built with the multithreaded 
+// versions of the runtime libraries
+#if defined(_MSC_VER) && !defined(_MT)
+	#error Must compile with /MD, /MDd, /MT or /MTd
+#endif
+
+
+// Check debug/release settings consistency
+#if defined(NDEBUG) && defined(_DEBUG)
+	#error Inconsistent build settings (check for /MD[d])
+#endif
+
+
+#if (_MSC_VER >= 1300) && (_MSC_VER < 1400)   // Visual Studio 2003, MSVC++ 7.1
+	#define POCO_MSVS_VERSION 2003
+	#define POCO_MSVC_VERSION 71
+#elif (_MSC_VER >= 1400) && (_MSC_VER < 1500) // Visual Studio 2005, MSVC++ 8.0
+	#define POCO_MSVS_VERSION 2005
+	#define POCO_MSVC_VERSION 80
+#elif (_MSC_VER >= 1500) && (_MSC_VER < 1600) // Visual Studio 2008, MSVC++ 9.0
+	#define POCO_MSVS_VERSION 2008
+	#define POCO_MSVC_VERSION 90
+#elif (_MSC_VER >= 1600) && (_MSC_VER < 1700) // Visual Studio 2010, MSVC++ 10.0
+	#define POCO_MSVS_VERSION 2010
+	#define POCO_MSVC_VERSION 100
+#elif (_MSC_VER >= 1700) && (_MSC_VER < 1800) // Visual Studio 2012, MSVC++ 11.0
+	#define POCO_MSVS_VERSION 2012
+	#define POCO_MSVC_VERSION 110
+#elif (_MSC_VER >= 1800) && (_MSC_VER < 1900) // Visual Studio 2013, MSVC++ 12.0
+	#define POCO_MSVS_VERSION 2013
+	#define POCO_MSVC_VERSION 120
+#elif (_MSC_VER >= 1900) && (_MSC_VER < 1910) // Visual Studio 2015, MSVC++ 14.0
+	#define POCO_MSVS_VERSION 2015
+	#define POCO_MSVC_VERSION 140
+#elif (_MSC_VER >= 1910) && (_MSC_VER < 2000) // Visual Studio 2017, MSVC++ 14.1
+	#define POCO_MSVS_VERSION 2017
+	#define POCO_MSVC_VERSION 141
+#endif
+
+
+// Unicode Support
+#if defined(UNICODE) && !defined(POCO_WIN32_UTF8)
+	#define POCO_WIN32_UTF8
+#endif
+
+
+#if !defined(POCO_WIN32_UTF8)
+	#pragma message("Compiling POCO on Windows without #define POCO_WIN32_UTF8 is deprecated.")
+#endif
+
+
+// Turn off some annoying warnings
+#if defined(_MSC_VER)
+	#pragma warning(disable:4018)	// signed/unsigned comparison
+	#pragma warning(disable:4250)	// VC++ 11.0: inheriting from std stream classes produces C4250 warning;
+									// see <http://connect.microsoft.com/VisualStudio/feedback/details/733720/inheriting-from-std-fstream-produces-c4250-warning>
+	#pragma warning(disable:4251)	// ... needs to have dll-interface warning
+	#pragma warning(disable:4275)	// non dll-interface class 'std::exception' used as base for dll-interface class 'Poco::Exception'
+	#pragma warning(disable:4344)	// behavior change: use of explicit template arguments results in call to '...' but '...' is a better match
+	#pragma warning(disable:4351)	// new behavior: elements of array '...' will be default initialized
+	#pragma warning(disable:4355)	// 'this' : used in base member initializer list
+	#pragma warning(disable:4675)	// resolved overload was found by argument-dependent lookup
+	#pragma warning(disable:4996)	// VC++ 8.0 deprecation warnings
+#endif
+
+
+// Enable C++11 support for VS 2010 and newer
+#if defined(_MSC_VER) && (_MSC_VER >= 1700) && !defined(POCO_ENABLE_CPP11)
+	#define POCO_ENABLE_CPP11
+#endif
+
+
+#if defined(__INTEL_COMPILER)
+	#pragma warning(disable:1738) // base class dllexport/dllimport specification differs from that of the derived class
+	#pragma warning(disable:1478) // function ... was declared "deprecated"
+	#pragma warning(disable:1744) // field of class type without a DLL interface used in a class with a DLL interface
+#endif
+
+
+#endif // Foundation_Platform_WIN32_INCLUDED
diff --git a/Poco/Poco.h b/Poco/Poco.h
new file mode 100644
index 0000000..cc5dd0e
--- /dev/null
+++ b/Poco/Poco.h
@@ -0,0 +1,24 @@
+//
+// Poco.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Foundation
+//
+// Basic definitions for the POCO libraries.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Poco_INCLUDED
+#define Foundation_Poco_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#endif // Foundation_Poco_INCLUDED
diff --git a/Poco/PriorityDelegate.h b/Poco/PriorityDelegate.h
new file mode 100644
index 0000000..7c776b9
--- /dev/null
+++ b/Poco/PriorityDelegate.h
@@ -0,0 +1,464 @@
+//
+// PriorityDelegate.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  PriorityDelegate
+//
+// Implementation of the PriorityDelegate template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PriorityDelegate_INCLUDED
+#define Foundation_PriorityDelegate_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AbstractPriorityDelegate.h"
+#include "Poco/PriorityExpire.h"
+#include "Poco/FunctionPriorityDelegate.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class TObj, class TArgs, bool useSender = true> 
+class PriorityDelegate: public AbstractPriorityDelegate<TArgs>
+{
+public:
+	typedef void (TObj::*NotifyMethod)(const void*, TArgs&);
+
+	PriorityDelegate(TObj* obj, NotifyMethod method, int prio):
+		AbstractPriorityDelegate<TArgs>(prio),
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+	
+	PriorityDelegate(const PriorityDelegate& delegate):
+		AbstractPriorityDelegate<TArgs>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+	
+	PriorityDelegate& operator = (const PriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_pTarget        = delegate._pTarget;
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+			this->_priority       = delegate._priority;
+		}
+		return *this;
+	}
+
+	~PriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)(sender, arguments);
+			return true; 
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const PriorityDelegate* pOtherDelegate = dynamic_cast<const PriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new PriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+	
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex _mutex;
+
+private:
+	PriorityDelegate();
+};
+
+
+template <class TObj, class TArgs> 
+class PriorityDelegate<TObj, TArgs, false>: public AbstractPriorityDelegate<TArgs>
+{
+public:
+	typedef void (TObj::*NotifyMethod)(TArgs&);
+
+	PriorityDelegate(TObj* obj, NotifyMethod method, int prio):
+		AbstractPriorityDelegate<TArgs>(prio),
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+	
+	PriorityDelegate(const PriorityDelegate& delegate):
+		AbstractPriorityDelegate<TArgs>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+	
+	PriorityDelegate& operator = (const PriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_pTarget        = delegate._pTarget;
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+			this->_priority       = delegate._priority;
+		}
+		return *this;
+	}
+
+	~PriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)(arguments);
+			return true;
+		}
+		return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		const PriorityDelegate* pOtherDelegate = dynamic_cast<const PriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<TArgs>* clone() const
+	{
+		return new PriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex _mutex;
+
+private:
+	PriorityDelegate();
+};
+
+
+template <class TObj>
+class PriorityDelegate<TObj, void, true>: public AbstractPriorityDelegate<void>
+{
+public:
+	typedef void (TObj::*NotifyMethod)(const void*);
+
+	PriorityDelegate(TObj* obj, NotifyMethod method, int prio):
+		AbstractPriorityDelegate<void>(prio),
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+
+	PriorityDelegate(const PriorityDelegate& delegate):
+		AbstractPriorityDelegate<void>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+
+	PriorityDelegate& operator = (const PriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_pTarget        = delegate._pTarget;
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+			this->_priority       = delegate._priority;
+		}
+		return *this;
+	}
+
+	~PriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)(sender);
+			return true;
+		}
+		else return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const PriorityDelegate* pOtherDelegate = dynamic_cast<const PriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new PriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex _mutex;
+
+private:
+	PriorityDelegate();
+};
+
+
+template <class TObj>
+class PriorityDelegate<TObj, void, false>: public AbstractPriorityDelegate<void>
+{
+public:
+	typedef void (TObj::*NotifyMethod)();
+
+	PriorityDelegate(TObj* obj, NotifyMethod method, int prio):
+		AbstractPriorityDelegate<void>(prio),
+		_receiverObject(obj),
+		_receiverMethod(method)
+	{
+	}
+
+	PriorityDelegate(const PriorityDelegate& delegate):
+		AbstractPriorityDelegate<void>(delegate),
+		_receiverObject(delegate._receiverObject),
+		_receiverMethod(delegate._receiverMethod)
+	{
+	}
+
+	PriorityDelegate& operator = (const PriorityDelegate& delegate)
+	{
+		if (&delegate != this)
+		{
+			this->_pTarget        = delegate._pTarget;
+			this->_receiverObject = delegate._receiverObject;
+			this->_receiverMethod = delegate._receiverMethod;
+			this->_priority       = delegate._priority;
+		}
+		return *this;
+	}
+
+	~PriorityDelegate()
+	{
+	}
+
+	bool notify(const void* sender)
+	{
+		Mutex::ScopedLock lock(_mutex);
+		if (_receiverObject)
+		{
+			(_receiverObject->*_receiverMethod)();
+			return true;
+		}
+		return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		const PriorityDelegate* pOtherDelegate = dynamic_cast<const PriorityDelegate*>(other.unwrap());
+		return pOtherDelegate && this->priority() == pOtherDelegate->priority() && _receiverObject == pOtherDelegate->_receiverObject && _receiverMethod == pOtherDelegate->_receiverMethod;
+	}
+
+	AbstractDelegate<void>* clone() const
+	{
+		return new PriorityDelegate(*this);
+	}
+
+	void disable()
+	{
+		Mutex::ScopedLock lock(_mutex);
+		_receiverObject = 0;
+	}
+
+protected:
+	TObj*        _receiverObject;
+	NotifyMethod _receiverMethod;
+	Mutex _mutex;
+
+private:
+	PriorityDelegate();
+};
+
+
+template <class TObj, class TArgs>
+static PriorityDelegate<TObj, TArgs, true> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), int prio)
+{
+	return PriorityDelegate<TObj, TArgs, true>(pObj, NotifyMethod, prio);
+}
+
+
+template <class TObj, class TArgs>
+static PriorityDelegate<TObj, TArgs, false> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&), int prio)
+{
+	return PriorityDelegate<TObj, TArgs, false>(pObj, NotifyMethod, prio);
+}
+
+
+template <class TObj, class TArgs>
+static PriorityExpire<TArgs> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*, TArgs&), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<TArgs>(PriorityDelegate<TObj, TArgs, true>(pObj, NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TObj, class TArgs>
+static PriorityExpire<TArgs> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(TArgs&), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<TArgs>(PriorityDelegate<TObj, TArgs, false>(pObj, NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TArgs>
+static PriorityExpire<TArgs> priorityDelegate(void (*NotifyMethod)(const void*, TArgs&), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<TArgs>(FunctionPriorityDelegate<TArgs, true, true>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TArgs>
+static PriorityExpire<TArgs> priorityDelegate(void (*NotifyMethod)(void*, TArgs&), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<TArgs>(FunctionPriorityDelegate<TArgs, true, false>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TArgs>
+static PriorityExpire<TArgs> priorityDelegate(void (*NotifyMethod)(TArgs&), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<TArgs>(FunctionPriorityDelegate<TArgs, false>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TArgs>
+static FunctionPriorityDelegate<TArgs, true, true> priorityDelegate(void (*NotifyMethod)(const void*, TArgs&), int prio)
+{
+	return FunctionPriorityDelegate<TArgs, true, true>(NotifyMethod, prio);
+}
+
+
+template <class TArgs>
+static FunctionPriorityDelegate<TArgs, true, false> priorityDelegate(void (*NotifyMethod)(void*, TArgs&), int prio)
+{
+	return FunctionPriorityDelegate<TArgs, true, false>(NotifyMethod, prio);
+}
+
+
+template <class TArgs>
+static FunctionPriorityDelegate<TArgs, false> priorityDelegate(void (*NotifyMethod)(TArgs&), int prio)
+{
+	return FunctionPriorityDelegate<TArgs, false>(NotifyMethod, prio);
+}
+
+
+template <class TObj>
+static PriorityDelegate<TObj, void, true> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), int prio)
+{
+	return PriorityDelegate<TObj, void, true>(pObj, NotifyMethod, prio);
+}
+
+
+template <class TObj>
+static PriorityDelegate<TObj, void, false> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(), int prio)
+{
+	return PriorityDelegate<TObj, void, false>(pObj, NotifyMethod, prio);
+}
+
+
+template <class TObj>
+static PriorityExpire<void> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(const void*), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<void>(PriorityDelegate<TObj, void, true>(pObj, NotifyMethod, prio), expireMilliSec);
+}
+
+
+template <class TObj>
+static PriorityExpire<void> priorityDelegate(TObj* pObj, void (TObj::*NotifyMethod)(), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<void>(PriorityDelegate<TObj, void, false>(pObj, NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline PriorityExpire<void> priorityDelegate(void (*NotifyMethod)(const void*), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<void>(FunctionPriorityDelegate<void, true, true>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline PriorityExpire<void> priorityDelegate(void (*NotifyMethod)(void*), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<void>(FunctionPriorityDelegate<void, true, false>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline PriorityExpire<void> priorityDelegate(void (*NotifyMethod)(), int prio, Timestamp::TimeDiff expireMilliSec)
+{
+	return PriorityExpire<void>(FunctionPriorityDelegate<void, false>(NotifyMethod, prio), expireMilliSec);
+}
+
+
+inline FunctionPriorityDelegate<void, true, true> priorityDelegate(void (*NotifyMethod)(const void*), int prio)
+{
+	return FunctionPriorityDelegate<void, true, true>(NotifyMethod, prio);
+}
+
+
+inline FunctionPriorityDelegate<void, true, false> priorityDelegate(void (*NotifyMethod)(void*), int prio)
+{
+	return FunctionPriorityDelegate<void, true, false>(NotifyMethod, prio);
+}
+
+
+inline FunctionPriorityDelegate<void, false> priorityDelegate(void (*NotifyMethod)(), int prio)
+{
+	return FunctionPriorityDelegate<void, false>(NotifyMethod, prio);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PriorityDelegate_INCLUDED
diff --git a/Poco/PriorityEvent.h b/Poco/PriorityEvent.h
new file mode 100644
index 0000000..48b9f60
--- /dev/null
+++ b/Poco/PriorityEvent.h
@@ -0,0 +1,61 @@
+//
+// PriorityEvent.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  PriorityEvent
+//
+// Implementation of the PriorityEvent template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PriorityEvent_INCLUDED
+#define Foundation_PriorityEvent_INCLUDED
+
+
+#include "Poco/AbstractEvent.h"
+#include "Poco/PriorityStrategy.h"
+#include "Poco/AbstractPriorityDelegate.h"
+
+
+namespace Poco {
+
+
+template <class TArgs, class TMutex = FastMutex> 
+class PriorityEvent: public AbstractEvent < 
+	TArgs,
+	PriorityStrategy<TArgs, AbstractPriorityDelegate<TArgs> >,
+	AbstractPriorityDelegate<TArgs>,
+	TMutex
+>
+	/// A PriorityEvent uses internally a PriorityStrategy which 
+	/// invokes delegates in order of priority (lower priorities first).
+	/// PriorityEvent's can only be used together with PriorityDelegate's.
+	/// PriorityDelegate's are sorted according to the priority value, when
+	/// two delegates have the same priority, they are invoked in
+	/// an arbitrary manner.
+{
+public:
+	PriorityEvent()
+	{
+	}
+
+	~PriorityEvent()
+	{
+	}
+
+private:
+	PriorityEvent(const PriorityEvent&);
+	PriorityEvent& operator = (const PriorityEvent&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PriorityEvent_INCLUDED
diff --git a/Poco/PriorityExpire.h b/Poco/PriorityExpire.h
new file mode 100644
index 0000000..9491445
--- /dev/null
+++ b/Poco/PriorityExpire.h
@@ -0,0 +1,195 @@
+//
+// PriorityExpire.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  PriorityExpire
+//
+// Implementation of the PriorityExpire template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PriorityExpire_INCLUDED
+#define Foundation_PriorityExpire_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+#include "Poco/AbstractPriorityDelegate.h"
+
+
+namespace Poco {
+
+
+template <class TArgs>
+class PriorityExpire: public AbstractPriorityDelegate<TArgs>
+	/// Decorator for AbstractPriorityDelegate adding automatic 
+	/// expiring of registrations to AbstractPriorityDelegate.
+{
+public:
+	PriorityExpire(const AbstractPriorityDelegate<TArgs>& p, Timestamp::TimeDiff expireMilliSec):
+		AbstractPriorityDelegate<TArgs>(p),
+		_pDelegate(static_cast<AbstractPriorityDelegate<TArgs>*>(p.clone())), 
+		_expire(expireMilliSec*1000)
+	{
+	}
+	
+	PriorityExpire(const PriorityExpire& expire):
+		AbstractPriorityDelegate<TArgs>(expire),
+		_pDelegate(static_cast<AbstractPriorityDelegate<TArgs>*>(expire._pDelegate->clone())),
+		_expire(expire._expire),
+		_creationTime(expire._creationTime)
+	{
+	}
+
+	~PriorityExpire()
+	{
+		delete _pDelegate;
+	}
+	
+	PriorityExpire& operator = (const PriorityExpire& expire)
+	{
+		if (&expire != this)
+		{
+			delete this->_pDelegate;
+			this->_pTarget      = expire._pTarget;
+			this->_pDelegate    = expire._pDelegate->clone();
+			this->_expire       = expire._expire;
+			this->_creationTime = expire._creationTime;
+		}
+		return *this; 
+	}
+
+	bool notify(const void* sender, TArgs& arguments)
+	{
+		if (!expired())
+			return this->_pDelegate->notify(sender, arguments);
+		else
+			return false;
+	}
+
+	bool equals(const AbstractDelegate<TArgs>& other) const
+	{
+		return other.equals(*_pDelegate);
+	}
+
+	AbstractPriorityDelegate<TArgs>* clone() const
+	{
+		return new PriorityExpire(*this);
+	}
+
+	void disable()
+	{
+		_pDelegate->disable();
+	}
+
+	const AbstractPriorityDelegate<TArgs>* unwrap() const
+	{
+		return this->_pDelegate;
+	}
+
+protected:
+	bool expired() const
+	{
+		return _creationTime.isElapsed(_expire);
+	}
+
+	AbstractPriorityDelegate<TArgs>* _pDelegate;
+	Timestamp::TimeDiff _expire;
+	Timestamp _creationTime;
+
+private:
+	PriorityExpire();
+};
+
+
+template <>
+class PriorityExpire<void>: public AbstractPriorityDelegate<void>
+	/// Decorator for AbstractPriorityDelegate adding automatic
+	/// expiring of registrations to AbstractPriorityDelegate.
+{
+public:
+	PriorityExpire(const AbstractPriorityDelegate<void>& p, Timestamp::TimeDiff expireMilliSec):
+		AbstractPriorityDelegate<void>(p),
+		_pDelegate(static_cast<AbstractPriorityDelegate<void>*>(p.clone())),
+		_expire(expireMilliSec*1000)
+	{
+	}
+
+	PriorityExpire(const PriorityExpire& expire):
+		AbstractPriorityDelegate<void>(expire),
+		_pDelegate(static_cast<AbstractPriorityDelegate<void>*>(expire._pDelegate->clone())),
+		_expire(expire._expire),
+		_creationTime(expire._creationTime)
+	{
+	}
+
+	~PriorityExpire()
+	{
+		delete _pDelegate;
+	}
+
+	PriorityExpire& operator = (const PriorityExpire& expire)
+	{
+		if (&expire != this)
+		{
+			delete this->_pDelegate;
+			this->_pDelegate    = static_cast<AbstractPriorityDelegate<void>*>(expire._pDelegate->clone());
+			this->_expire       = expire._expire;
+			this->_creationTime = expire._creationTime;
+		}
+		return *this;
+	}
+
+	bool notify(const void* sender)
+	{
+		if (!expired())
+			return this->_pDelegate->notify(sender);
+		else
+			return false;
+	}
+
+	bool equals(const AbstractDelegate<void>& other) const
+	{
+		return other.equals(*_pDelegate);
+	}
+
+	AbstractPriorityDelegate<void>* clone() const
+	{
+		return new PriorityExpire(*this);
+	}
+
+	void disable()
+	{
+		_pDelegate->disable();
+	}
+
+	const AbstractPriorityDelegate<void>* unwrap() const
+	{
+		return this->_pDelegate;
+	}
+
+protected:
+	bool expired() const
+	{
+		return _creationTime.isElapsed(_expire);
+	}
+
+	AbstractPriorityDelegate<void>* _pDelegate;
+	Timestamp::TimeDiff _expire;
+	Timestamp _creationTime;
+
+private:
+	PriorityExpire();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PriorityExpire_INCLUDED
diff --git a/Poco/PriorityNotificationQueue.h b/Poco/PriorityNotificationQueue.h
new file mode 100644
index 0000000..e5269ab
--- /dev/null
+++ b/Poco/PriorityNotificationQueue.h
@@ -0,0 +1,158 @@
+//
+// PriorityNotificationQueue.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  PriorityNotificationQueue
+//
+// Definition of the PriorityNotificationQueue class.
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PriorityNotificationQueue_INCLUDED
+#define Foundation_PriorityNotificationQueue_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Notification.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+#include <map>
+#include <deque>
+
+
+namespace Poco {
+
+
+class NotificationCenter;
+
+
+class Foundation_API PriorityNotificationQueue
+	/// A PriorityNotificationQueue object provides a way to implement asynchronous
+	/// notifications. This is especially useful for sending notifications
+	/// from one thread to another, for example from a background thread to 
+	/// the main (user interface) thread. 
+	///
+	/// The PriorityNotificationQueue is quite similar to the NotificationQueue class.
+	/// The only difference to NotificationQueue is that each Notification is tagged
+	/// with a priority value. When inserting a Notification into the queue, the
+	/// Notification is inserted according to the given priority value, with 
+	/// lower priority values being inserted before higher priority
+	/// values. Therefore, the lower the numerical priority value, the higher
+	/// the actual notification priority. 
+	///
+	/// Notifications are dequeued in order of their priority.
+	/// 
+	/// The PriorityNotificationQueue can also be used to distribute work from
+	/// a controlling thread to one or more worker threads. Each worker thread
+	/// repeatedly calls waitDequeueNotification() and processes the
+	/// returned notification. Special care must be taken when shutting
+	/// down a queue with worker threads waiting for notifications.
+	/// The recommended sequence to shut down and destroy the queue is to
+	///   1. set a termination flag for every worker thread
+	///   2. call the wakeUpAll() method
+	///   3. join each worker thread
+	///   4. destroy the notification queue.
+{
+public:
+	PriorityNotificationQueue();
+		/// Creates the PriorityNotificationQueue.
+
+	~PriorityNotificationQueue();
+		/// Destroys the PriorityNotificationQueue.
+
+	void enqueueNotification(Notification::Ptr pNotification, int priority);
+		/// Enqueues the given notification by adding it to
+		/// the queue according to the given priority.
+		/// Lower priority values are inserted before higher priority values.
+		/// The queue takes ownership of the notification, thus
+		/// a call like
+		///     notificationQueue.enqueueNotification(new MyNotification, 1);
+		/// does not result in a memory leak.
+		
+	Notification* dequeueNotification();
+		/// Dequeues the next pending notification.
+		/// Returns 0 (null) if no notification is available.
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	Notification* waitDequeueNotification();
+		/// Dequeues the next pending notification.
+		/// If no notification is available, waits for a notification
+		/// to be enqueued. 
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		/// This method returns 0 (null) if wakeUpAll()
+		/// has been called by another thread.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	Notification* waitDequeueNotification(long milliseconds);
+		/// Dequeues the next pending notification.
+		/// If no notification is available, waits for a notification
+		/// to be enqueued up to the specified time.
+		/// Returns 0 (null) if no notification is available.
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	void dispatch(NotificationCenter& notificationCenter);
+		/// Dispatches all queued notifications to the given
+		/// notification center.
+
+	void wakeUpAll();
+		/// Wakes up all threads that wait for a notification.
+	
+	bool empty() const;
+		/// Returns true iff the queue is empty.
+		
+	int size() const;
+		/// Returns the number of notifications in the queue.
+
+	void clear();
+		/// Removes all notifications from the queue.
+		
+	bool hasIdleThreads() const;	
+		/// Returns true if the queue has at least one thread waiting 
+		/// for a notification.
+		
+	static PriorityNotificationQueue& defaultQueue();
+		/// Returns a reference to the default
+		/// PriorityNotificationQueue.
+
+protected:
+	Notification::Ptr dequeueOne();
+	
+private:
+	typedef std::multimap<int, Notification::Ptr> NfQueue;
+	struct WaitInfo
+	{
+		Notification::Ptr pNf;
+		Event nfAvailable;
+	};
+	typedef std::deque<WaitInfo*> WaitQueue;
+
+	NfQueue           _nfQueue;
+	WaitQueue         _waitQueue;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PriorityNotificationQueue_INCLUDED
diff --git a/Poco/PriorityStrategy.h b/Poco/PriorityStrategy.h
new file mode 100644
index 0000000..65d67a4
--- /dev/null
+++ b/Poco/PriorityStrategy.h
@@ -0,0 +1,230 @@
+//
+// PriorityStrategy.h
+//
+// Library: Foundation
+// Package: Events
+// Module:  PrioritytStrategy
+//
+// Implementation of the DefaultStrategy template.
+//
+// Copyright (c) 2006-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PriorityStrategy_INCLUDED
+#define Foundation_PriorityStrategy_INCLUDED
+
+
+#include "Poco/NotificationStrategy.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+template <class TArgs, class TDelegate> 
+class PriorityStrategy: public NotificationStrategy<TArgs, TDelegate>
+	/// NotificationStrategy for PriorityEvent.
+	///
+	/// Delegates are kept in a std::vector<>, ordered
+	/// by their priority.
+{
+public:
+	typedef TDelegate*                   DelegateHandle;
+	typedef SharedPtr<TDelegate>         DelegatePtr;
+	typedef std::vector<DelegatePtr>     Delegates;
+	typedef typename Delegates::iterator Iterator;
+
+public:
+	PriorityStrategy()
+	{
+	}
+
+	PriorityStrategy(const PriorityStrategy& s):
+		_delegates(s._delegates)
+	{
+	}
+
+	~PriorityStrategy()
+	{
+	}
+
+	void notify(const void* sender, TArgs& arguments)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->notify(sender, arguments);
+		}
+	}
+
+	DelegateHandle add(const TDelegate& delegate)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if ((*it)->priority() > delegate.priority())
+			{
+				DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
+				_delegates.insert(it, pDelegate);
+				return pDelegate.get();
+			}
+		}
+		DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
+		_delegates.push_back(pDelegate);
+		return pDelegate.get();
+	}
+
+	void remove(const TDelegate& delegate)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (delegate.equals(**it))
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	void remove(DelegateHandle delegateHandle)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (*it == delegateHandle)
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	PriorityStrategy& operator = (const PriorityStrategy& s)
+	{
+		if (this != &s)
+		{
+			_delegates = s._delegates;
+		}
+		return *this;
+	}
+
+	void clear()
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->disable();
+		}
+		_delegates.clear();
+	}
+
+	bool empty() const
+	{
+		return _delegates.empty();
+	}
+
+protected:
+	Delegates _delegates;
+};
+
+
+template <class TDelegate>
+class PriorityStrategy<void, TDelegate>
+	/// NotificationStrategy for PriorityEvent.
+	///
+	/// Delegates are kept in a std::vector<>, ordered
+	/// by their priority.
+{
+public:
+	typedef TDelegate*                   DelegateHandle;
+	typedef SharedPtr<TDelegate>         DelegatePtr;
+	typedef std::vector<DelegatePtr>     Delegates;
+	typedef typename Delegates::iterator Iterator;
+
+public:
+
+	void notify(const void* sender)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->notify(sender);
+		}
+	}
+
+	DelegateHandle add(const TDelegate& delegate)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if ((*it)->priority() > delegate.priority())
+			{
+				DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
+				_delegates.insert(it, pDelegate);
+				return pDelegate.get();
+			}
+		}
+		DelegatePtr pDelegate(static_cast<TDelegate*>(delegate.clone()));
+		_delegates.push_back(pDelegate);
+		return pDelegate.get();
+	}
+
+	void remove(const TDelegate& delegate)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (delegate.equals(**it))
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	void remove(DelegateHandle delegateHandle)
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			if (*it == delegateHandle)
+			{
+				(*it)->disable();
+				_delegates.erase(it);
+				return;
+			}
+		}
+	}
+
+	PriorityStrategy& operator = (const PriorityStrategy& s)
+	{
+		if (this != &s)
+		{
+			_delegates = s._delegates;
+		}
+		return *this;
+	}
+
+	void clear()
+	{
+		for (Iterator it = _delegates.begin(); it != _delegates.end(); ++it)
+		{
+			(*it)->disable();
+		}
+		_delegates.clear();
+	}
+
+	bool empty() const
+	{
+		return _delegates.empty();
+	}
+
+protected:
+	Delegates _delegates;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PriorityStrategy_INCLUDED
diff --git a/Poco/Process.h b/Poco/Process.h
new file mode 100644
index 0000000..f9fefc5
--- /dev/null
+++ b/Poco/Process.h
@@ -0,0 +1,266 @@
+//
+// Process.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Process
+//
+// Definition of the Process class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Process_INCLUDED
+#define Foundation_Process_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+#if defined(_WIN32_WCE)
+#include "Process_WINCE.h"
+#else
+#include "Poco/Process_WIN32U.h"
+#endif
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/Process_WIN32.h"
+#elif defined(POCO_VXWORKS)
+#include "Poco/Process_VX.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/Process_UNIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Pipe;
+
+
+class Foundation_API ProcessHandle
+	/// A handle for a process created with Process::launch().
+	///
+	/// This handle can be used to determine the process ID of
+	/// the newly created process and it can be used to wait for
+	/// the completion of a process.
+{
+public:
+	typedef ProcessImpl::PIDImpl PID;
+
+	ProcessHandle(const ProcessHandle& handle);
+		/// Creates a ProcessHandle by copying another one.
+
+	~ProcessHandle();
+		/// Destroys the ProcessHandle.
+
+	ProcessHandle& operator = (const ProcessHandle& handle);
+		/// Assigns another handle.
+
+	PID id() const;
+		/// Returns the process ID.
+
+	int wait() const;
+		/// Waits for the process to terminate
+		/// and returns the exit code of the process.
+
+protected:
+	ProcessHandle(ProcessHandleImpl* pImpl);
+
+private:
+	ProcessHandle();
+
+	ProcessHandleImpl* _pImpl;
+
+	friend class Process;
+};
+
+
+class Foundation_API Process: public ProcessImpl
+	/// This class provides methods for working with processes.
+{
+public:
+	typedef PIDImpl  PID;
+	typedef ArgsImpl Args;
+	typedef EnvImpl  Env;
+
+	static PID id();
+		/// Returns the process ID of the current process.
+
+	static void times(long& userTime, long& kernelTime);
+		/// Returns the number of seconds spent by the
+		/// current process in user and kernel mode.
+
+	static ProcessHandle launch(const std::string& command, const Args& args);
+		/// Creates a new process for the given command and returns
+		/// a ProcessHandle of the new process. The given arguments are
+		/// passed to the command on the command line.
+
+	static ProcessHandle launch(
+		const std::string& command,
+		const Args& args,
+		const std::string& initialDirectory);
+		/// Creates a new process for the given command and returns
+		/// a ProcessHandle of the new process. The given arguments are
+		/// passed to the command on the command line.
+		/// The process starts executing in the specified initial directory.
+
+	static ProcessHandle launch(
+		const std::string& command,
+		const Args& args,
+		Pipe* inPipe,
+		Pipe* outPipe,
+		Pipe* errPipe);
+		/// Creates a new process for the given command and returns
+		/// a ProcessHandle of the new process. The given arguments are
+		/// passed to the command on the command line.
+		///
+		/// If inPipe, outPipe or errPipe is non-null, the corresponding
+		/// standard input, standard output or standard error stream
+		/// of the launched process is redirected to the Pipe.
+		/// PipeInputStream or PipeOutputStream can be used to
+		/// send receive data from, or send data to the process.
+		///
+		/// Note: the same Pipe can be used for both outPipe and errPipe.
+		///
+		/// After a Pipe has been passed as inPipe, only write operations
+		/// are valid. After a Pipe has been passed as outPipe or errPipe,
+		/// only read operations are valid.
+		///
+		/// It is forbidden to pass the same pipe as inPipe and outPipe or errPipe.
+		///
+		/// Usage example:
+		///     Pipe outPipe;
+		///     Process::Args args;
+		///     ProcessHandle ph(launch("/bin/ps", args, 0, &outPipe, 0));
+		///     PipeInputStream istr(outPipe);
+		///     ... // read output of ps from istr
+		///     int rc = ph.wait();
+
+	static ProcessHandle launch(
+		const std::string& command,
+		const Args& args,
+		const std::string& initialDirectory,
+		Pipe* inPipe,
+		Pipe* outPipe,
+		Pipe* errPipe);
+		/// Creates a new process for the given command and returns
+		/// a ProcessHandle of the new process. The given arguments are
+		/// passed to the command on the command line.
+		/// The process starts executing in the specified initial directory.
+		///
+		/// If inPipe, outPipe or errPipe is non-null, the corresponding
+		/// standard input, standard output or standard error stream
+		/// of the launched process is redirected to the Pipe.
+		/// PipeInputStream or PipeOutputStream can be used to
+		/// send receive data from, or send data to the process.
+		///
+		/// Note: the same Pipe can be used for both outPipe and errPipe.
+		///
+		/// After a Pipe has been passed as inPipe, only write operations
+		/// are valid. After a Pipe has been passed as outPipe or errPipe,
+		/// only read operations are valid.
+		///
+		/// It is forbidden to pass the same pipe as inPipe and outPipe or errPipe.
+		///
+		/// Usage example:
+		///     Pipe outPipe;
+		///     Process::Args args;
+		///     ProcessHandle ph(launch("/bin/ps", args, 0, &outPipe, 0));
+		///     PipeInputStream istr(outPipe);
+		///     ... // read output of ps from istr
+		///     int rc = ph.wait();
+
+	static ProcessHandle launch(
+		const std::string& command,
+		const Args& args,
+		Pipe* inPipe,
+		Pipe* outPipe,
+		Pipe* errPipe,
+		const Env& env);
+		/// Creates a new process for the given command and returns
+		/// a ProcessHandle of the new process. The given arguments are
+		/// passed to the command on the command line.
+		///
+		/// If inPipe, outPipe or errPipe is non-null, the corresponding
+		/// standard input, standard output or standard error stream
+		/// of the launched process is redirected to the Pipe.
+		///
+		/// The launched process is given the specified environment variables.
+
+	static ProcessHandle launch(
+		const std::string& command,
+		const Args& args,
+		const std::string& initialDirectory,
+		Pipe* inPipe,
+		Pipe* outPipe,
+		Pipe* errPipe,
+		const Env& env);
+		/// Creates a new process for the given command and returns
+		/// a ProcessHandle of the new process. The given arguments are
+		/// passed to the command on the command line.
+		/// The process starts executing in the specified initial directory.
+		/// If inPipe, outPipe or errPipe is non-null, the corresponding
+		/// standard input, standard output or standard error stream
+		/// of the launched process is redirected to the Pipe.
+		/// The launched process is given the specified environment variables.
+
+	static int wait(const ProcessHandle& handle);
+		/// Waits for the process specified by handle to terminate
+		/// and returns the exit code of the process.
+
+	static bool isRunning(const ProcessHandle& handle);
+		/// check if the process specified by handle is running or not
+		///
+		/// This is preferable on Windows where process IDs
+		/// may be reused.
+
+	static bool isRunning(PID pid);
+		/// Check if the process specified by given pid is running or not.
+
+	static void kill(ProcessHandle& handle);
+		/// Kills the process specified by handle.
+		///
+		/// This is preferable on Windows where process IDs
+		/// may be reused.
+
+	static void kill(PID pid);
+		/// Kills the process with the given pid.
+
+	static void requestTermination(PID pid);
+		/// Requests termination of the process with the give PID.
+		///
+		/// On Unix platforms, this will send a SIGINT to the
+		/// process and thus work with arbitrary processes.
+		///
+		/// On other platforms, a global event flag
+		/// will be set. Setting the flag will cause
+		/// Util::ServerApplication::waitForTerminationRequest() to
+		/// return. Therefore this will only work with applications
+		/// based on Util::ServerApplication.
+};
+
+
+//
+// inlines
+//
+inline Process::PID Process::id()
+{
+	return ProcessImpl::idImpl();
+}
+
+
+inline void Process::times(long& userTime, long& kernelTime)
+{
+	ProcessImpl::timesImpl(userTime, kernelTime);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Process_INCLUDED
diff --git a/Poco/Process_UNIX.h b/Poco/Process_UNIX.h
new file mode 100644
index 0000000..b33dd08
--- /dev/null
+++ b/Poco/Process_UNIX.h
@@ -0,0 +1,86 @@
+//
+// Process_UNIX.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Process
+//
+// Definition of the ProcessImpl class for Unix.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Process_UNIX_INCLUDED
+#define Foundation_Process_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+#include <unistd.h>
+#include <vector>
+#include <map>
+
+
+namespace Poco {
+
+
+class Pipe;
+
+
+class Foundation_API ProcessHandleImpl: public RefCountedObject
+{
+public:
+	ProcessHandleImpl(pid_t pid);
+	~ProcessHandleImpl();
+	
+	pid_t id() const;
+	int wait() const;
+	
+private:
+	pid_t _pid;
+};
+
+
+class Foundation_API ProcessImpl
+{
+public:
+	typedef pid_t PIDImpl;
+	typedef std::vector<std::string> ArgsImpl;
+	typedef std::map<std::string, std::string> EnvImpl;
+	
+	static PIDImpl idImpl();
+	static void timesImpl(long& userTime, long& kernelTime);
+	static ProcessHandleImpl* launchImpl(
+		const std::string& command, 
+		const ArgsImpl& args, 
+		const std::string& initialDirectory,
+		Pipe* inPipe, 
+		Pipe* outPipe, 
+		Pipe* errPipe,
+		const EnvImpl& env);
+	static void killImpl(ProcessHandleImpl& handle);
+	static void killImpl(PIDImpl pid);
+	static bool isRunningImpl(const ProcessHandleImpl& handle);
+	static bool isRunningImpl(PIDImpl pid);
+	static void requestTerminationImpl(PIDImpl pid);
+
+private:
+	static ProcessHandleImpl* launchByForkExecImpl(
+		const std::string& command, 
+		const ArgsImpl& args, 
+		const std::string& initialDirectory,
+		Pipe* inPipe, 
+		Pipe* outPipe, 
+		Pipe* errPipe,
+		const EnvImpl& env);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Process_UNIX_INCLUDED
diff --git a/Poco/Process_VX.h b/Poco/Process_VX.h
new file mode 100644
index 0000000..0ac9bce
--- /dev/null
+++ b/Poco/Process_VX.h
@@ -0,0 +1,78 @@
+//
+// Process_VX.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Process
+//
+// Definition of the ProcessImpl class for VxWorks.
+//
+// Copyright (c) 2004-20011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Process_VX_INCLUDED
+#define Foundation_Process_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+#include <vector>
+#include <map>
+
+
+#undef PID
+
+
+namespace Poco {
+
+
+class Pipe;
+
+
+class Foundation_API ProcessHandleImpl: public RefCountedObject
+{
+public:
+	ProcessHandleImpl(int pid);
+	~ProcessHandleImpl();
+	
+	int id() const;
+	int wait() const;
+	
+private:
+	int _pid;
+};
+
+
+class Foundation_API ProcessImpl
+{
+public:
+	typedef int PIDImpl;
+	typedef std::vector<std::string> ArgsImpl;
+	typedef std::map<std::string, std::string> EnvImpl;
+	
+	static PIDImpl idImpl();
+	static void timesImpl(long& userTime, long& kernelTime);
+	static ProcessHandleImpl* launchImpl(
+		const std::string& command, 
+		const ArgsImpl& args, 
+		const std::string& initialDirectory,
+		Pipe* inPipe, 
+		Pipe* outPipe, 
+		Pipe* errPipe,
+		const EnvImpl& env);
+	static void killImpl(ProcessHandleImpl& handle);
+	static void killImpl(PIDImpl pid);
+	static bool isRunningImpl(const ProcessHandleImpl& handle);
+	static bool isRunningImpl(PIDImpl pid);
+	static void requestTerminationImpl(PIDImpl pid);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Process_UNIX_INCLUDED
diff --git a/Poco/Process_WIN32.h b/Poco/Process_WIN32.h
new file mode 100644
index 0000000..afed42c
--- /dev/null
+++ b/Poco/Process_WIN32.h
@@ -0,0 +1,83 @@
+//
+// Process_WIN32.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Process
+//
+// Definition of the ProcessImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Process_WIN32_INCLUDED
+#define Foundation_Process_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+#include <vector>
+#include <map>
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Pipe;
+
+
+class Foundation_API ProcessHandleImpl: public RefCountedObject
+{
+public:
+	ProcessHandleImpl(HANDLE _hProcess, UInt32 pid);
+	~ProcessHandleImpl();
+	
+	UInt32 id() const;
+	HANDLE process() const;
+	int wait() const;
+	void closeHandle();
+
+private:
+	HANDLE _hProcess;
+	UInt32 _pid;
+	
+	ProcessHandleImpl(const ProcessHandleImpl&);
+	ProcessHandleImpl& operator = (const ProcessHandleImpl&);
+};
+
+
+class Foundation_API ProcessImpl
+{
+public:
+	typedef UInt32 PIDImpl;
+	typedef std::vector<std::string> ArgsImpl;
+	typedef std::map<std::string, std::string> EnvImpl;
+	
+	static PIDImpl idImpl();
+	static void timesImpl(long& userTime, long& kernelTime);
+	static ProcessHandleImpl* launchImpl(
+		const std::string& command, 
+		const ArgsImpl& args, 
+		const std::string& initialDirectory,
+		Pipe* inPipe, 
+		Pipe* outPipe, 
+		Pipe* errPipe,
+		const EnvImpl& env);
+	static void killImpl(ProcessHandleImpl& handle);
+	static void killImpl(PIDImpl pid);
+	static bool isRunningImpl(const ProcessHandleImpl& handle);
+	static bool isRunningImpl(PIDImpl pid);
+	static void requestTerminationImpl(PIDImpl pid);
+	static std::string terminationEventName(PIDImpl pid);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Process_WIN32_INCLUDED
diff --git a/Poco/Process_WIN32U.h b/Poco/Process_WIN32U.h
new file mode 100644
index 0000000..bb52013
--- /dev/null
+++ b/Poco/Process_WIN32U.h
@@ -0,0 +1,83 @@
+//
+// Process_WIN32U.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Process
+//
+// Definition of the ProcessImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Process_WIN32U_INCLUDED
+#define Foundation_Process_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+#include <vector>
+#include <map>
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Pipe;
+
+
+class Foundation_API ProcessHandleImpl: public RefCountedObject
+{
+public:
+	ProcessHandleImpl(HANDLE _hProcess, UInt32 pid);
+	~ProcessHandleImpl();
+	
+	UInt32 id() const;
+	HANDLE process() const;
+	int wait() const;
+	void closeHandle();
+
+private:
+	HANDLE _hProcess;
+	UInt32 _pid;
+
+	ProcessHandleImpl(const ProcessHandleImpl&);
+	ProcessHandleImpl& operator = (const ProcessHandleImpl&);
+};
+
+
+class Foundation_API ProcessImpl
+{
+public:
+	typedef UInt32 PIDImpl;
+	typedef std::vector<std::string> ArgsImpl;
+	typedef std::map<std::string, std::string> EnvImpl;
+	
+	static PIDImpl idImpl();
+	static void timesImpl(long& userTime, long& kernelTime);
+	static ProcessHandleImpl* launchImpl(
+		const std::string& command, 
+		const ArgsImpl& args, 
+		const std::string& initialDirectory,
+		Pipe* inPipe, 
+		Pipe* outPipe, 
+		Pipe* errPipe,
+		const EnvImpl& env);
+	static void killImpl(ProcessHandleImpl& handle);
+	static void killImpl(PIDImpl pid);
+	static bool isRunningImpl(const ProcessHandleImpl& handle);
+	static bool isRunningImpl(PIDImpl pid);
+	static void requestTerminationImpl(PIDImpl pid);
+	static std::string terminationEventName(PIDImpl pid);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Process_WIN32U_INCLUDED
diff --git a/Poco/Process_WINCE.h b/Poco/Process_WINCE.h
new file mode 100644
index 0000000..f754c57
--- /dev/null
+++ b/Poco/Process_WINCE.h
@@ -0,0 +1,83 @@
+//
+// Process_WINCE.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  Process
+//
+// Definition of the ProcessImpl class for WIN32.
+//
+// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Process_WINCE_INCLUDED
+#define Foundation_Process_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/RefCountedObject.h"
+#include <vector>
+#include <map>
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Pipe;
+
+
+class Foundation_API ProcessHandleImpl: public RefCountedObject
+{
+public:
+	ProcessHandleImpl(HANDLE _hProcess, UInt32 pid);
+	~ProcessHandleImpl();
+	
+	UInt32 id() const;
+	HANDLE process() const;
+	int wait() const;
+	void closeHandle();
+
+private:
+	HANDLE _hProcess;
+	UInt32 _pid;
+
+	ProcessHandleImpl(const ProcessHandleImpl&);
+	ProcessHandleImpl& operator = (const ProcessHandleImpl&);
+};
+
+
+class Foundation_API ProcessImpl
+{
+public:
+	typedef UInt32 PIDImpl;
+	typedef std::vector<std::string> ArgsImpl;
+	typedef std::map<std::string, std::string> EnvImpl;
+	
+	static PIDImpl idImpl();
+	static void timesImpl(long& userTime, long& kernelTime);
+	static ProcessHandleImpl* launchImpl(
+		const std::string& command, 
+		const ArgsImpl& args, 
+		const std::string& initialDirectory,
+		Pipe* inPipe, 
+		Pipe* outPipe, 
+		Pipe* errPipe,
+		const EnvImpl& env);
+	static void killImpl(ProcessHandleImpl& handle);
+	static void killImpl(PIDImpl pid);
+	static bool isRunningImpl(const ProcessHandleImpl& handle);
+	static bool isRunningImpl(PIDImpl pid);
+	static void requestTerminationImpl(PIDImpl pid);
+	static std::string terminationEventName(PIDImpl pid);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Process_WINCE_INCLUDED
diff --git a/Poco/PurgeStrategy.h b/Poco/PurgeStrategy.h
new file mode 100644
index 0000000..c7ef96b
--- /dev/null
+++ b/Poco/PurgeStrategy.h
@@ -0,0 +1,97 @@
+//
+// PurgeStrategy.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  FileChannel
+//
+// Definition of the PurgeStrategy class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_PurgeStrategy_INCLUDED
+#define Foundation_PurgeStrategy_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/File.h"
+#include "Poco/Timespan.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API PurgeStrategy
+	/// The PurgeStrategy is used by FileChannel
+	/// to purge archived log files.
+{
+public:
+	PurgeStrategy();
+	virtual ~PurgeStrategy();
+
+	virtual void purge(const std::string& path) = 0;
+		/// Purges archived log files. The path to the
+		/// current "hot" log file is given.
+		/// To find archived log files, look for files
+		/// with a name consisting of the given path 
+		/// plus any suffix (e.g., .1, .20050929081500, .1.gz).
+		/// A list of archived files can be obtained by calling
+		/// the list() method.
+
+protected:
+	void list(const std::string& path, std::vector<File>& files);
+		/// Fills the given vector with a list of archived log
+		/// files. The path of the current "hot" log file is
+		/// given in path.
+		///
+		/// All files with the same name as the one given in path,
+		/// plus some suffix (e.g., .1, .20050929081500, .1.gz) are
+		/// considered archived files.
+
+private:
+	PurgeStrategy(const PurgeStrategy&);
+	PurgeStrategy& operator = (const PurgeStrategy&);
+};
+
+
+class Foundation_API PurgeByAgeStrategy: public PurgeStrategy
+	/// This purge strategy purges all files that have
+	/// exceeded a given age (given in seconds).
+{
+public:
+	PurgeByAgeStrategy(const Timespan& age);
+	~PurgeByAgeStrategy();
+	
+	void purge(const std::string& path);
+	
+private:
+	Timespan _age;
+};
+
+
+class Foundation_API PurgeByCountStrategy: public PurgeStrategy
+	/// This purge strategy ensures that a maximum number
+	/// of archived files is not exceeded. Files are deleted
+	/// based on their age, with oldest files deleted first.
+{
+public:
+	PurgeByCountStrategy(int count);
+	~PurgeByCountStrategy();
+	
+	void purge(const std::string& path);
+	
+private:
+	int _count;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_PurgeStrategy_INCLUDED
diff --git a/Poco/RWLock.h b/Poco/RWLock.h
new file mode 100644
index 0000000..23b3b16
--- /dev/null
+++ b/Poco/RWLock.h
@@ -0,0 +1,203 @@
+//
+// RWLock.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  RWLock
+//
+// Definition of the RWLock class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RWLock_INCLUDED
+#define Foundation_RWLock_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#if defined(_WIN32_WCE)
+#include "Poco/RWLock_WINCE.h"
+#else
+#include "Poco/RWLock_WIN32.h"
+#endif
+#elif POCO_OS == POCO_OS_ANDROID
+#include "Poco/RWLock_Android.h"
+#elif defined(POCO_VXWORKS)
+#include "Poco/RWLock_VX.h"
+#else
+#include "Poco/RWLock_POSIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class ScopedRWLock;
+class ScopedReadRWLock;
+class ScopedWriteRWLock;
+
+
+class Foundation_API RWLock: private RWLockImpl
+	/// A reader writer lock allows multiple concurrent
+	/// readers or one exclusive writer.
+{
+public:
+	typedef ScopedRWLock ScopedLock;
+	typedef ScopedReadRWLock ScopedReadLock;
+	typedef ScopedWriteRWLock ScopedWriteLock;
+
+	RWLock();
+		/// Creates the Reader/Writer lock.
+		
+	~RWLock();
+		/// Destroys the Reader/Writer lock.
+	
+	void readLock();
+		/// Acquires a read lock. If another thread currently holds a write lock,
+		/// waits until the write lock is released.
+
+	bool tryReadLock();
+		/// Tries to acquire a read lock. Immediately returns true if successful, or
+		/// false if another thread currently holds a write lock.
+
+	void writeLock();
+		/// Acquires a write lock. If one or more other threads currently hold 
+		/// locks, waits until all locks are released. The results are undefined
+		/// if the same thread already holds a read or write lock
+
+	bool tryWriteLock();
+		/// Tries to acquire a write lock. Immediately returns true if successful,
+		/// or false if one or more other threads currently hold 
+		/// locks. The result is undefined if the same thread already
+		/// holds a read or write lock.
+
+	void unlock();
+		/// Releases the read or write lock.
+
+private:
+	RWLock(const RWLock&);
+	RWLock& operator = (const RWLock&);
+};
+
+
+class Foundation_API ScopedRWLock
+	/// A variant of ScopedLock for reader/writer locks.
+{
+public:
+	ScopedRWLock(RWLock& rwl, bool write = false);
+	~ScopedRWLock();
+
+private:
+	RWLock& _rwl;
+
+	ScopedRWLock();
+	ScopedRWLock(const ScopedRWLock&);
+	ScopedRWLock& operator = (const ScopedRWLock&);
+};
+
+
+class Foundation_API ScopedReadRWLock : public ScopedRWLock
+	/// A variant of ScopedLock for reader locks.
+{
+public:
+	ScopedReadRWLock(RWLock& rwl);
+	~ScopedReadRWLock();
+};
+
+
+class Foundation_API ScopedWriteRWLock : public ScopedRWLock
+	/// A variant of ScopedLock for writer locks.
+{
+public:
+	ScopedWriteRWLock(RWLock& rwl);
+	~ScopedWriteRWLock();
+};
+
+
+//
+// inlines
+//
+inline void RWLock::readLock()
+{
+	readLockImpl();
+}
+
+
+inline bool RWLock::tryReadLock()
+{
+	return tryReadLockImpl();
+}
+
+
+inline void RWLock::writeLock()
+{
+	writeLockImpl();
+}
+
+
+inline bool RWLock::tryWriteLock()
+{
+	return tryWriteLockImpl();
+}
+
+
+inline void RWLock::unlock()
+{
+	unlockImpl();
+}
+
+
+inline ScopedRWLock::ScopedRWLock(RWLock& rwl, bool write): _rwl(rwl)
+{
+	if (write)
+		_rwl.writeLock();
+	else
+		_rwl.readLock();
+}
+
+
+inline ScopedRWLock::~ScopedRWLock()
+{
+	try
+	{
+		_rwl.unlock();
+	}
+	catch (...)
+	{
+		poco_unexpected();
+	}
+}
+
+
+inline ScopedReadRWLock::ScopedReadRWLock(RWLock& rwl): ScopedRWLock(rwl, false)
+{
+}
+
+
+inline ScopedReadRWLock::~ScopedReadRWLock()
+{
+}
+
+
+inline ScopedWriteRWLock::ScopedWriteRWLock(RWLock& rwl): ScopedRWLock(rwl, true)
+{
+}
+
+
+inline ScopedWriteRWLock::~ScopedWriteRWLock()
+{
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RWLock_INCLUDED
diff --git a/Poco/RWLock_Android.h b/Poco/RWLock_Android.h
new file mode 100644
index 0000000..c6dfc4e
--- /dev/null
+++ b/Poco/RWLock_Android.h
@@ -0,0 +1,97 @@
+//
+// RWLock_Android.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  RWLock
+//
+// Definition of the RWLockImpl class for Android Threads.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RWLock_Android_INCLUDED
+#define Foundation_RWLock_Android_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <pthread.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API RWLockImpl
+{
+protected:
+	RWLockImpl();
+	~RWLockImpl();
+	void readLockImpl();
+	bool tryReadLockImpl();
+	void writeLockImpl();
+	bool tryWriteLockImpl();
+	void unlockImpl();
+	
+private:
+	pthread_mutex_t _mutex;
+};
+
+
+//
+// inlines
+//
+inline void RWLockImpl::readLockImpl()
+{
+	if (pthread_mutex_lock(&_mutex)) 
+		throw SystemException("cannot lock reader/writer lock");
+}
+
+
+inline bool RWLockImpl::tryReadLockImpl()
+{
+	int rc = pthread_mutex_trylock(&_mutex);
+	if (rc == 0)
+		return true;
+	else if (rc == EBUSY)
+		return false;
+	else
+		throw SystemException("cannot lock reader/writer lock");
+}
+
+
+inline void RWLockImpl::writeLockImpl()
+{
+	if (pthread_mutex_lock(&_mutex)) 
+		throw SystemException("cannot lock reader/writer lock");
+}
+
+
+inline bool RWLockImpl::tryWriteLockImpl()
+{
+	int rc = pthread_mutex_trylock(&_mutex);
+	if (rc == 0)
+		return true;
+	else if (rc == EBUSY)
+		return false;
+	else
+		throw SystemException("cannot lock reader/writer lock");
+}
+
+
+inline void RWLockImpl::unlockImpl()
+{
+	if (pthread_mutex_unlock(&_mutex))
+		throw SystemException("cannot unlock reader/writer lock");
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RWLock_Android_INCLUDED
diff --git a/Poco/RWLock_POSIX.h b/Poco/RWLock_POSIX.h
new file mode 100644
index 0000000..be4d11b
--- /dev/null
+++ b/Poco/RWLock_POSIX.h
@@ -0,0 +1,99 @@
+//
+// RWLock_POSIX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  RWLock
+//
+// Definition of the RWLockImpl class for POSIX Threads.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RWLock_POSIX_INCLUDED
+#define Foundation_RWLock_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <pthread.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API RWLockImpl
+{
+protected:
+	RWLockImpl();
+	~RWLockImpl();
+	void readLockImpl();
+	bool tryReadLockImpl();
+	void writeLockImpl();
+	bool tryWriteLockImpl();
+	void unlockImpl();
+	
+private:
+	pthread_rwlock_t _rwl;
+};
+
+
+//
+// inlines
+//
+inline void RWLockImpl::readLockImpl()
+{
+	if (pthread_rwlock_rdlock(&_rwl)) 
+		throw SystemException("cannot lock reader/writer lock");
+}
+
+
+inline bool RWLockImpl::tryReadLockImpl()
+{
+	int rc = pthread_rwlock_tryrdlock(&_rwl);
+	if (rc == 0)
+		return true;
+	else if (rc == EBUSY)
+		return false;
+	else
+		throw SystemException("cannot lock reader/writer lock");
+
+}
+
+
+inline void RWLockImpl::writeLockImpl()
+{
+	if (pthread_rwlock_wrlock(&_rwl)) 
+		throw SystemException("cannot lock reader/writer lock");
+}
+
+
+inline bool RWLockImpl::tryWriteLockImpl()
+{
+	int rc = pthread_rwlock_trywrlock(&_rwl);
+	if (rc == 0)
+		return true;
+	else if (rc == EBUSY)
+		return false;
+	else
+		throw SystemException("cannot lock reader/writer lock");
+
+}
+
+
+inline void RWLockImpl::unlockImpl()
+{
+	if (pthread_rwlock_unlock(&_rwl))
+		throw SystemException("cannot unlock mutex");
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RWLock_POSIX_INCLUDED
diff --git a/Poco/RWLock_VX.h b/Poco/RWLock_VX.h
new file mode 100644
index 0000000..bdc4af2
--- /dev/null
+++ b/Poco/RWLock_VX.h
@@ -0,0 +1,92 @@
+//
+// RWLock_VX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  RWLock
+//
+// Definition of the RWLockImpl class for POSIX Threads (VxWorks).
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RWLock_VX_INCLUDED
+#define Foundation_RWLock_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <pthread.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API RWLockImpl
+{
+protected:
+	RWLockImpl();
+	~RWLockImpl();
+	void readLockImpl();
+	bool tryReadLockImpl();
+	void writeLockImpl();
+	bool tryWriteLockImpl();
+	void unlockImpl();
+	
+private:
+	pthread_mutex_t _mutex;
+};
+
+
+//
+// inlines
+//
+inline void RWLockImpl::readLockImpl()
+{
+	if (pthread_mutex_lock(&_mutex)) 
+		throw SystemException("cannot lock mutex");
+}
+
+
+inline bool RWLockImpl::tryReadLockImpl()
+{
+	int rc = pthread_mutex_trylock(&_mutex);
+	if (rc == 0)
+		return true;
+	else if (rc == EBUSY)
+		return false;
+	else
+		throw SystemException("cannot lock mutex");
+
+}
+
+
+inline void RWLockImpl::writeLockImpl()
+{
+	readLockImpl();
+}
+
+
+inline bool RWLockImpl::tryWriteLockImpl()
+{
+	return tryReadLockImpl();
+
+}
+
+
+inline void RWLockImpl::unlockImpl()
+{
+	if (pthread_mutex_unlock(&_mutex))
+		throw SystemException("cannot unlock mutex");
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RWLock_VX_INCLUDED
diff --git a/Poco/RWLock_WIN32.h b/Poco/RWLock_WIN32.h
new file mode 100644
index 0000000..e50856e
--- /dev/null
+++ b/Poco/RWLock_WIN32.h
@@ -0,0 +1,57 @@
+//
+// RWLock_WIN32.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  RWLock
+//
+// Definition of the RWLockImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RWLock_WIN32_INCLUDED
+#define Foundation_RWLock_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API RWLockImpl
+{
+protected:
+	RWLockImpl();
+	~RWLockImpl();
+	void readLockImpl();
+	bool tryReadLockImpl();
+	void writeLockImpl();
+	bool tryWriteLockImpl();
+	void unlockImpl();
+	
+private:
+	void addWriter();
+	void removeWriter();
+	DWORD tryReadLockOnce();
+
+	HANDLE   _mutex;
+	HANDLE   _readEvent;
+	HANDLE   _writeEvent;
+	unsigned _readers;
+	unsigned _writersWaiting;
+	unsigned _writers;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RWLock_WIN32_INCLUDED
diff --git a/Poco/RWLock_WINCE.h b/Poco/RWLock_WINCE.h
new file mode 100644
index 0000000..d6c8314
--- /dev/null
+++ b/Poco/RWLock_WINCE.h
@@ -0,0 +1,61 @@
+//
+// RWLock_WINCE.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  RWLock
+//
+// Definition of the RWLockImpl class for WINCE.
+//
+// Copyright (c) 2009-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RWLock_WINCE_INCLUDED
+#define Foundation_RWLock_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API RWLockImpl
+	/// This implementation is based on the one from Stone Steps Inc,
+	/// licensed under the BSD license.
+	/// http://forums.stonesteps.ca/thread.asp?t=105
+	///
+	/// Note that with this implementation, writers always take
+	/// precedence over readers.
+{
+protected:
+	RWLockImpl();
+	~RWLockImpl();
+	void readLockImpl();
+	bool tryReadLockImpl(DWORD timeout = 1);
+	void writeLockImpl();
+	bool tryWriteLockImpl(DWORD timeout = 1);
+	void unlockImpl();
+	
+private:
+	DWORD _readerCount;
+	DWORD _readerWaiting;
+	DWORD _writerCount;
+	DWORD _writerWaiting;
+	HANDLE _readerGreen;
+	HANDLE _writerGreen;
+	CRITICAL_SECTION _cs;
+	bool _writeLock;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RWLock_WINCE_INCLUDED
diff --git a/Poco/Random.h b/Poco/Random.h
new file mode 100644
index 0000000..3db078e
--- /dev/null
+++ b/Poco/Random.h
@@ -0,0 +1,165 @@
+//
+// Random.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  Random
+//
+// Definition of class Random.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+//
+// Based on the FreeBSD random number generator.
+// src/lib/libc/stdlib/random.c,v 1.25 
+//
+// Copyright (c) 1983, 1993
+// The Regents of the University of California.  All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 4. Neither the name of the University nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+
+#ifndef Foundation_Random_INCLUDED
+#define Foundation_Random_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Random
+	/// A better random number generator.
+	/// Random implements a pseudo random number generator
+	/// (PRNG). The PRNG is a nonlinear additive
+	/// feedback random number generator using 256 bytes
+	/// of state information and a period of up to 2^69.
+{
+public:
+	enum Type
+	{
+		RND_STATE_0   =   8,  /// linear congruential
+		RND_STATE_32  =  32,  /// x**7 + x**3 + 1
+		RND_STATE_64  =  64,  /// x**15 + x + 1
+		RND_STATE_128 = 128,  /// x**31 + x**3 + 1
+		RND_STATE_256 = 256   /// x**63 + x + 1
+	};
+
+	Random(int stateSize = 256);
+		/// Creates and initializes the PRNG.
+		/// Specify either a state buffer size
+		/// (8 to 256 bytes) or one of the Type values.
+
+	~Random();
+		/// Destroys the PRNG.
+
+	void seed(UInt32 seed);
+		/// Seeds the pseudo random generator with the given seed.
+
+	void seed();
+		/// Seeds the pseudo random generator with a random seed
+		/// obtained from a RandomInputStream.
+
+	UInt32 next();
+		/// Returns the next 31-bit pseudo random number.
+
+	UInt32 next(UInt32 n);
+		/// Returns the next 31-bit pseudo random number modulo n.
+	
+	char nextChar();
+		/// Returns the next pseudo random character.
+	
+	bool nextBool();
+		/// Returns the next boolean pseudo random value.
+		
+	float nextFloat();
+		/// Returns the next float pseudo random number between 0.0 and 1.0.
+		
+	double nextDouble();
+		/// Returns the next double pseudo random number between 0.0 and 1.0.
+
+protected:
+	void initState(UInt32 seed, char* arg_state, Int32 n);
+	static UInt32 goodRand(Int32 x);
+
+private:
+	enum
+	{
+		MAX_TYPES = 5,
+		NSHUFF    = 50
+	};
+
+	UInt32* _fptr;
+	UInt32* _rptr;
+	UInt32* _state;
+	int     _randType;
+	int     _randDeg;
+	int     _randSep;
+	UInt32* _endPtr;
+	char*  _pBuffer;
+};
+
+
+//
+// inlines
+//
+inline UInt32 Random::next(UInt32 n)
+{
+	return next() % n;
+}
+
+
+inline char Random::nextChar()
+{
+	return char((next() >> 3) & 0xFF);
+}
+
+
+inline bool Random::nextBool()
+{
+	return (next() & 0x1000) != 0;
+}
+
+	
+inline float Random::nextFloat()
+{
+	return float(next()) / 0x7FFFFFFF;
+}
+
+	
+inline double Random::nextDouble()
+{
+	return double(next()) / 0x7FFFFFFF;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Random_INCLUDED
diff --git a/Poco/RandomStream.h b/Poco/RandomStream.h
new file mode 100644
index 0000000..152b95c
--- /dev/null
+++ b/Poco/RandomStream.h
@@ -0,0 +1,73 @@
+//
+// RandomStream.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  RandomStream
+//
+// Definition of class RandomInputStream.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RandomStream_INCLUDED
+#define Foundation_RandomStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/BufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class Foundation_API RandomBuf: public BufferedStreamBuf
+	/// This streambuf generates random data.
+	/// On Windows NT, the cryptographic API is used.
+	/// On Unix, /dev/random is used, if available.
+	/// Otherwise, a random number generator, some
+	/// more-or-less random data and a SHA-1 digest
+	/// is used to generate random data.
+{
+public:
+	RandomBuf();
+	~RandomBuf();
+	int readFromDevice(char* buffer, std::streamsize length);
+};
+
+
+class Foundation_API RandomIOS: public virtual std::ios
+	/// The base class for RandomInputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	RandomIOS();
+	~RandomIOS();
+	RandomBuf* rdbuf();
+
+protected:
+	RandomBuf _buf;
+};
+
+
+class Foundation_API RandomInputStream: public RandomIOS, public std::istream
+	/// This istream generates random data
+	/// using the RandomBuf.
+{
+public:
+	RandomInputStream();
+	~RandomInputStream();
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RandomStream_INCLUDED
diff --git a/Poco/RecursiveDirectoryIterator.h b/Poco/RecursiveDirectoryIterator.h
new file mode 100644
index 0000000..c0ce228
--- /dev/null
+++ b/Poco/RecursiveDirectoryIterator.h
@@ -0,0 +1,254 @@
+//
+// RecursiveDirectoryIterator.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  RecursiveDirectoryIterator
+//
+// Definition of the RecursiveDirectoryIterator class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RecursiveDirectoryIterator_INCLUDED
+#define Foundation_RecursiveDirectoryIterator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/File.h"
+#include "Poco/Path.h"
+#include "Poco/RecursiveDirectoryIteratorImpl.h"
+#include "Poco/DirectoryIteratorStrategy.h"
+
+
+namespace Poco {
+
+
+class DirectoryIterator;
+
+
+template<class TTravStr>
+class RecursiveDirectoryIteratorImpl;
+
+
+template<class TTravStr = ChildrenFirstTraverse>
+class RecursiveDirectoryIterator
+	/// The RecursiveDirectoryIterator class is used to enumerate
+	/// all files in a directory and its subdirectories.
+	///
+	/// RecursiveDirectoryIterator has some limitations:
+	///   * only forward iteration (++) is supported
+	///   * an iterator copied from another one will always
+	///     point to the same file as the original iterator,
+	///     even is the original iterator has been advanced
+	///     (all copies of an iterator share their state with
+	///     the original iterator)
+	///
+	/// The class can follow different traversal strategies:
+	///     * depth-first strategy;
+	///     * siblings-first strategy.
+	/// The stategies are set by template parameter.
+	/// There are two corresponding typedefs:
+	///     * SimpleRecursiveDirectoryIterator;
+	///     * SiblingsFirstRecursiveDirectoryIterator.
+	///
+	/// The depth of traversal can be limited by constructor
+	/// parameter maxDepth (which sets the infinite depth by default).
+{
+public:
+	typedef RecursiveDirectoryIterator<TTravStr> MyType;
+
+	enum
+	{
+		D_INFINITE = 0 /// Constant for infinite traverse depth.
+	};
+
+	RecursiveDirectoryIterator()
+		/// Creates the end iterator.
+		: _pImpl(0)
+	{
+	}
+
+	RecursiveDirectoryIterator(const std::string& path, UInt16 maxDepth = D_INFINITE)
+		/// Creates a recursive directory iterator for the given path.
+		: _pImpl(new ImplType(path, maxDepth)), _path(Path(_pImpl->get())), _file(_path)
+	{
+	}
+
+	RecursiveDirectoryIterator(const MyType& iterator):
+		/// Creates a copy of another recursive directory iterator.
+		_pImpl(iterator._pImpl), _path(iterator._path), _file(iterator._file)
+	{
+	}
+
+	RecursiveDirectoryIterator(const DirectoryIterator& iterator, UInt16 maxDepth = D_INFINITE):
+		/// Creates a recursive directory iterator for the path of
+		/// non-recursive directory iterator.
+		_pImpl(new ImplType(iterator->path(), maxDepth)), _path(Path(_pImpl->get())), _file(_path)
+	{
+	}
+
+	RecursiveDirectoryIterator(const File& file, UInt16 maxDepth = D_INFINITE):
+		/// Creates a recursive directory iterator for the given path.
+		_pImpl(new ImplType(file.path(), maxDepth)), _path(Path(_pImpl->get())), _file(_path)
+	{
+	}
+
+	RecursiveDirectoryIterator(const Path& path, UInt16 maxDepth = D_INFINITE):
+		/// Creates a recursive directory iterator for the given path.
+		_pImpl(new ImplType(path.toString(), maxDepth)), _path(Path(_pImpl->get())), _file(_path)
+	{
+	}
+
+	~RecursiveDirectoryIterator()
+		/// Destroys the DirectoryIterator.
+	{
+		if (_pImpl)
+			_pImpl->release();
+	}
+
+	const std::string& name() const
+		/// Returns the current filename.
+	{
+		return _path.getFileName();
+	}
+
+	const Poco::Path& path() const
+		/// Returns the current path.
+	{
+		return _path;
+	}
+
+	UInt16 depth() const
+		/// Depth of recursion (counting from 1).
+	{
+		return _pImpl->depth();
+	}
+
+	UInt16 maxDepth() const
+		/// Max depth of recursion (counting from 1).
+	{
+		return _pImpl->maxDepth();
+	}
+
+
+	MyType& operator = (const MyType& it)
+	{
+		if (_pImpl)
+			_pImpl->release();
+		_pImpl = it._pImpl;
+		if (_pImpl)
+		{
+			_pImpl->duplicate();
+			_path = it._path;
+			_file = _path;
+		}
+		return *this;
+	}
+
+	MyType& operator = (const File& file)
+	{
+		if (_pImpl)
+			_pImpl->release();
+		_pImpl = new ImplType(file.path());
+		_path = Path(_pImpl->get());
+		_file = _path;
+		return *this;
+	}
+
+
+	MyType& operator = (const Path& path)
+	{
+		if (_pImpl)
+			_pImpl->release();
+		_pImpl = new ImplType(path.toString());
+		_path = Path(_pImpl->get());
+		_file = _path;
+		return *this;
+	}
+
+	MyType& operator = (const std::string& path)
+	{
+		if (_pImpl)
+			_pImpl->release();
+		_pImpl = new ImplType(path);
+		_path = Path(_pImpl->get());
+		_file = _path;
+		return *this;
+	}
+
+	MyType& operator ++ ()
+	{
+		if (_pImpl)
+		{
+			_path = Path(_pImpl->next());
+			_file = _path;
+		}
+		return *this;
+	}
+
+	const File& operator * () const
+	{
+		return _file;
+	}
+
+	File& operator *()
+	{
+		return _file;
+	}
+
+	const File* operator -> () const
+	{
+		return &_file;
+	}
+
+	File* operator -> ()
+	{
+		return &_file;
+	}
+
+	template<class T1, class T2>
+	friend inline bool operator ==(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b);
+	template<class T1, class T2>
+	friend inline bool operator !=(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b);
+
+private:
+	typedef RecursiveDirectoryIteratorImpl<TTravStr> ImplType;
+
+	ImplType* _pImpl;
+	Path _path;
+	File _file;
+};
+
+
+//
+// friend comparsion operators
+//
+template<class T1, class T2>
+inline bool operator ==(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b)
+{
+	return a.path().toString() == b.path().toString();;
+}
+
+template<class T1, class T2>
+inline bool operator !=(const RecursiveDirectoryIterator<T1>& a, const RecursiveDirectoryIterator<T2>& b)
+{
+	return a.path().toString() != b.path().toString();;
+}
+
+
+//
+// typedefs
+//
+typedef RecursiveDirectoryIterator<ChildrenFirstTraverse> SimpleRecursiveDirectoryIterator;
+typedef RecursiveDirectoryIterator<SiblingsFirstTraverse> SiblingsFirstRecursiveDirectoryIterator;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RecursiveDirectoryIterator_INCLUDED
diff --git a/Poco/RecursiveDirectoryIteratorImpl.h b/Poco/RecursiveDirectoryIteratorImpl.h
new file mode 100644
index 0000000..fb2d467
--- /dev/null
+++ b/Poco/RecursiveDirectoryIteratorImpl.h
@@ -0,0 +1,111 @@
+//
+// RecursiveDirectoryIteratorImpl.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  RecursiveDirectoryIterator
+//
+// Definition of the RecursiveDirectoryIteratorImpl class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RecursiveDirectoryIteratorImpl_INCLUDED
+#define Foundation_RecursiveDirectoryIteratorImpl_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DirectoryIteratorStrategy.h"
+#include <stack>
+#include <functional>
+
+
+namespace Poco {
+
+
+class ChildrenFirstTraverse;
+class SiblingsFirstTraverse;
+
+
+template<class TTraverseStrategy = ChildrenFirstTraverse>
+class RecursiveDirectoryIteratorImpl
+{
+public:
+	enum
+	{
+		D_INFINITE = 0 /// Special value for infinite traverse depth.
+	};
+
+	RecursiveDirectoryIteratorImpl(const std::string& path, UInt16 maxDepth = D_INFINITE)
+		: _maxDepth(maxDepth), _traverseStrategy(std::ptr_fun(depthFun), _maxDepth), _isFinished(false), _rc(1)
+	{
+		_itStack.push(DirectoryIterator(path));
+		_current = _itStack.top()->path();
+	}
+
+	~RecursiveDirectoryIteratorImpl()
+	{
+	}
+
+	inline void duplicate()
+	{
+		++_rc;
+	}
+
+	inline void release()
+	{
+		if (--_rc == 0)
+			delete this;
+	}
+
+	inline UInt16 depth() const
+	{
+		return depthFun(_itStack);
+	}
+
+	inline UInt16 maxDepth() const
+	{
+		return _maxDepth;
+	}
+
+	inline const std::string& get() const
+	{
+		return _current;
+	}
+	const std::string& next()
+	{
+		if (_isFinished)
+			return _current;
+
+		_current = _traverseStrategy.next(&_itStack, &_isFinished);
+
+		return _current;
+	}
+
+private:
+	typedef std::stack<DirectoryIterator> Stack;
+
+	static UInt16 depthFun(const Stack& stack)
+		/// Function which implements the logic of determining
+		/// recursion depth.
+	{
+		return static_cast<Poco::UInt16>(stack.size());
+	}
+
+	UInt16 _maxDepth;
+	TTraverseStrategy _traverseStrategy;
+	bool _isFinished;
+	Stack _itStack;
+	std::string _current;
+	int _rc;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RecursiveDirectoryIteratorImpl_INCLUDED
diff --git a/Poco/Redis/Array.h b/Poco/Redis/Array.h
new file mode 100644
index 0000000..262abc9
--- /dev/null
+++ b/Poco/Redis/Array.h
@@ -0,0 +1,322 @@
+//
+// Array.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Array
+//
+// Definition of the Array class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_Array_INCLUDED
+#define Redis_Array_INCLUDED
+
+
+#include "Poco/Redis/Redis.h"
+#include "Poco/Redis/Type.h"
+#include "Poco/Redis/Exception.h"
+#include <vector>
+#include <sstream>
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API Array
+	/// Represents a Redis Array. An Array can contain Integers, Strings,
+	/// Bulk Strings, Errors and other Arrays. It can also contain a Null
+	/// value.
+{
+public:
+	typedef std::vector<RedisType::Ptr>::const_iterator const_iterator;
+
+	Array();
+		/// Creates an Array. As long as there are no elements added,
+		/// the array will contain a Null value.
+
+	Array(const Array& copy);
+		/// Creates an Array by copying another one.
+
+	virtual ~Array();
+		/// Destroys the Array.
+
+	template<typename T>
+	Array& operator<<(const T& arg)
+		/// Adds the argument to the array.
+		///
+		/// Note: a std::string will be added as a BulkString because this
+		/// is commonly used for representing strings in Redis. If you
+		/// really need a simple string, use addSimpleString().
+	{
+		return add(arg);
+	}
+
+	Array& operator<<(const char* s);
+		/// Special implementation for const char*.
+		///
+		/// Note: the specialization creates a BulkString. If you need
+		/// a simple string, call addSimpleString().
+
+	Array& operator<<(const std::vector<std::string>& strings);
+		/// Special implementation for a vector with strings.
+		/// All strings will be added as a BulkString.
+
+	Array& add();
+		/// Adds an Null BulkString.
+
+	template<typename T>
+	Array& add(const T& arg)
+		/// Adds an element to the array.
+		///
+		/// Note: the specialization for std::string will add a BulkString!
+		/// If you really need a simple string, call addSimpleString.
+	{
+		addRedisType(new Type<T>(arg));
+		return *this;
+	}
+
+	Array& add(const char* s);
+		/// Special implementation for const char*.
+		///
+		/// Note: the specialization creates a BulkString. If you need
+		/// a simple string, call addSimpleString.
+
+	Array& add(const std::vector<std::string>& strings);
+		/// Special implementation for a vector with strings.
+		/// All strings will be added as a BulkString.
+
+	Array& addRedisType(RedisType::Ptr value);
+		/// Adds a Redis element.
+
+	Array& addSimpleString(const std::string& value);
+		/// Adds a simple string (can't contain newline characters!).
+
+	const_iterator begin() const;
+		/// Returns an iterator to the start of the array. 
+		///
+		/// Note: this can throw a NullValueException when this is a Null array.
+
+	void clear();
+		/// Removes all elements from the array.
+
+	const_iterator end() const;
+		/// Returns an iterator to the end of the array. 
+		///
+		/// Note: this can throw a NullValueException when this is a Null array.
+
+	template<typename T>
+	T get(size_t pos) const
+		/// Returns the element on the given position and tries to convert
+		/// to the template type. A Poco::BadCastException will be thrown when the
+		/// the conversion fails. An Poco::InvalidArgumentException will be thrown
+		/// when the index is out of range. When the array is a Null array
+		/// a Poco::NullValueException is thrown.
+	{
+		if ( _elements.isNull() ) throw NullValueException();
+
+		if ( pos >= _elements.value().size() ) throw InvalidArgumentException();
+
+		RedisType::Ptr element = _elements.value().at(pos);
+		if ( RedisTypeTraits<T>::TypeId == element->type() )
+		{
+			Type<T>* concrete = dynamic_cast<Type<T>* >(element.get());
+			if ( concrete != NULL ) return concrete->value();
+		}
+		throw BadCastException();
+	}
+
+	int getType(size_t pos) const;
+		/// Returns the type of the element. This can throw a Poco::NullValueException
+		/// when this array is a Null array. An Poco::InvalidArgumentException will
+		/// be thrown when the index is out of range.
+
+	bool isNull() const;
+		/// Returns true when this is a Null array.
+
+	void makeNull();
+		/// Turns the array into a Null array. When the array already has some
+		/// elements, the array will be cleared.
+
+	std::string toString() const;
+		/// Returns the String representation as specified in the
+		/// Redis Protocol specification.
+
+	size_t size() const;
+		/// Returns the size of the array. 
+		///
+		/// Note: this can throw a NullValueException when this is a Null array.
+
+private:
+	void checkNull();
+		/// Checks for null array and sets a new vector if true.
+
+	Nullable<std::vector<RedisType::Ptr> > _elements;
+};
+
+
+//
+// inlines
+//
+
+
+inline Array& Array::operator<<(const char* s)
+{
+	BulkString value(s);
+	return add(value);
+}
+
+
+inline Array& Array::operator<<(const std::vector<std::string>& strings)
+{
+	return add(strings);
+}
+
+
+inline Array& Array::add()
+{
+	BulkString value;
+	return add(value);
+}
+
+
+template<>
+inline Array& Array::add(const std::string& arg)
+{
+	BulkString value(arg);
+	return add(value);
+}
+
+
+inline Array& Array::add(const char* s)
+{
+	BulkString value(s);
+	return add(value);
+}
+
+
+inline Array& Array::add(const std::vector<std::string>& strings)
+{
+	for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it)
+	{
+		add(*it);
+	}
+	return *this;
+}
+
+
+inline Array& Array::addSimpleString(const std::string& value)
+{
+	return addRedisType(new Type<std::string>(value));
+}
+
+
+inline Array::const_iterator Array::begin() const
+{
+	return _elements.value().begin();
+}
+
+
+inline void Array::checkNull()
+{
+	std::vector<RedisType::Ptr> v;
+	if ( _elements.isNull() ) _elements.assign(v);
+}
+
+
+inline void Array::clear()
+{
+	if ( !_elements.isNull() )
+	{
+		_elements.value().clear();
+	}
+}
+
+
+inline Array::const_iterator Array::end() const
+{
+	return _elements.value().end();
+}
+
+
+inline bool Array::isNull() const
+{
+	return _elements.isNull();
+}
+
+
+inline void Array::makeNull()
+{
+	if ( !_elements.isNull() ) _elements.value().clear();
+
+	_elements.clear();
+}
+
+
+inline size_t Array::size() const
+{
+	return _elements.value().size();
+}
+
+
+template<>
+struct RedisTypeTraits<Array>
+{
+	enum { TypeId = RedisType::REDIS_ARRAY };
+
+	static const char marker = '*';
+
+	static std::string toString(const Array& value)
+	{
+		std::stringstream result;
+		result <<  marker;
+		if ( value.isNull() )
+		{
+			result << "-1" << LineEnding::NEWLINE_CRLF;
+		}
+		else
+		{
+			result << value.size() << LineEnding::NEWLINE_CRLF;
+			for(std::vector<RedisType::Ptr>::const_iterator it = value.begin();
+				it != value.end(); ++it)
+			{
+				result << (*it)->toString();
+			}
+		}
+		return result.str();
+	}
+
+	static void read(RedisInputStream& input, Array& value)
+	{
+		value.clear();
+
+		Int64 length = NumberParser::parse64(input.getline());
+
+		if ( length != -1 )
+		{
+			for(int i = 0; i < length; ++i)
+			{
+				char marker = input.get();
+				RedisType::Ptr element = RedisType::createRedisType(marker);
+
+				if ( element.isNull() )
+					throw RedisException("Wrong answer received from Redis server");
+
+				element->read(input);
+				value.addRedisType(element);
+			}
+		}
+	}
+};
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_Array_INCLUDED
diff --git a/Poco/Redis/AsyncReader.h b/Poco/Redis/AsyncReader.h
new file mode 100644
index 0000000..040ce32
--- /dev/null
+++ b/Poco/Redis/AsyncReader.h
@@ -0,0 +1,98 @@
+//
+// AsyncReader.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  AsyncReader
+//
+// Definition of the AsyncReader class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_AsyncReader_INCLUDED
+#define Redis_AsyncReader_INCLUDED
+
+
+#include "Poco/Redis/Redis.h"
+#include "Poco/Redis/Client.h"
+#include "Poco/Redis/RedisEventArgs.h"
+#include "Poco/Activity.h"
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API AsyncReader
+	/// Wrapper around a Redis client to read messages asynchronously. Use this
+	/// for publish/subscribe. The redisResponse event is used to notify that
+	/// a message is received. When a reader is started for a Redis server,
+	/// you should use execute<void>, because this class is responsible for
+	/// reading all replies.
+{
+public:
+	BasicEvent<RedisEventArgs> redisResponse;
+		/// Event that is fired when a message is received.
+
+	BasicEvent<RedisEventArgs> redisException;
+		/// Event that is fired when an error occurred.
+
+	AsyncReader(Client& client);
+		/// Creates the AsyncReader using the given Client.
+
+	virtual ~AsyncReader();
+		/// Destroys the AsyncReader.
+
+	bool isStopped();
+		/// Returns true if the activity is not running, false when it is.
+
+	void start();
+		/// Starts the activity to read replies from the Redis server.
+
+	void stop();
+		/// Stops the read activity.
+
+protected:
+	void runActivity();
+
+private:
+	AsyncReader(const AsyncReader&);
+	AsyncReader& operator = (const AsyncReader&);
+
+	Client& _client;
+	Activity<AsyncReader> _activity;
+};
+
+
+//
+// inlines
+//
+
+
+inline bool AsyncReader::isStopped()
+{
+	return _activity.isStopped();
+}
+
+
+inline void AsyncReader::start()
+{
+	_activity.start();
+}
+
+
+inline void AsyncReader::stop()
+{
+	_activity.stop();
+}
+
+
+} } // namespace Poco::Redis
+
+
+#endif //Redis_AsyncReader_INCLUDED
diff --git a/Poco/Redis/Client.h b/Poco/Redis/Client.h
new file mode 100644
index 0000000..6b204ae
--- /dev/null
+++ b/Poco/Redis/Client.h
@@ -0,0 +1,239 @@
+//
+// Client.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Client
+//
+// Definition of the Client class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_Client_INCLUDED
+#define Redis_Client_INCLUDED
+
+
+#include "Poco/Redis/Redis.h"
+#include "Poco/Redis/Array.h"
+#include "Poco/Redis/Error.h"
+#include "Poco/Redis/RedisStream.h"
+#include "Poco/Net/SocketAddress.h"
+#include "Poco/Timespan.h"
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API Client
+	/// Represents a connection to a Redis server.
+	///
+	/// A command is always made from an Array and a reply can be a signed 64
+	/// bit integer, a simple string, a bulk string, an array or an error. The
+	/// first element of the command array is the Redis command. A simple string
+	/// is a string that cannot contain a CR or LF character. A bulk string is
+	/// implemented as a typedef for Poco::Nullable<std::string>. This is
+	/// because a bulk string can represent a Null value.
+	///
+	///     BulkString bs = client.execute<BulkString>(...);
+	///     if ( bs.isNull() )
+	///     {
+	///        // We have a Null value
+	///     }
+	///     else
+	///     {
+	///        // We have a string value
+	///     }
+	///
+	/// To create Redis commands, the factory methods of the Command class can
+	/// be used or the Array class can be used directly.
+	///
+	///     Command llen = Command::llen("list");
+	///
+	/// is the same as:
+	///
+	///     Array command;
+	///     command.add("LLEN").add("list");
+	///
+	/// or:
+	///
+	///     Array command;
+	///     command << "LLEN" << "list";
+	///
+	///	or even:
+	///
+	///     Command command("LLEN");
+	///     command << "list";
+{
+public:
+	typedef SharedPtr<Client> Ptr;
+
+	Client();
+		/// Creates an unconnected Client.
+		/// Use this when you want to connect later on.
+
+	Client(const std::string& hostAndPort);
+		/// Constructor which connects to the given Redis host/port.
+		/// The host and port must be separated with a colon.
+
+	Client(const std::string& host, int port);
+		/// Constructor which connects to the given Redis host/port.
+
+	Client(const Net::SocketAddress& addrs);
+		/// Constructor which connects to the given Redis host/port.
+
+	virtual ~Client();
+		/// Destroys the Client.
+
+	Net::SocketAddress address() const;
+		/// Returns the address of the Redis connection.
+
+	void connect(const std::string& hostAndPort);
+		/// Connects to the given Redis server. The host and port must be
+		/// separated with a colon.
+
+	void connect(const std::string& host, int port);
+		/// Connects to the given Redis server.
+
+	void connect(const Net::SocketAddress& addrs);
+		/// Connects to the given Redis server.
+
+	void connect(const std::string& hostAndPort, const Timespan& timeout);
+		/// Connects to the given Redis server. The host and port must be
+		/// separated with a colon.
+
+	void connect(const std::string& host, int port, const Timespan& timeout);
+		/// Connects to the given Redis server.
+
+	void connect(const Net::SocketAddress& addrs, const Timespan& timeout);
+		/// Connects to the given Redis server.
+
+	void disconnect();
+		/// Disconnects from the Redis server.
+
+	bool isConnected() const;
+		/// Returns true iff the Client is connected to a Redis server.
+
+	template<typename T>
+	T execute(const Array& command)
+		/// Sends the Redis Command to the server. It gets the reply
+		/// and tries to convert it to the given template type.
+		///
+		/// A specialization exists for type void, which doesn't read
+		/// the reply. If the server sends a reply, it is your
+		/// responsibility to read it. Use this for pipelining.
+		///
+		/// A Poco::BadCastException will be thrown when the reply couldn't be
+		/// converted. Supported types are Int64, std::string, BulkString,
+		/// Array and void. When the reply is an Error, it will throw
+		/// a RedisException.
+	{
+		T result = T();
+		writeCommand(command, true);
+		readReply(result);
+		return result;
+	}
+
+	void flush();
+		/// Flush the output buffer to Redis. Use this when commands
+		/// are stored in the buffer to send them all at once to Redis.
+
+	RedisType::Ptr sendCommand(const Array& command);
+		/// Sends a Redis command to the server and returns the reply.
+		/// Use this when the type of the reply isn't known.
+
+	RedisType::Ptr readReply();
+		/// Read a reply from the Redis server.
+
+	template<typename T>
+	void readReply(T& result)
+		/// Read a reply from the Redis server and tries to convert that reply
+		/// to the template type. When the reply is a Redis error, it will
+		/// throw a RedisException. A BadCastException will be thrown, when
+		/// the reply is not of the given type.
+	{
+		RedisType::Ptr redisResult = readReply();
+		if (redisResult->type() == RedisTypeTraits<Error>::TypeId)
+		{
+			Type<Error>* error = dynamic_cast<Type<Error>*>(redisResult.get());
+			throw RedisException(error->value().getMessage());
+		}
+
+		if (redisResult->type() == RedisTypeTraits<T>::TypeId)
+		{
+			Type<T>* type = dynamic_cast<Type<T>*>(redisResult.get());
+			if (type != NULL) result = type->value();
+		}
+		else throw BadCastException();
+	}
+
+	Array sendCommands(const std::vector<Array>& commands);
+		/// Sends all commands (pipelining) to the Redis server before
+		/// getting all replies.
+
+	void setReceiveTimeout(const Timespan& timeout);
+		/// Sets a receive timeout.
+
+private:
+	Client(const Client&);
+	Client& operator = (const Client&);
+
+	void connect();
+		/// Connects to the Redis server
+
+	void connect(const Timespan& timeout);
+		/// Connects to the Redis server and sets a timeout.
+
+	void writeCommand(const Array& command, bool flush);
+		/// Sends a request to the Redis server. Use readReply to get the
+		/// answer. Can also be used for pipelining commands. Make sure you
+		/// call readReply as many times as you called writeCommand, even when
+		/// an error occurred on a command.
+
+	Net::SocketAddress _address;
+	Net::StreamSocket _socket;
+	RedisInputStream* _input;
+	RedisOutputStream* _output;
+};
+
+
+//
+// inlines
+//
+
+
+inline Net::SocketAddress Client::address() const
+{
+	return _address;
+}
+
+
+template<> inline
+void Client::execute<void>(const Array& command)
+{
+	writeCommand(command, false);
+}
+
+
+inline void Client::flush()
+{
+	poco_assert(_output);
+	_output->flush();
+}
+
+
+inline void Client::setReceiveTimeout(const Timespan& timeout)
+{
+	_socket.setReceiveTimeout(timeout);
+}
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_Client_INCLUDED
diff --git a/Poco/Redis/Command.h b/Poco/Redis/Command.h
new file mode 100644
index 0000000..627441c
--- /dev/null
+++ b/Poco/Redis/Command.h
@@ -0,0 +1,279 @@
+//
+// Command.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Command
+//
+// Definition of the Command class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_Command_INCLUDED
+#define Redis_Command_INCLUDED
+
+
+#include "Poco/Redis/Redis.h"
+#include "Poco/Redis/Array.h"
+#include <vector>
+#include <map>
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API Command: public Array
+	/// Helper class for creating commands. This class contains
+	/// factory methods for commonly used Redis commands.
+	///
+	/// There are two ways of building commands:
+	///
+	///     1. Use this class and the factory methods
+	///     2. Use the Array or Command class and build the command using the add
+	///        method or << operator.
+	///
+	/// For example:
+	///
+	///     Command cmd = Command::set("mykey", "Hello");
+	///
+	/// is the same as:
+	///
+	///     Array cmd;
+	///     cmd << "SET" << "mykey" << "Hello";
+	///
+{
+public:
+	typedef std::vector<std::string> StringVec;
+
+	Command(const std::string& command);
+		/// Creates a command.
+
+	Command(const Command& copy);
+		/// Creates a command by copying another one.
+
+	virtual ~Command();
+		/// Destroys the command.
+
+	static Command append(const std::string& key, const std::string& value);
+		/// Creates and returns an APPEND command.
+
+	static Command blpop(const StringVec& lists, Int64 timeout = 0);
+		/// Creates and returns a BLPOP command.
+
+	static Command brpop(const StringVec& lists, Int64 timeout = 0);
+		/// Creates and returns a BRPOP command.
+
+	static Command brpoplpush(const std::string& sourceList, const std::string& destinationList, Int64 timeout = 0);
+		/// Creates and returns a BRPOPLPUSH command.
+
+	static Command decr(const std::string& key, Int64 by = 0);
+		/// Creates and returns an DECR or DECRBY command. Calls DECR when by is omitted or zero.
+
+	static Command del(const std::string& key);
+		/// Creates and returns an DEL command.
+
+	static Command del(const StringVec& keys);
+		/// Creates and returns an DEL command.
+
+	static Command get(const std::string& key);
+		/// Creates and returns an GET command.
+
+	static Command exists(const std::string& key);
+		/// Creates and returns an EXISTS command.
+
+	static Command hdel(const std::string& hash, const std::string& field);
+		/// Creates and returns an HDEL command.
+
+	static Command hdel(const std::string& hash, const StringVec& fields);
+		/// Creates and returns an HDEL command.
+
+	static Command hexists(const std::string& hash, const std::string& field);
+		/// Creates and returns an HEXISTS command.
+
+	static Command hget(const std::string& hash, const std::string& field);
+		/// Creates and returns an HGET command.
+
+	static Command hgetall(const std::string& hash);
+		/// Creates and returns an HGETALL command.
+
+	static Command hincrby(const std::string& hash, const std::string& field, Int64 by = 1);
+		/// Creates and returns an HINCRBY command.
+
+	static Command hkeys(const std::string& hash);
+		/// Creates and returns an HKEYS command.
+
+	static Command hlen(const std::string& hash);
+		/// Creates and returns an HLEN command.
+
+	static Command hmget(const std::string& hash, const StringVec& fields);
+		/// Creates and returns an HMGET command.
+
+	static Command hmset(const std::string& hash, std::map<std::string, std::string>& fields);
+		/// Creates and returns a HMSET command.
+
+	static Command hset(const std::string& hash, const std::string& field, const std::string& value, bool create = true);
+		/// Creates and returns an HSET or HSETNX (when create is false) command.
+
+	static Command hset(const std::string& hash, const std::string& field, Int64 value, bool create = true);
+		/// Creates and returns an HSET or HSETNX (when create is false) command.
+
+	static Command hstrlen(const std::string& hash, const std::string& field);
+		/// Creates and returns an HSTRLEN command (Available for Redis 3.2).
+
+	static Command hvals(const std::string& hash);
+		/// Creates and returns an HVALS command.
+
+	static Command incr(const std::string& key, Int64 by = 0);
+		/// Creates and returns an INCR or INCRBY command. Calls INCR when by is omitted or zero.
+
+	static Command lindex(const std::string& list, Int64 index = 0);
+		/// Creates and returns a LINDEX command.
+
+	static Command linsert(const std::string& list, bool before, const std::string& reference, const std::string& value);
+		/// Creates and returns a LINSERT command.
+
+	static Command llen(const std::string& list);
+		/// Creates and returns a LLEN command.
+
+	static Command lpop(const std::string& list);
+		/// Creates and returns a LPOP command.
+
+	static Command lpush(const std::string& list, const std::string& value, bool create = true);
+		/// Creates and returns a LPUSH or LPUSHX (when create is false) command.
+
+	static Command lpush(const std::string& list, const StringVec& value, bool create = true);
+		/// Creates and returns a LPUSH or LPUSHX (when create is false) command.
+
+	static Command lrange(const std::string& list, Int64 start = 0, Int64 stop = -1);
+		/// Creates and returns a LRANGE command. When start and stop is omitted an LRANGE
+		/// command will returned that returns all items of the list.
+
+	static Command lrem(const std::string& list, Int64 count, const std::string& value);
+		/// Creates and returns a LREM command.
+
+	static Command lset(const std::string& list, Int64 index, const std::string& value);
+		/// Creates and returns a LSET command.
+
+	static Command ltrim(const std::string& list, Int64 start = 0, Int64 stop = -1);
+		/// Creates and returns a LTRIM command.
+
+	static Command mget(const StringVec& keys);
+		/// Creates and returns a MGET command.
+
+	static Command mset(const std::map<std::string, std::string>& keyvalues, bool create = true);
+		/// Creates and returns a MSET or MSETNX (when create is false) command.
+
+	static Command sadd(const std::string& set, const std::string& value);
+		/// Creates and returns a SADD command.
+
+	static Command sadd(const std::string& set, const StringVec& values);
+		/// Creates and returns a SADD command.
+
+	static Command scard(const std::string& set);
+		/// Creates and returns a SCARD command.
+
+	static Command sdiff(const std::string& set1, const std::string& set2);
+		/// Creates and returns a SDIFF command.Creates and returns
+
+	static Command sdiff(const std::string& set, const StringVec& sets);
+		/// Creates and returns a SDIFF command.
+
+	static Command sdiffstore(const std::string& set, const std::string& set1, const std::string& set2);
+		/// Creates and returns a SDIFFSTORE command.
+
+	static Command sdiffstore(const std::string& set, const StringVec& sets);
+		/// Creates and returns a SDIFFSTORE command.
+
+	static Command set(const std::string& key, const std::string& value, bool overwrite = true, const Poco::Timespan& expireTime = 0, bool create = true);
+		/// Creates and returns a SET command to set the key with a value.
+
+	static Command set(const std::string& key, Int64 value, bool overwrite = true, const Poco::Timespan& expireTime = 0, bool create = true);
+		/// Creates and returns a SET command to set the key with a value.
+
+	static Command sinter(const std::string& set1, const std::string& set2);
+		/// Creates and returns a SINTER command.
+
+	static Command sinter(const std::string& set, const StringVec& sets);
+		/// Creates and returns a SINTER command.
+
+	static Command sinterstore(const std::string& set, const std::string& set1, const std::string& set2);
+		/// Creates and returns a SINTERSTORE command.
+
+	static Command sinterstore(const std::string& set, const StringVec& sets);
+		/// Creates and returns a SINTERSTORE command.
+
+	static Command sismember(const std::string& set, const std::string& member);
+		/// Creates and returns a SISMEMBER command.
+
+	static Command smembers(const std::string& set);
+		/// Creates and returns a SMEMBERS command.
+
+	static Command smove(const std::string& source, const std::string& destination, const std::string& member);
+		/// Creates and returns a SMOVE command.
+
+	static Command spop(const std::string& set, Int64 count = 0);
+		/// Creates and returns a SPOP command.
+
+	static Command srandmember(const std::string& set, Int64 count = 0);
+		/// Creates and returns a SRANDMEMBER command.
+
+	static Command srem(const std::string& set, const std::string& member);
+		/// Creates and returns a SREM command.
+
+	static Command srem(const std::string& set, const StringVec& members);
+		/// Creates and returns a SREM command.
+
+	static Command sunion(const std::string& set1, const std::string& set2);
+		/// Creates and returns a SUNION command.
+
+	static Command sunion(const std::string& set, const StringVec& sets);
+		/// Creates and returns a SUNION command.
+
+	static Command sunionstore(const std::string& set, const std::string& set1, const std::string& set2);
+		/// Creates and returns a SUNIONSTORE command.
+
+	static Command sunionstore(const std::string& set, const StringVec& sets);
+		/// Creates and returns a SUNIONSTORE command.
+
+	static Command rename(const std::string& key, const std::string& newName, bool overwrite = true);
+		/// Creates and returns a RENAME or RENAMENX when overwrite is false.
+
+	static Command rpop(const std::string& list);
+		/// Creates and returns a RPOP command.
+
+	static Command rpoplpush(const std::string& sourceList, const std::string& destinationList);
+		/// Creates and returns a RPOPLPUSH command.
+
+	static Command rpush(const std::string& list, const std::string& value, bool create = true);
+		/// Creates and returns a RPUSH or RPUSHX (when create is false) command.
+
+	static Command rpush(const std::string& list, const StringVec& value, bool create = true);
+		/// Creates and returns a RPUSH or RPUSHX (when create is false) command.
+
+	static Command expire(const std::string& key, Int64 seconds);
+		/// Creates and returns an EXPIRE command.
+
+	static Command ping();
+		/// Creates and returns a PING command.
+
+	static Command multi();
+		/// Creates and returns a MULTI command.
+
+	static Command exec();
+		/// Creates and returns a EXEC command.
+
+	static Command discard();
+		/// Creates and returns a DISCARD command.
+};
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_Command_INCLUDED
diff --git a/Poco/Redis/Error.h b/Poco/Redis/Error.h
new file mode 100644
index 0000000..ddc8155
--- /dev/null
+++ b/Poco/Redis/Error.h
@@ -0,0 +1,91 @@
+//
+// Error.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Error
+//
+// Definition of the Error class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_Error_INCLUDED
+#define Redis_Error_INCLUDED
+
+
+#include "Poco/Redis/Type.h"
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API Error
+	/// Represent a Redis error.
+{
+public:
+	Error();
+		/// Creates an empty Error.
+
+	Error(const std::string& message);
+		/// Creates an Error with the given message.
+
+	virtual ~Error();
+		/// Destroys the Error.
+
+	const std::string& getMessage() const;
+		/// Returns the error message.
+
+	void setMessage(const std::string& message);
+		/// Sets the error message.
+
+private:
+	std::string _message;
+};
+
+
+//
+// inlines
+//
+
+
+inline const std::string& Error::getMessage() const
+{
+	return _message;
+}
+
+
+inline void Error::setMessage(const std::string& message)
+{
+	_message = message;
+}
+
+
+template<>
+struct RedisTypeTraits<Error>
+{
+	enum { TypeId = RedisType::REDIS_ERROR };
+
+	static const char marker = '-';
+
+	static std::string toString(const Error& value)
+	{
+		return marker + value.getMessage()  + LineEnding::NEWLINE_CRLF;
+	}
+
+	static void read(RedisInputStream& input, Error& value)
+	{
+		value.setMessage(input.getline());
+	}
+};
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_Error_INCLUDED
diff --git a/Poco/Redis/Exception.h b/Poco/Redis/Exception.h
new file mode 100644
index 0000000..4454428
--- /dev/null
+++ b/Poco/Redis/Exception.h
@@ -0,0 +1,36 @@
+//
+// Exception.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Exception
+//
+// Definition of the Exception class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_Exception_INCLUDED
+#define Redis_Exception_INCLUDED
+
+
+#include "Poco/Redis/Redis.h"
+#include "Poco/Exception.h"
+#include <typeinfo>
+
+
+namespace Poco {
+namespace Redis {
+
+
+POCO_DECLARE_EXCEPTION(Redis_API, RedisException, Exception)
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_Exception_INCLUDED
diff --git a/Poco/Redis/PoolableConnectionFactory.h b/Poco/Redis/PoolableConnectionFactory.h
new file mode 100644
index 0000000..57dc24c
--- /dev/null
+++ b/Poco/Redis/PoolableConnectionFactory.h
@@ -0,0 +1,114 @@
+//
+// PoolableConnectionFactory.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  PoolableConnectionFactory
+//
+// Definition of the PoolableConnectionFactory class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_PoolableConnectionFactory_INCLUDED
+#define Redis_PoolableConnectionFactory_INCLUDED
+
+
+#include "Poco/Redis/Client.h"
+#include "Poco/ObjectPool.h"
+#include "Poco/Version.h"
+
+
+namespace Poco {
+
+
+template<>
+class PoolableObjectFactory<Redis::Client, Redis::Client::Ptr>
+	/// PoolableObjectFactory specialisation for Client. New connections
+	/// are created with the given address.
+{
+public:
+	PoolableObjectFactory(Net::SocketAddress& address):
+		_address(address)
+	{
+	}
+
+	PoolableObjectFactory(const std::string& address):
+		_address(address)
+	{
+	}
+
+	Redis::Client::Ptr createObject()
+	{
+		return new Redis::Client(_address);
+	}
+
+	bool validateObject(Redis::Client::Ptr pObject)
+	{
+		return true;
+	}
+
+	void activateObject(Redis::Client::Ptr pObject)
+	{
+	}
+
+	void deactivateObject(Redis::Client::Ptr pObject)
+	{
+	}
+
+	void destroyObject(Redis::Client::Ptr pObject)
+	{
+	}
+
+private:
+	Net::SocketAddress _address;
+};
+
+
+namespace Redis {
+
+
+class PooledConnection
+	/// Helper class for borrowing and returning a connection automatically from a pool.
+{
+public:
+	PooledConnection(ObjectPool<Client, Client::Ptr>& pool, long timeoutMilliseconds = 0) : _pool(pool)
+	{
+#if POCO_VERSION >= 0x01080000
+		_client = _pool.borrowObject(timeoutMilliseconds);
+#else
+		_client = _pool.borrowObject();
+#endif
+	}
+
+	virtual ~PooledConnection()
+	{
+		try
+		{
+			_pool.returnObject(_client);
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	operator Client::Ptr()
+	{
+		return _client;
+	}
+
+private:
+	ObjectPool<Client, Client::Ptr>& _pool;
+	Client::Ptr _client;
+};
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_PoolableConnectionFactory_INCLUDED
diff --git a/Poco/Redis/Redis.h b/Poco/Redis/Redis.h
new file mode 100644
index 0000000..bddc260
--- /dev/null
+++ b/Poco/Redis/Redis.h
@@ -0,0 +1,62 @@
+//
+// Redis.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Redis
+//
+// Basic definitions for the Poco Redis library.
+// This file must be the first file included by every other Redis
+// header file.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef RedisRedis_INCLUDED
+#define RedisRedis_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Redis_EXPORTS
+// symbol defined on the command line. This symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Redis_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(Redis_EXPORTS)
+		#define Redis_API __declspec(dllexport)
+	#else
+		#define Redis_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Redis_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Redis_API __attribute__ ((visibility ("default")))
+	#else
+		#define Redis_API
+	#endif
+#endif
+
+
+//
+// Automatically link Redis library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Redis_EXPORTS)
+		#pragma comment(lib, "PocoRedis" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // RedisRedis_INCLUDED
diff --git a/Poco/Redis/RedisEventArgs.h b/Poco/Redis/RedisEventArgs.h
new file mode 100644
index 0000000..6150078
--- /dev/null
+++ b/Poco/Redis/RedisEventArgs.h
@@ -0,0 +1,99 @@
+//
+// RedisEventArgs.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  RedisEventArgs
+//
+// Definition of the RedisEventArgs class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_RedisEventArgs_INCLUDED
+#define Redis_RedisEventArgs_INCLUDED
+
+
+#include "Poco/Redis/Type.h"
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API RedisEventArgs
+	/// Event arguments for AsyncReader events.
+{
+public:
+	RedisEventArgs(RedisType::Ptr message);
+		/// Creates the RedisEventArgs from the given message.
+
+	RedisEventArgs(Exception* e);
+		/// Creates the RedisEventArgs from the given Redis Exception.
+
+	~RedisEventArgs();
+		/// Destroys the RedisEventArgs.
+
+	RedisType::Ptr message() const;
+		/// Returns the message retrieved from the Redis server.
+		/// This can be a NULL pointer when this event is about an exception.
+
+	const Exception* exception() const;
+		/// Returns the exception if any, otherwise it returns null pointer.
+
+	void stop();
+		/// When called, the AsyncReader will stop.
+		///
+		/// Note: The AsyncReader will always stop when this is an exception
+		/// event. Use this for example for pub/sub when there are no
+		/// subcribers anymore.
+
+	bool isStopped() const;
+		/// Returns true when the AsyncReader will stop.
+
+private:
+	RedisType::Ptr _message;
+
+	Exception* _exception;
+
+	bool _stop;
+};
+
+
+//
+// inlines
+//
+
+
+inline RedisType::Ptr RedisEventArgs::message() const
+{
+	return _message;
+}
+
+
+inline const Exception* RedisEventArgs::exception() const
+{
+	return _exception;
+}
+
+
+inline bool RedisEventArgs::isStopped() const
+{
+	return _stop;
+}
+
+
+inline void RedisEventArgs::stop()
+{
+	_stop = true;
+}
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_RedisEventArgs_INCLUDED
diff --git a/Poco/Redis/RedisStream.h b/Poco/Redis/RedisStream.h
new file mode 100644
index 0000000..c750f38
--- /dev/null
+++ b/Poco/Redis/RedisStream.h
@@ -0,0 +1,114 @@
+//
+// RedisStream.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  RedisStream
+//
+// Definition of the RedisStream class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_RedisStream_INCLUDED
+#define Redis_RedisStream_INCLUDED
+
+
+#include "Poco/Redis/Redis.h"
+#include "Poco/BufferedStreamBuf.h"
+#include "Poco/Net/StreamSocket.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Redis {
+
+
+class RedisStreamBuf: public BufferedStreamBuf
+	/// BufferedStreamBuf for Redis.
+{
+public:
+	RedisStreamBuf(Net::StreamSocket& redis);
+		/// Constructor
+
+	~RedisStreamBuf();
+		/// Destructor
+
+	std::string readLine();
+		/// Reads a line from Redis (until \r\n is encountered).
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum
+	{
+		STREAM_BUFFER_SIZE = 1024
+	};
+
+	Net::StreamSocket& _redis;
+};
+
+
+class RedisIOS: public virtual std::ios
+{
+public:
+	RedisIOS(Net::StreamSocket& redis);
+		/// Creates the RedisIOS with the given socket.
+
+	~RedisIOS();
+		/// Destroys the RedisIOS.
+		///
+		/// Flushes the buffer, but does not close the socket.
+
+	RedisStreamBuf* rdbuf();
+		/// Returns a pointer to the internal RedisStreamBuf.
+
+	void close();
+		/// Flushes the stream.
+
+protected:
+	RedisStreamBuf _buf;
+};
+
+
+class Redis_API RedisOutputStream: public RedisIOS, public std::ostream
+	/// An output stream for writing to a Redis server.
+{
+public:
+	RedisOutputStream(Net::StreamSocket& redis);
+		/// Creates the RedisOutputStream with the given socket.
+
+	~RedisOutputStream();
+		/// Destroys the RedisOutputStream.
+		///
+		/// Flushes the buffer.
+};
+
+
+class Redis_API RedisInputStream: public RedisIOS, public std::istream
+	/// An input stream for reading from a Redis server.
+{
+public:
+	RedisInputStream(Net::StreamSocket& redis);
+		/// Creates the RedisInputStream with the given socket.
+
+	~RedisInputStream();
+		/// Destroys the RedisInputStream.
+
+	std::string getline();
+		/// Redis uses \r\n as delimiter. This getline version removes
+		/// the \r from the result.
+};
+
+
+} } // namespace Poco::Redis
+
+
+#endif // Redis_RedisStream_INCLUDED
diff --git a/Poco/Redis/Type.h b/Poco/Redis/Type.h
new file mode 100644
index 0000000..79c534f
--- /dev/null
+++ b/Poco/Redis/Type.h
@@ -0,0 +1,293 @@
+//
+// Type.h
+//
+// Library: Redis
+// Package: Redis
+// Module:  Type
+//
+// Definition of the Type class.
+//
+// Copyright (c) 2016, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Redis_Type_INCLUDED
+#define Redis_Type_INCLUDED
+
+
+#include "Poco/LineEndingConverter.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/NumberParser.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/Nullable.h"
+#include "Poco/Redis/Redis.h"
+#include "Poco/Redis/RedisStream.h"
+
+
+namespace Poco {
+namespace Redis {
+
+
+class Redis_API RedisType
+	/// Base class for all Redis types. This class makes it possible to store
+	/// element with different types in Array.
+{
+public:
+	enum Types 
+	{
+		REDIS_INTEGER,       /// Redis Integer
+		REDIS_SIMPLE_STRING, /// Redis Simple String
+		REDIS_BULK_STRING,   /// Redis Bulkstring
+		REDIS_ARRAY,         /// Redis Array
+		REDIS_ERROR          /// Redis Error
+	};
+
+	typedef SharedPtr<RedisType> Ptr;
+
+	RedisType();
+		/// Creates the RedisType.
+
+	virtual ~RedisType();
+		/// Destroys the RedisType.
+
+	bool isArray() const;
+		/// Returns true when the value is a Redis array.
+
+	bool isBulkString() const;
+		/// Returns true when the value is a Redis bulkstring.
+
+	bool isError() const;
+		/// Returns true when the value is a Redis error.
+
+	bool isInteger() const;
+		/// Returns true when the value is a Redis integer (64 bit integer).
+
+	bool isSimpleString() const;
+		/// Returns true when the value is a simple string.
+
+	virtual int type() const = 0;
+		/// Returns the type of the value.
+
+	virtual void read(RedisInputStream& input) = 0;
+		/// Reads the value from the stream.
+
+	virtual std::string toString() const = 0;
+		/// Converts the value to a RESP (REdis Serialization Protocol) string.
+
+	static RedisType::Ptr createRedisType(char marker);
+		/// Create a Redis type based on the marker:
+		///
+		///     - '+': a simple string (std::string)
+		///     - '-': an error (Error)
+		///     - '$': a bulk string (BulkString)
+		///     - '*': an array (Array)
+		///     - ':': a signed 64 bit integer (Int64)
+};
+
+
+//
+// inlines
+//
+
+
+inline bool RedisType::isArray() const
+{
+	return type() == REDIS_ARRAY;
+}
+
+
+inline bool RedisType::isBulkString() const
+{
+	return type() == REDIS_BULK_STRING;
+}
+
+
+inline bool RedisType::isError() const
+{
+	return type() == REDIS_ERROR;
+}
+
+
+inline bool RedisType::isInteger() const
+{
+	return type() == REDIS_INTEGER;
+}
+
+
+inline bool RedisType::isSimpleString() const
+{
+	return type() == REDIS_SIMPLE_STRING;
+}
+
+
+template<typename T>
+struct RedisTypeTraits
+{
+};
+
+
+template<>
+struct RedisTypeTraits<Int64>
+{
+	enum 
+	{
+		TypeId = RedisType::REDIS_INTEGER 
+	};
+
+	static const char marker = ':';
+
+	static std::string toString(const Int64& value)
+	{
+		return marker + NumberFormatter::format(value) + "\r\n";
+	}
+
+	static void read(RedisInputStream& input, Int64& value)
+	{
+		std::string number = input.getline();
+		value = NumberParser::parse64(number);
+	}
+};
+
+
+template<>
+struct RedisTypeTraits<std::string>
+{
+	enum 
+	{ 
+		TypeId = RedisType::REDIS_SIMPLE_STRING 
+	};
+
+	static const char marker = '+';
+
+	static std::string toString(const std::string& value)
+	{
+		return marker + value + LineEnding::NEWLINE_CRLF;
+	}
+
+	static void read(RedisInputStream& input, std::string& value)
+	{
+		value = input.getline();
+	}
+};
+
+
+typedef Nullable<std::string> BulkString;
+	/// A bulk string is a string that can contain a NULL value.
+	/// So, BulkString is a typedef for Nullable<std::string>.
+
+
+template<>
+struct RedisTypeTraits<BulkString>
+{
+	enum 
+	{ 
+		TypeId = RedisType::REDIS_BULK_STRING 
+	};
+
+	static const char marker = '$';
+
+	static std::string toString(const BulkString& value)
+	{
+		if ( value.isNull() )
+		{
+			return marker + std::string("-1") + LineEnding::NEWLINE_CRLF;
+		}
+		else
+		{
+			std::string s = value.value();
+			return marker
+				+ NumberFormatter::format(s.length())
+				+ LineEnding::NEWLINE_CRLF
+				+ s
+				+ LineEnding::NEWLINE_CRLF;
+		}
+	}
+
+	static void read(RedisInputStream& input, BulkString& value)
+	{
+		value.clear();
+
+		std::string line = input.getline();
+		int length = NumberParser::parse(line);
+
+		if ( length >= 0 )
+		{
+			std::string s;
+			s.resize(length, ' ');
+			input.read(&*s.begin(), length);
+			value.assign(s);
+
+			input.getline(); // Read and ignore /r/n
+		}
+	}
+};
+
+
+template<typename T>
+class Type: public RedisType
+	/// Template class for all Redis types. This class will use
+	/// RedisTypeTraits structure for calling the type specific code.
+{
+public:
+	Type()
+		/// Creates the Type.
+	{
+	}
+
+	Type(const T& t) : _value(t)
+		/// Creates the Type from another one.
+	{
+	}
+
+	Type(const Type& copy) : _value(copy._value)
+		/// Creates the Type by copying another one.
+	{
+	}
+
+	virtual ~Type()
+		/// Destroys the Type.
+	{
+	}
+
+	int type() const
+		/// Returns the type of the value
+	{
+		return RedisTypeTraits<T>::TypeId;
+	}
+
+	void read(RedisInputStream& socket)
+		/// Reads the value from the stream (RESP).
+	{
+		RedisTypeTraits<T>::read(socket, _value);
+	}
+
+	std::string toString() const
+		/// Converts the value to a string based on the RESP protocol.
+	{
+		return RedisTypeTraits<T>::toString(_value);
+	}
+
+	T& value()
+		/// Returns the value
+	{
+		return _value;
+	}
+
+	const T& value() const
+		/// Returns a const value
+	{
+		return _value;
+	}
+
+private:
+	T _value;
+};
+
+
+} } // namespace Poco/Redis
+
+
+#endif // Redis_Type_INCLUDED
diff --git a/Poco/RefCountedObject.h b/Poco/RefCountedObject.h
new file mode 100644
index 0000000..083cdfb
--- /dev/null
+++ b/Poco/RefCountedObject.h
@@ -0,0 +1,94 @@
+//
+// RefCountedObject.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  RefCountedObject
+//
+// Definition of the RefCountedObject class.
+//
+// Copyright (c) 2004-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RefCountedObject_INCLUDED
+#define Foundation_RefCountedObject_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/AtomicCounter.h"
+
+
+namespace Poco {
+
+
+class Foundation_API RefCountedObject
+	/// A base class for objects that employ
+	/// reference counting based garbage collection.
+	///
+	/// Reference-counted objects inhibit construction
+	/// by copying and assignment.
+{
+public:
+	RefCountedObject();
+		/// Creates the RefCountedObject.
+		/// The initial reference count is one.
+
+	void duplicate() const;
+		/// Increments the object's reference count.
+		
+	void release() const throw();
+		/// Decrements the object's reference count
+		/// and deletes the object if the count
+		/// reaches zero.
+		
+	int referenceCount() const;
+		/// Returns the reference count.
+
+protected:
+	virtual ~RefCountedObject();
+		/// Destroys the RefCountedObject.
+
+private:
+	RefCountedObject(const RefCountedObject&);
+	RefCountedObject& operator = (const RefCountedObject&);
+
+	mutable AtomicCounter _counter;
+};
+
+
+//
+// inlines
+//
+inline int RefCountedObject::referenceCount() const
+{
+	return _counter.value();
+}
+
+
+inline void RefCountedObject::duplicate() const
+{
+	++_counter;
+}
+
+
+inline void RefCountedObject::release() const throw()
+{
+	try
+	{
+		if (--_counter == 0) delete this;
+	}
+	catch (...)
+	{
+		poco_unexpected();
+	}
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RefCountedObject_INCLUDED
diff --git a/Poco/RegularExpression.h b/Poco/RegularExpression.h
new file mode 100644
index 0000000..638b99e
--- /dev/null
+++ b/Poco/RegularExpression.h
@@ -0,0 +1,247 @@
+//
+// RegularExpression.h
+//
+// Library: Foundation
+// Package: RegExp
+// Module:  RegularExpression
+//
+// Definitions of class RegularExpression.
+//
+// A wrapper class for Philip Hazel's PCRE - Perl Compatible Regular Expressions
+// library (http://www.pcre.org).
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RegularExpression_INCLUDED
+#define Foundation_RegularExpression_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API RegularExpression
+	/// A class for working with regular expressions.
+	/// Implemented using PCRE, the Perl Compatible
+	/// Regular Expressions library by Philip Hazel
+	/// (see http://www.pcre.org).
+{
+public:
+	enum Options // These must match the corresponding options in pcre.h!
+		/// Some of the following options can only be passed to the constructor;
+		/// some can be passed only to matching functions, and some can be used
+		/// everywhere.
+		/// 
+		///   * Options marked [ctor] can be passed to the constructor.
+		///   * Options marked [match] can be passed to match, extract, split and subst.
+		///   * Options marked [subst] can be passed to subst.
+		///
+		/// See the PCRE documentation for more information.
+	{
+		RE_CASELESS        = 0x00000001, /// case insensitive matching (/i) [ctor]
+		RE_MULTILINE       = 0x00000002, /// enable multi-line mode; affects ^ and $ (/m) [ctor]
+		RE_DOTALL          = 0x00000004, /// dot matches all characters, including newline (/s) [ctor]
+		RE_EXTENDED        = 0x00000008, /// totally ignore whitespace (/x) [ctor]
+		RE_ANCHORED        = 0x00000010, /// treat pattern as if it starts with a ^ [ctor, match]
+		RE_DOLLAR_ENDONLY  = 0x00000020, /// dollar matches end-of-string only, not last newline in string [ctor]
+		RE_EXTRA           = 0x00000040, /// enable optional PCRE functionality [ctor]
+		RE_NOTBOL          = 0x00000080, /// circumflex does not match beginning of string [match]
+		RE_NOTEOL          = 0x00000100, /// $ does not match end of string [match]
+		RE_UNGREEDY        = 0x00000200, /// make quantifiers ungreedy [ctor]
+		RE_NOTEMPTY        = 0x00000400, /// empty string never matches [match]
+		RE_UTF8            = 0x00000800, /// assume pattern and subject is UTF-8 encoded [ctor]
+		RE_NO_AUTO_CAPTURE = 0x00001000, /// disable numbered capturing parentheses [ctor, match]
+		RE_NO_UTF8_CHECK   = 0x00002000, /// do not check validity of UTF-8 code sequences [match]
+		RE_FIRSTLINE       = 0x00040000, /// an  unanchored  pattern  is  required  to  match
+		                                 /// before  or  at  the  first  newline  in  the subject string, 
+		                                 /// though the matched text may continue over the newline [ctor]
+		RE_DUPNAMES        = 0x00080000, /// names used to identify capturing  subpatterns  need not be unique [ctor]
+		RE_NEWLINE_CR      = 0x00100000, /// assume newline is CR ('\r'), the default [ctor] 
+		RE_NEWLINE_LF      = 0x00200000, /// assume newline is LF ('\n') [ctor]
+		RE_NEWLINE_CRLF    = 0x00300000, /// assume newline is CRLF ("\r\n") [ctor]
+		RE_NEWLINE_ANY     = 0x00400000, /// assume newline is any valid Unicode newline character [ctor]
+		RE_NEWLINE_ANYCRLF = 0x00500000, /// assume newline is any of CR, LF, CRLF [ctor]
+		RE_GLOBAL          = 0x10000000, /// replace all occurences (/g) [subst]
+		RE_NO_VARS         = 0x20000000  /// treat dollar in replacement string as ordinary character [subst]
+	};
+	
+	struct Match
+	{
+		std::string::size_type offset; /// zero based offset (std::string::npos if subexpr does not match)
+		std::string::size_type length; /// length of substring
+	};
+	typedef std::vector<Match> MatchVec;
+	
+	RegularExpression(const std::string& pattern, int options = 0, bool study = true);
+		/// Creates a regular expression and parses the given pattern.
+		/// If study is true, the pattern is analyzed and optimized. This
+		/// is mainly useful if the pattern is used more than once.
+		/// For a description of the options, please see the PCRE documentation.
+		/// Throws a RegularExpressionException if the patter cannot be compiled.
+		
+	~RegularExpression();
+		/// Destroys the regular expression.
+
+	int match(const std::string& subject, Match& mtch, int options = 0) const;
+		/// Matches the given subject string against the pattern. Returns the position
+		/// of the first captured substring in mtch.
+		/// If no part of the subject matches the pattern, mtch.offset is std::string::npos and
+		/// mtch.length is 0.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+
+	int match(const std::string& subject, std::string::size_type offset, Match& mtch, int options = 0) const;
+		/// Matches the given subject string, starting at offset, against the pattern. 
+		/// Returns the position of the captured substring in mtch.
+		/// If no part of the subject matches the pattern, mtch.offset is std::string::npos and
+		/// mtch.length is 0.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+
+	int match(const std::string& subject, std::string::size_type offset, MatchVec& matches, int options = 0) const;
+		/// Matches the given subject string against the pattern. 
+		/// The first entry in matches contains the position of the captured substring.
+		/// The following entries identify matching subpatterns. See the PCRE documentation
+		/// for a more detailed explanation.
+		/// If no part of the subject matches the pattern, matches is empty.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+
+	bool match(const std::string& subject, std::string::size_type offset = 0) const;
+		/// Returns true if and only if the subject matches the regular expression.
+		///
+		/// Internally, this method sets the RE_ANCHORED and RE_NOTEMPTY options for
+		/// matching, which means that the empty string will never match and
+		/// the pattern is treated as if it starts with a ^.
+
+	bool match(const std::string& subject, std::string::size_type offset, int options) const;
+		/// Returns true if and only if the subject matches the regular expression.
+
+	bool operator == (const std::string& subject) const;
+		/// Returns true if and only if the subject matches the regular expression.
+		///
+		/// Internally, this method sets the RE_ANCHORED and RE_NOTEMPTY options for
+		/// matching, which means that the empty string will never match and
+		/// the pattern is treated as if it starts with a ^.
+
+	bool operator != (const std::string& subject) const;
+		/// Returns true if and only if the subject does not match the regular expression.
+		///
+		/// Internally, this method sets the RE_ANCHORED and RE_NOTEMPTY options for
+		/// matching, which means that the empty string will never match and
+		/// the pattern is treated as if it starts with a ^.
+
+	int extract(const std::string& subject, std::string& str, int options = 0) const;
+		/// Matches the given subject string against the pattern. 
+		/// Returns the captured string.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+
+	int extract(const std::string& subject, std::string::size_type offset, std::string& str, int options = 0) const;
+		/// Matches the given subject string, starting at offset, against the pattern. 
+		/// Returns the captured string.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+
+	int split(const std::string& subject, std::vector<std::string>& strings, int options = 0) const;
+		/// Matches the given subject string against the pattern. 
+		/// The first entry in captured is the captured substring.
+		/// The following entries contain substrings matching subpatterns. See the PCRE documentation
+		/// for a more detailed explanation.
+		/// If no part of the subject matches the pattern, captured is empty.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+
+	int split(const std::string& subject, std::string::size_type offset, std::vector<std::string>& strings, int options = 0) const;
+		/// Matches the given subject string against the pattern. 
+		/// The first entry in captured is the captured substring.
+		/// The following entries contain substrings matching subpatterns. See the PCRE documentation
+		/// for a more detailed explanation.
+		/// If no part of the subject matches the pattern, captured is empty.
+		/// Throws a RegularExpressionException in case of an error.
+		/// Returns the number of matches.
+	
+	int subst(std::string& subject, const std::string& replacement, int options = 0) const;
+		/// Substitute in subject all matches of the pattern with replacement.
+		/// If RE_GLOBAL is specified as option, all matches are replaced. Otherwise,
+		/// only the first match is replaced.
+		/// Occurrences of $<n> (for example, $1, $2, ...) in replacement are replaced
+		/// with the corresponding captured string. $0 is the original subject string.
+		/// Returns the number of replaced occurrences.
+
+	int subst(std::string& subject, std::string::size_type offset, const std::string& replacement, int options = 0) const;
+		/// Substitute in subject all matches of the pattern with replacement,
+		/// starting at offset.
+		/// If RE_GLOBAL is specified as option, all matches are replaced. Otherwise,
+		/// only the first match is replaced.
+		/// Unless RE_NO_VARS is specified, occurrences of $<n> (for example, $0, $1, $2, ... $9)
+		/// in replacement are replaced with the corresponding captured string. 
+		/// $0 is the captured substring. $1 ... $n are the substrings matching the subpatterns.
+		/// Returns the number of replaced occurrences.
+
+	static bool match(const std::string& subject, const std::string& pattern, int options = 0);
+		/// Matches the given subject string against the regular expression given in pattern,
+		/// using the given options.
+
+protected:
+	std::string::size_type substOne(std::string& subject, std::string::size_type offset, const std::string& replacement, int options) const;
+
+private:
+	// Note: to avoid a dependency on the pcre.h header the following are 
+	// declared as void* and casted to the correct type in the implementation file.
+	void* _pcre;  // Actual type is pcre*
+	void* _extra; // Actual type is struct pcre_extra*
+	
+	static const int OVEC_SIZE;
+	
+	RegularExpression();
+	RegularExpression(const RegularExpression&);
+	RegularExpression& operator = (const RegularExpression&);
+};
+
+
+//
+// inlines
+//
+inline int RegularExpression::match(const std::string& subject, Match& mtch, int options) const
+{
+	return match(subject, 0, mtch, options);
+}
+
+
+inline int RegularExpression::split(const std::string& subject, std::vector<std::string>& strings, int options) const
+{
+	return split(subject, 0, strings, options);
+}
+
+
+inline int RegularExpression::subst(std::string& subject, const std::string& replacement, int options) const
+{
+	return subst(subject, 0, replacement, options);
+}
+
+
+inline bool RegularExpression::operator == (const std::string& subject) const
+{
+	return match(subject);
+}
+
+
+inline bool RegularExpression::operator != (const std::string& subject) const
+{
+	return !match(subject);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RegularExpression_INCLUDED
diff --git a/Poco/RotateStrategy.h b/Poco/RotateStrategy.h
new file mode 100644
index 0000000..82c331f
--- /dev/null
+++ b/Poco/RotateStrategy.h
@@ -0,0 +1,165 @@
+//
+// RotateStrategy.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  FileChannel
+//
+// Definition of the RotateStrategy class and subclasses.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RotateStrategy_INCLUDED
+#define Foundation_RotateStrategy_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timespan.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Exception.h"
+#include "Poco/LogFile.h"
+#include "Poco/StringTokenizer.h"
+#include "Poco/DateTimeParser.h"
+#include "Poco/NumberParser.h"
+
+
+namespace Poco {
+
+
+class Foundation_API RotateStrategy
+	/// The RotateStrategy is used by LogFile to determine when
+	/// a file must be rotated.
+{
+public:
+	RotateStrategy();
+	virtual ~RotateStrategy();
+
+	virtual bool mustRotate(LogFile* pFile) = 0;
+		/// Returns true if the given log file must
+		/// be rotated, false otherwise.
+		
+private:
+	RotateStrategy(const RotateStrategy&);
+	RotateStrategy& operator = (const RotateStrategy&);
+};
+
+
+template <class DT>
+class RotateAtTimeStrategy: public RotateStrategy
+	/// The file is rotated at specified [day,][hour]:minute
+{
+public:
+	RotateAtTimeStrategy(const std::string& rtime):
+		_day(-1), 
+		_hour(-1), 
+		_minute(0)
+	{
+		if (rtime.empty()) 
+			throw InvalidArgumentException("Rotation time must be specified.");
+
+		if ((rtime.find(',') != rtime.npos) && (rtime.find(':') == rtime.npos)) 
+			throw InvalidArgumentException("Invalid rotation time specified.");
+
+		StringTokenizer timestr(rtime, ",:", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY);
+		int index = 0;
+
+		switch (timestr.count())
+		{
+		case 3: // day,hh:mm
+			{
+				std::string::const_iterator it = timestr[index].begin();
+				_day = DateTimeParser::parseDayOfWeek(it, timestr[index].end());
+				++index;
+			}
+		case 2: // hh:mm
+			_hour = NumberParser::parse(timestr[index]);
+			++index;
+		case 1: // mm
+			_minute = NumberParser::parse(timestr[index]);
+			break;
+		default:
+			throw InvalidArgumentException("Invalid rotation time specified.");
+		}
+		getNextRollover();
+	}
+	
+	~RotateAtTimeStrategy()
+	{
+	}
+	
+	bool mustRotate(LogFile* /*pFile*/)
+	{
+		if (DT() >= _threshold)
+		{
+			getNextRollover();
+			return true;
+		}
+		return false;
+	}
+
+private:
+	void getNextRollover()
+	{
+		Timespan tsp(0, 0, 1, 0, 1000); // 0,00:01:00.001
+		do
+		{
+			_threshold += tsp;
+		}
+		while (!(_threshold.minute() == _minute &&
+		        (-1 == _hour || _threshold.hour() == _hour) && 
+		        (-1 == _day  || _threshold.dayOfWeek() == _day)));
+		// round to :00.0 seconds
+		_threshold.assign(_threshold.year(), _threshold.month(), _threshold.day(), _threshold.hour(), _threshold.minute());
+	}
+
+	DT  _threshold;
+	int _day;
+	int _hour;
+	int _minute;
+};
+
+
+class Foundation_API RotateByIntervalStrategy: public RotateStrategy
+	/// The file is rotated when the log file 
+	/// exceeds a given age.
+	///
+	/// For this to work reliably across all platforms and file systems
+	/// (there are severe issues on most platforms finding out the real
+	/// creation date of a file), the creation date of the file is
+	/// written into the log file as the first entry.
+{
+public:
+	RotateByIntervalStrategy(const Timespan& span);
+	~RotateByIntervalStrategy();
+	bool mustRotate(LogFile* pFile);
+
+private:
+	Timespan _span;
+	Timestamp _lastRotate;
+	static const std::string ROTATE_TEXT;
+};
+
+
+class Foundation_API RotateBySizeStrategy: public RotateStrategy
+	/// The file is rotated when the log file
+	/// exceeds a given size.
+{
+public:
+	RotateBySizeStrategy(UInt64 size);
+	~RotateBySizeStrategy();
+	bool mustRotate(LogFile* pFile);
+
+private:
+	UInt64 _size;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RotateStrategy_INCLUDED
diff --git a/Poco/Runnable.h b/Poco/Runnable.h
new file mode 100644
index 0000000..c87a628
--- /dev/null
+++ b/Poco/Runnable.h
@@ -0,0 +1,45 @@
+//
+// Runnable.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the Runnable class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Runnable_INCLUDED
+#define Foundation_Runnable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Runnable
+	/// The Runnable interface with the run() method
+	/// must be implemented by classes that provide
+	/// an entry point for a thread.
+{
+public:	
+	Runnable();
+	virtual ~Runnable();
+	
+	virtual void run() = 0;
+		/// Do whatever the thread needs to do. Must
+		/// be overridden by subclasses.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Runnable_INCLUDED
diff --git a/Poco/RunnableAdapter.h b/Poco/RunnableAdapter.h
new file mode 100644
index 0000000..571871b
--- /dev/null
+++ b/Poco/RunnableAdapter.h
@@ -0,0 +1,78 @@
+//
+// RunnableAdapter.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the RunnableAdapter template class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_RunnableAdapter_INCLUDED
+#define Foundation_RunnableAdapter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+
+
+namespace Poco {
+
+
+template <class C>
+class RunnableAdapter: public Runnable
+	/// This adapter simplifies using ordinary methods as
+	/// targets for threads.
+	/// Usage:
+	///    RunnableAdapter<MyClass> ra(myObject, &MyObject::doSomething));
+	///    Thread thr;
+	///    thr.Start(ra);
+	///
+	/// For using a freestanding or static member function as a thread
+	/// target, please see the ThreadTarget class.
+{
+public:
+	typedef void (C::*Callback)();
+	
+	RunnableAdapter(C& object, Callback method): _pObject(&object), _method(method)
+	{
+	}
+	
+	RunnableAdapter(const RunnableAdapter& ra): _pObject(ra._pObject), _method(ra._method)
+	{
+	}
+
+	~RunnableAdapter()
+	{
+	}
+
+	RunnableAdapter& operator = (const RunnableAdapter& ra)
+	{
+		_pObject = ra._pObject;
+		_method  = ra._method;
+		return *this;
+	}
+
+	void run()
+	{
+		(_pObject->*_method)();
+	}
+	
+private:
+	RunnableAdapter();
+
+	C*       _pObject;
+	Callback _method;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_RunnableAdapter_INCLUDED
diff --git a/Poco/SAX/Attributes.h b/Poco/SAX/Attributes.h
new file mode 100644
index 0000000..d7ba912
--- /dev/null
+++ b/Poco/SAX/Attributes.h
@@ -0,0 +1,120 @@
+//
+// Attributes.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX2 Attributes Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_Attributes_INCLUDED
+#define SAX_Attributes_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Attributes
+	/// Interface for a list of XML attributes.
+	/// This interface allows access to a list of attributes in three different ways:
+	///   1.by attribute index; 
+	///   2.by Namespace-qualified name; or 
+	///   3.by qualified (prefixed) name. 
+	/// 
+	/// The list will not contain attributes that were declared #IMPLIED but not 
+	/// specified in the start tag. It will also not contain
+	/// attributes used as Namespace declarations (xmlns*) unless the 
+	/// http://xml.org/sax/features/namespace-prefixes
+	/// feature is set to true (it is false by default).
+	/// 
+	/// If the namespace-prefixes feature (see above) is false, access by 
+	/// qualified name may not be available; if the
+	/// http://xml.org/sax/features/namespaces feature is false, access by 
+	/// Namespace-qualified names may not be available.
+	/// This interface replaces the now-deprecated SAX1 AttributeList interface, 
+	/// which does not contain Namespace support. In
+	/// addition to Namespace support, it adds the getIndex methods (below).
+	/// The order of attributes in the list is unspecified, and will vary from 
+	/// implementation to implementation.
+{
+public:
+	virtual int getIndex(const XMLString& name) const = 0;
+		/// Look up the index of an attribute by a qualified name.
+
+	virtual int getIndex(const XMLString& namespaceURI, const XMLString& localName) const = 0;
+		/// Look up the index of an attribute by a namspace name.
+
+	virtual int getLength() const = 0;
+		/// Return the number of attributes in the list.
+		///
+		/// Once you know the number of attributes, you can iterate through the list.
+		
+	virtual const XMLString& getLocalName(int i) const = 0;
+		/// Look up a local attribute name by index.
+
+	virtual const XMLString& getQName(int i) const = 0;
+		/// Look up a qualified attribute name by index.
+
+	virtual const XMLString& getType(int i) const = 0;
+		/// Look up an attribute type by index.
+		///
+		/// The attribute type is one of the strings "CDATA", "ID", "IDREF", "IDREFS", "NMTOKEN", 
+		/// "NMTOKENS", "ENTITY", "ENTITIES", or "NOTATION" (always in upper case).
+		///
+		/// If the parser has not read a declaration for the attribute, or if the parser does not 
+		/// report attribute types, then it must return the value "CDATA" as stated in the XML 1.0 
+		/// Recommendation (clause 3.3.3, "Attribute-Value Normalization").
+		/// 
+		/// For an enumerated attribute that is not a notation, the parser will report the type 
+		/// as "NMTOKEN".
+
+	virtual const XMLString& getType(const XMLString& qname) const = 0;
+		/// Look up an attribute type by a qualified name.
+		///
+		/// See getType(int) for a description of the possible types.
+
+	virtual const XMLString& getType(const XMLString& namespaceURI, const XMLString& localName) const = 0;
+		/// Look up an attribute type by a namespace name.
+		///
+		/// See getType(int) for a description of the possible types.
+
+	virtual const XMLString& getValue(int i) const = 0;
+		/// Look up an attribute value by index.
+		///
+		/// If the attribute value is a list of tokens (IDREFS, ENTITIES, or NMTOKENS), the tokens 
+		/// will be concatenated into a single string with each token separated by a single space.
+
+	virtual const XMLString& getValue(const XMLString& qname) const = 0;
+		/// Look up an attribute value by a qualified name.
+		///
+		/// See getValue(int) for a description of the possible values.
+
+	virtual const XMLString& getValue(const XMLString& uri, const XMLString& localName) const = 0;
+		/// Look up an attribute value by a namespace name.
+		///
+		/// See getValue(int) for a description of the possible values.
+
+	virtual const XMLString& getURI(int i) const = 0;
+		/// Look up a namespace URI by index.
+
+protected:
+	virtual ~Attributes();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_Attributes_INCLUDED
diff --git a/Poco/SAX/AttributesImpl.h b/Poco/SAX/AttributesImpl.h
new file mode 100644
index 0000000..8ce2d52
--- /dev/null
+++ b/Poco/SAX/AttributesImpl.h
@@ -0,0 +1,296 @@
+//
+// AttributesImpl.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// Implementation of the SAX2 Attributes Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_AttributesImpl_INCLUDED
+#define SAX_AttributesImpl_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/Attributes.h"
+#include <vector>
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API AttributesImpl: public Attributes
+	/// This class provides a default implementation of the SAX2 Attributes interface, 
+	/// with the addition of manipulators so that the list can be modified or reused.
+	/// 
+	/// There are two typical uses of this class:
+	///     1. to take a persistent snapshot of an Attributes object in a startElement event; or
+	///     2. to construct or modify an Attributes object in a SAX2 driver or filter.
+{
+public:
+	struct Attribute
+	{
+		XMLString localName;
+		XMLString namespaceURI;
+		XMLString qname;
+		XMLString value;
+		XMLString type;
+		bool      specified;
+	};
+	typedef std::vector<Attribute> AttributeVec;
+	typedef AttributeVec::const_iterator iterator;
+
+	AttributesImpl();
+		/// Creates the AttributesImpl.
+		
+	AttributesImpl(const Attributes& attributes);
+		/// Creates the AttributesImpl by copying another one.
+
+	AttributesImpl(const AttributesImpl& attributes);
+		/// Creates the AttributesImpl by copying another one.
+
+	~AttributesImpl();
+		/// Destroys the AttributesImpl.
+
+	AttributesImpl& operator = (const AttributesImpl& attributes);
+		/// Assignment operator.
+
+	int getIndex(const XMLString& name) const;
+	int getIndex(const XMLString& namespaceURI, const XMLString& localName) const;
+	int getLength() const;
+	const XMLString& getLocalName(int i) const;
+	const XMLString& getQName(int i) const;
+	const XMLString& getType(int i) const;
+	const XMLString& getType(const XMLString& qname) const;
+	const XMLString& getType(const XMLString& namespaceURI, const XMLString& localName) const;
+	const XMLString& getValue(int i) const;
+	const XMLString& getValue(const XMLString& qname) const;
+	const XMLString& getValue(const XMLString& namespaceURI, const XMLString& localName) const;
+	const XMLString& getURI(int i) const;
+
+	bool isSpecified(int i) const;
+		/// Returns true unless the attribute value was provided by DTD defaulting.
+		/// Extension from Attributes2 interface.
+
+	bool isSpecified(const XMLString& qname) const;
+		/// Returns true unless the attribute value was provided by DTD defaulting.
+		/// Extension from Attributes2 interface.
+
+	bool isSpecified(const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns true unless the attribute value was provided by DTD defaulting.
+		/// Extension from Attributes2 interface.
+
+	void setValue(int i, const XMLString& value);
+		/// Sets the value of an attribute.
+
+	void setValue(const XMLString& qname, const XMLString& value);
+		/// Sets the value of an attribute.
+
+	void setValue(const XMLString& namespaceURI, const XMLString& localName, const XMLString& value);
+		/// Sets the value of an attribute.
+
+	void setAttributes(const Attributes& attributes);
+		/// Copies the attributes from another Attributes object.
+
+	void setAttribute(int i, const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const XMLString& type, const XMLString& value);
+		/// Sets an attribute.
+
+	void addAttribute(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const XMLString& type, const XMLString& value);
+		/// Adds an attribute to the end of the list.
+
+	void addAttribute(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const XMLString& type, const XMLString& value, bool specified);
+		/// Adds an attribute to the end of the list.
+
+	void addAttribute(const XMLChar* namespaceURI, const XMLChar* localName, const XMLChar* qname, const XMLChar* type, const XMLChar* value, bool specified);
+		/// Adds an attribute to the end of the list.
+
+	Attribute& addAttribute();
+		/// Add an (empty) attribute to the end of the list.
+		/// For internal use only.
+		/// The returned Attribute element must be filled by the caller.
+
+	void removeAttribute(int i);
+		/// Removes an attribute.
+
+	void removeAttribute(const XMLString& qname);
+		/// Removes an attribute.
+
+	void removeAttribute(const XMLString& namespaceURI, const XMLString& localName);
+		/// Removes an attribute.
+
+	void clear();
+		/// Removes all attributes.
+		
+	void reserve(std::size_t capacity);
+		/// Reserves capacity in the internal vector.
+
+	void setLocalName(int i, const XMLString& localName);
+		/// Sets the local name of an attribute.
+
+	void setQName(int i, const XMLString& qname);
+		/// Sets the qualified name of an attribute.
+
+	void setType(int i, const XMLString& type);
+		/// Sets the type of an attribute.
+
+	void setURI(int i, const XMLString& namespaceURI);
+		/// Sets the namespace URI of an attribute.
+
+	iterator begin() const;
+		/// Iterator support.
+		
+	iterator end() const;
+		/// Iterator support.
+
+protected:	
+	Attribute* find(const XMLString& qname) const;
+	Attribute* find(const XMLString& namespaceURI, const XMLString& localName) const;
+
+private:
+	AttributeVec _attributes;
+	Attribute _empty;
+};
+
+
+//
+// inlines
+//
+inline AttributesImpl::iterator AttributesImpl::begin() const
+{
+	return _attributes.begin();
+}
+
+
+inline AttributesImpl::iterator AttributesImpl::end() const
+{
+	return _attributes.end();
+}
+
+
+inline AttributesImpl::Attribute& AttributesImpl::addAttribute()
+{
+	_attributes.push_back(_empty);
+	return _attributes.back();
+}
+
+
+inline int AttributesImpl::getLength() const
+{
+	return (int) _attributes.size();
+}
+
+
+inline const XMLString& AttributesImpl::getLocalName(int i) const
+{
+	poco_assert (0 <= i && i < static_cast<int>(_attributes.size()));
+	return _attributes[i].localName;
+}
+
+
+inline const XMLString& AttributesImpl::getQName(int i) const
+{
+	poco_assert (0 <= i && i < static_cast<int>(_attributes.size()));
+	return _attributes[i].qname;
+}
+
+
+inline const XMLString& AttributesImpl::getType(int i) const
+{
+	poco_assert (0 <= i && i < static_cast<int>(_attributes.size()));
+	return _attributes[i].type;
+}
+
+
+inline const XMLString& AttributesImpl::getType(const XMLString& qname) const
+{
+	Attribute* pAttr = find(qname);
+	if (pAttr)
+		return pAttr->type;
+	else
+		return _empty.type;
+}
+
+
+inline const XMLString& AttributesImpl::getType(const XMLString& namespaceURI, const XMLString& localName) const
+{
+	Attribute* pAttr = find(namespaceURI, localName);
+	if (pAttr)
+		return pAttr->type;
+	else
+		return _empty.type;
+}
+
+
+inline const XMLString& AttributesImpl::getValue(int i) const
+{
+	poco_assert (0 <= i && i < static_cast<int>(_attributes.size()));
+	return _attributes[i].value;
+}
+
+
+inline const XMLString& AttributesImpl::getValue(const XMLString& qname) const
+{
+	Attribute* pAttr = find(qname);
+	if (pAttr)
+		return pAttr->value;
+	else
+		return _empty.value;
+}
+
+
+inline const XMLString& AttributesImpl::getValue(const XMLString& namespaceURI, const XMLString& localName) const
+{
+	Attribute* pAttr = find(namespaceURI, localName);
+	if (pAttr)
+		return pAttr->value;
+	else
+		return _empty.value;
+}
+
+
+inline const XMLString& AttributesImpl::getURI(int i) const
+{
+	poco_assert (0 <= i && i < static_cast<int>(_attributes.size()));
+	return _attributes[i].namespaceURI;
+}
+
+
+inline bool AttributesImpl::isSpecified(int i) const
+{
+	poco_assert (0 <= i && i < static_cast<int>(_attributes.size()));
+	return _attributes[i].specified;
+}
+
+
+inline bool AttributesImpl::isSpecified(const XMLString& qname) const
+{
+	Attribute* pAttr = find(qname);
+	if (pAttr)
+		return pAttr->specified;
+	else
+		return false;
+}
+
+
+inline bool AttributesImpl::isSpecified(const XMLString& namespaceURI, const XMLString& localName) const
+{
+	Attribute* pAttr = find(namespaceURI, localName);
+	if (pAttr)
+		return pAttr->specified;
+	else
+		return false;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_AttributesImpl_INCLUDED
diff --git a/Poco/SAX/ContentHandler.h b/Poco/SAX/ContentHandler.h
new file mode 100644
index 0000000..58f2a25
--- /dev/null
+++ b/Poco/SAX/ContentHandler.h
@@ -0,0 +1,240 @@
+//
+// ContentHandler.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX2 ContentHandler Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_ContentHandler_INCLUDED
+#define SAX_ContentHandler_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class Locator;
+class Attributes;
+
+
+class XML_API ContentHandler
+	/// Receive notification of the logical content of a document. 
+	///
+	/// This is the main interface that most SAX applications implement: if the
+	/// application needs to be informed of basic parsing events, it implements
+	/// this interface and registers an instance with the SAX parser using the setContentHandler
+	/// method. The parser uses the instance to report basic document-related events
+	/// like the start and end of elements and character data.
+	/// 
+	/// The order of events in this interface is very important, and mirrors the
+	/// order of information in the document itself. For example, all of an element's
+	/// content (character data, processing instructions, and/or subelements) will
+	/// appear, in order, between the startElement event and the corresponding endElement
+	/// event.
+	/// 
+	/// This interface is similar to the now-deprecated SAX 1.0 DocumentHandler
+	/// interface, but it adds support for Namespaces and for reporting skipped
+	/// entities (in non-validating XML processors).
+	/// Receive notification of the logical content of a document.
+{
+public:
+	virtual void setDocumentLocator(const Locator* loc) = 0;
+		/// Receive an object for locating the origin of SAX document events.
+		/// 
+		/// SAX parsers are strongly encouraged (though not absolutely required) to
+		/// supply a locator: if it does so, it must supply the locator to the application
+		/// by invoking this method before invoking any of the other methods in the
+		/// ContentHandler interface.
+		/// 
+		/// The locator allows the application to determine the end position of any
+		/// document-related event, even if the parser is not reporting an error. Typically,
+		/// the application will use this information for reporting its own errors (such
+		/// as character content that does not match an application's business rules).
+		/// The information returned by the locator is probably not sufficient for use
+		/// with a search engine.
+		/// 
+		/// Note that the locator will return correct information only during the invocation
+		/// SAX event callbacks after startDocument returns and before endDocument is
+		/// called. The application should not attempt to use it at any other time.
+
+	virtual void startDocument() = 0;
+		/// Receive notification of the beginning of a document.
+		///
+		/// The SAX parser calls this function one time before calling all other 
+		/// functions of this class (except SetDocumentLocator).
+
+	virtual void endDocument() = 0;
+		/// Receive notification of the end of a document.
+		///
+		/// The SAX parser will invoke this method only once, and it will be the last
+		/// method invoked during the parse. The parser shall not invoke this method
+		/// until it has either abandoned parsing (because of an unrecoverable error)
+		/// or reached the end of input.
+
+	virtual void startElement(const XMLString& uri, const XMLString& localName, const XMLString& qname, const Attributes& attrList) = 0;
+		/// Receive notification of the beginning of an element.
+		/// 
+		/// The Parser will invoke this method at the beginning of every element in
+		/// the XML document; there will be a corresponding endElement event for every
+		/// startElement event (even when the element is empty). All of the element's
+		/// content will be reported, in order, before the corresponding endElement
+		/// event.
+		/// 
+		/// This event allows up to three name components for each element:
+		///    1. the Namespace URI;
+		///    2. the local name; and
+		///    3. the qualified (prefixed) name.
+		/// 
+		/// Any or all of these may be provided, depending on the values of the http://xml.org/sax/features/namespaces
+		/// and the http://xml.org/sax/features/namespace-prefixes properties:
+		///     * the Namespace URI and local name are required when the namespaces
+		///       property is true (the default), and are optional when the namespaces property
+		///       is false (if one is specified, both must be);
+		///     * the qualified name is required when the namespace-prefixes property
+		///       is true, and is optional when the namespace-prefixes property is false (the
+		///       default).
+		/// 
+		/// Note that the attribute list provided will contain only attributes with
+		/// explicit values (specified or defaulted): #IMPLIED attributes will be omitted.
+		/// The attribute list will contain attributes used for Namespace declarations
+		/// (xmlns* attributes) only if the http://xml.org/sax/features/namespace-prefixes
+		/// property is true (it is false by default, and support for a true value is
+		/// optional).
+		/// 
+		/// Like characters(), attribute values may have characters that need more than
+		/// one char value.
+
+	virtual void endElement(const XMLString& uri, const XMLString& localName, const XMLString& qname) = 0;
+		/// Receive notification of the end of an element.
+		/// 
+		/// The SAX parser will invoke this method at the end of every element in the
+		/// XML document; there will be a corresponding startElement event for every
+		/// endElement event (even when the element is empty).
+		/// 
+		/// For information on the names, see startElement.
+
+	virtual void characters(const XMLChar ch[], int start, int length) = 0;
+		/// Receive notification of character data.
+		/// 
+		/// The Parser will call this method to report each chunk of character data.
+		/// SAX parsers may return all contiguous character data in a single chunk,
+		/// or they may split it into several chunks; however, all of the characters
+		/// in any single event must come from the same external entity so that the
+		/// Locator provides useful information.
+		/// 
+		/// The application must not attempt to read from the array outside of the specified
+		/// range.
+		/// 
+		/// Individual characters may consist of more than one XMLChar value. There
+		/// are three important cases where this happens, because characters can't be
+		/// represented in just sixteen bits. In one case, characters are represented
+		/// in a Surrogate Pair, using two special Unicode values. Such characters are
+		/// in the so-called "Astral Planes", with a code point above U+FFFF. A second
+		/// case involves composite characters, such as a base character combining with
+		/// one or more accent characters. And most important, if XMLChar is a plain
+		/// char, characters are encoded in UTF-8.
+		/// 
+		/// Your code should not assume that algorithms using char-at-a-time idioms
+		/// will be working in character units; in some cases they will split characters.
+		/// This is relevant wherever XML permits arbitrary characters, such as attribute
+		/// values, processing instruction data, and comments as well as in data reported
+		/// from this method. It's also generally relevant whenever C++ code manipulates
+		/// internationalized text; the issue isn't unique to XML.
+		/// 
+		/// Note that some parsers will report whitespace in element content using the
+		/// ignorableWhitespace method rather than this one (validating parsers must
+		/// do so).
+
+	virtual void ignorableWhitespace(const XMLChar ch[], int start, int length) = 0;
+		/// Receive notification of ignorable whitespace in element content.
+		/// 
+		/// Validating Parsers must use this method to report each chunk of whitespace
+		/// in element content (see the W3C XML 1.0 recommendation, section 2.10): non-validating
+		/// parsers may also use this method if they are capable of parsing and using
+		/// content models.
+		/// 
+		/// SAX parsers may return all contiguous whitespace in a single chunk, or they
+		/// may split it into several chunks; however, all of the characters in any
+		/// single event must come from the same external entity, so that the Locator
+		/// provides useful information.
+		/// 
+		/// The application must not attempt to read from the array outside of the specified
+		/// range.
+
+	virtual void processingInstruction(const XMLString& target, const XMLString& data) = 0;
+		/// Receive notification of a processing instruction.
+		/// 
+		/// The Parser will invoke this method once for each processing instruction
+		/// found: note that processing instructions may occur before or after the main
+		/// document element.
+		/// 
+		/// A SAX parser must never report an XML declaration (XML 1.0, section 2.8)
+		/// or a text declaration (XML 1.0, section 4.3.1) using this method.
+		/// 
+		/// Like characters(), processing instruction data may have characters that
+		/// need more than one char value.
+
+	virtual void startPrefixMapping(const XMLString& prefix, const XMLString& uri) = 0;
+		/// Begin the scope of a prefix-URI Namespace mapping.
+		/// 
+		/// The information from this event is not necessary for normal Namespace processing:
+		/// the SAX XML reader will automatically replace prefixes for element and attribute
+		/// names when the http://xml.org/sax/features/namespaces feature is true (the
+		/// default).
+		/// 
+		/// There are cases, however, when applications need to use prefixes in character
+		/// data or in attribute values, where they cannot safely be expanded automatically;
+		/// the start/endPrefixMapping event supplies the information to the application
+		/// to expand prefixes in those contexts itself, if necessary.
+		/// 
+		/// Note that start/endPrefixMapping events are not guaranteed to be properly
+		/// nested relative to each other: all startPrefixMapping events will occur
+		/// immediately before the corresponding startElement event, and all endPrefixMapping
+		/// events will occur immediately after the corresponding endElement event,
+		/// but their order is not otherwise guaranteed.
+		/// 
+		/// There should never be start/endPrefixMapping events for the "xml" prefix,
+		/// since it is predeclared and immutable.
+
+	virtual void endPrefixMapping(const XMLString& prefix) = 0;
+		/// End the scope of a prefix-URI mapping.
+		/// 
+		/// See startPrefixMapping for details. These events will always occur immediately
+		/// after the corresponding endElement event, but the order of endPrefixMapping
+		/// events is not otherwise guaranteed.
+
+	virtual void skippedEntity(const XMLString& name) = 0;
+		/// Receive notification of a skipped entity. This is not called for entity
+		/// references within markup constructs such as element start tags or markup
+		/// declarations. (The XML recommendation requires reporting skipped external
+		/// entities. SAX also reports internal entity expansion/non-expansion, except
+		/// within markup constructs.)
+		/// 
+		/// The Parser will invoke this method each time the entity is skipped. Non-validating
+		/// processors may skip entities if they have not seen the declarations (because,
+		/// for example, the entity was declared in an external DTD subset). All processors
+		/// may skip external entities, depending on the values of the http://xml.org/sax/features/external-general-entities
+		/// and the http://xml.org/sax/features/external-parameter-entities properties.
+
+protected:
+	virtual ~ContentHandler();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_ContentHandler_INCLUDED
diff --git a/Poco/SAX/DTDHandler.h b/Poco/SAX/DTDHandler.h
new file mode 100644
index 0000000..f21a299
--- /dev/null
+++ b/Poco/SAX/DTDHandler.h
@@ -0,0 +1,86 @@
+//
+// DTDHandler.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX DTDHandler Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_DTDHandler_INCLUDED
+#define SAX_DTDHandler_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API DTDHandler
+	/// If a SAX application needs information about notations and unparsed entities, 
+	/// then the application implements this interface and registers an instance with the 
+	/// SAX parser using the parser's setDTDHandler method. The parser uses the instance 
+	/// to report notation and unparsed entity declarations to the application.
+	///
+	/// Note that this interface includes only those DTD events that the XML recommendation 
+	/// requires processors to report: notation and unparsed entity declarations.
+	///
+	/// The SAX parser may report these events in any order, regardless of the order in 
+	/// which the notations and unparsed entities were declared; however, all DTD events 
+	/// must be reported after the document handler's startDocument event, and before the first 
+	/// startElement event. (If the LexicalHandler is used, these events must also be reported before the endDTD event.)
+	/// 
+	/// It is up to the application to store the information for future use (perhaps in a hash table or 
+	/// object tree). If the application encounters attributes of type "NOTATION", "ENTITY", or "ENTITIES", 
+	/// it can use the information that it obtained through this interface to find the entity and/or notation
+	/// corresponding with the attribute value.
+{
+public:
+	virtual void notationDecl(const XMLString& name, const XMLString* publicId, const XMLString* systemId) = 0;
+		/// Receive notification of a notation declaration event.
+		/// 
+		/// It is up to the application to record the notation for later reference, 
+		/// if necessary; notations may appear as attribute values and in unparsed 
+		/// entity declarations, and are sometime used with processing instruction 
+		/// target names.
+		/// 
+		/// At least one of publicId and systemId must be non-null. If a system identifier 
+		/// is present, and it is a URL, the SAX parser must resolve it fully before passing 
+		/// it to the application through this event.
+		/// 
+		/// There is no guarantee that the notation declaration will be reported before any 
+		/// unparsed entities that use it.
+		///
+		/// Note that publicId and systemId maybe null, therefore we pass a pointer rather than a reference.
+		
+	virtual void unparsedEntityDecl(const XMLString& name, const XMLString* publicId, const XMLString& systemId, const XMLString& notationName) = 0;
+		/// Receive notification of an unparsed entity declaration event.
+		/// 
+		/// Note that the notation name corresponds to a notation reported by the 
+		/// notationDecl event. It is up to the application to record the entity for 
+		/// later reference, if necessary; unparsed entities may appear as attribute values.
+		/// 
+		/// If the system identifier is a URL, the parser must resolve it fully before 
+		/// passing it to the application.
+		/// 
+		/// Note that publicId maybe null, therefore we pass a pointer rather than a reference.
+
+protected:
+	virtual ~DTDHandler();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_DTDHandler_INCLUDED
diff --git a/Poco/SAX/DeclHandler.h b/Poco/SAX/DeclHandler.h
new file mode 100644
index 0000000..578f102
--- /dev/null
+++ b/Poco/SAX/DeclHandler.h
@@ -0,0 +1,91 @@
+//
+// DeclHandler.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX2-ext DeclHandler Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_DeclHandler_INCLUDED
+#define SAX_DeclHandler_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API DeclHandler
+	/// This is an optional extension handler for SAX2 to provide information 
+	/// about DTD declarations in an XML document. XML
+	/// readers are not required to support this handler, and this handler is 
+	/// not included in the core SAX2 distribution.
+	///
+	/// Note that data-related DTD declarations (unparsed entities and notations) 
+	/// are already reported through the DTDHandler interface.
+	/// If you are using the declaration handler together with a lexical handler, 
+	/// all of the events will occur between the startDTD and the endDTD events.
+	/// To set the DeclHandler for an XML reader, use the setProperty method 
+	/// with the propertyId "http://xml.org/sax/properties/declaration-handler". 
+	/// If the reader does not support declaration events, it will throw a
+	/// SAXNotRecognizedException or a SAXNotSupportedException when you attempt to 
+	/// register the handler.
+{
+public:
+	virtual void attributeDecl(const XMLString& eName, const XMLString& aName, const XMLString* valueDefault, const XMLString* value) = 0;
+		/// Report an attribute type declaration.
+		/// 
+		/// Only the effective (first) declaration for an attribute will be reported. 
+		/// The type will be one of the strings "CDATA", "ID", "IDREF", "IDREFS", 
+		/// "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", a parenthesized token group 
+		/// with the separator "|" and all whitespace removed, or the word "NOTATION" 
+		/// followed by a space followed by a parenthesized token group with all whitespace 
+		/// removed.
+		///
+		/// The value will be the value as reported to applications, appropriately normalized 
+		/// and with entity and character references expanded. 
+		
+	virtual void elementDecl(const XMLString& name, const XMLString& model) = 0;
+		/// Report an element type declaration.
+		///
+		/// The content model will consist of the string "EMPTY", the string "ANY", or a 
+		/// parenthesised group, optionally followed by an occurrence indicator. The model 
+		/// will be normalized so that all parameter entities are fully resolved and all 
+		/// whitespace is removed,and will include the enclosing parentheses. Other 
+		/// normalization (such as removing redundant parentheses or simplifying occurrence 
+		/// indicators) is at the discretion of the parser.
+		
+	virtual void externalEntityDecl(const XMLString& name, const XMLString* publicId, const XMLString& systemId) = 0;
+		/// Report an external entity declaration.
+		/// 
+		/// Only the effective (first) declaration for each entity will be reported.
+		/// 
+		/// If the system identifier is a URL, the parser must resolve it fully before 
+		/// passing it to the application.
+
+	virtual void internalEntityDecl(const XMLString& name, const XMLString& value) = 0;
+		/// Report an internal entity declaration.
+		///
+		/// Only the effective (first) declaration for each entity will be reported. All 
+		/// parameter entities in the value will be expanded, but general entities will not.
+
+protected:
+	virtual ~DeclHandler();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_DeclHandler_INCLUDED
diff --git a/Poco/SAX/DefaultHandler.h b/Poco/SAX/DefaultHandler.h
new file mode 100644
index 0000000..7df1f54
--- /dev/null
+++ b/Poco/SAX/DefaultHandler.h
@@ -0,0 +1,83 @@
+//
+// DefaultHandler.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX-2 DefaultHandler class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_DefaultHandler_INCLUDED
+#define SAX_DefaultHandler_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/EntityResolver.h"
+#include "Poco/SAX/DTDHandler.h"
+#include "Poco/SAX/ContentHandler.h"
+#include "Poco/SAX/ErrorHandler.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API DefaultHandler: public EntityResolver, public DTDHandler, public ContentHandler, public ErrorHandler
+	/// Default base class for SAX2 event handlers. 
+	/// This class is available as a convenience base class for SAX2 applications: 
+	/// it provides default implementations for all of the
+	/// callbacks in the four core SAX2 handler classes:
+	///      * EntityResolver 
+	///      * DTDHandler 
+	///      * ContentHandler 
+	///      * ErrorHandler 
+	/// Application writers can extend this class when they need to implement only 
+	/// part of an interface; parser writers can instantiate this
+	/// class to provide default handlers when the application has not supplied its own.
+{
+public:
+	DefaultHandler();
+		/// Creates the DefaultHandler.
+		
+	~DefaultHandler();
+		/// Destroys the DefaultHandler.
+	
+	// EntityResolver
+	InputSource* resolveEntity(const XMLString* publicId, const XMLString& systemId);
+	void releaseInputSource(InputSource* pSource);
+	
+	// DTDHandler
+	void notationDecl(const XMLString& name, const XMLString* publicId, const XMLString* systemId);
+	void unparsedEntityDecl(const XMLString& name, const XMLString* publicId, const XMLString& systemId, const XMLString& notationName);
+
+	// ContentHandler
+	void setDocumentLocator(const Locator* loc);
+	void startDocument();
+	void endDocument();
+	void startElement(const XMLString& uri, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+	void endElement(const XMLString& uri, const XMLString& localName, const XMLString& qname);
+	void characters(const XMLChar ch[], int start, int length);
+	void ignorableWhitespace(const XMLChar ch[], int start, int length);
+	void processingInstruction(const XMLString& target, const XMLString& data);
+	void startPrefixMapping(const XMLString& prefix, const XMLString& uri);
+	void endPrefixMapping(const XMLString& prefix);
+	void skippedEntity(const XMLString& name);
+	
+	// ErrorHandler
+	void warning(const SAXException& exc);
+	void error(const SAXException& exc);
+	void fatalError(const SAXException& exc);
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_DefaultHandler_INCLUDED
diff --git a/Poco/SAX/EntityResolver.h b/Poco/SAX/EntityResolver.h
new file mode 100644
index 0000000..3387ecf
--- /dev/null
+++ b/Poco/SAX/EntityResolver.h
@@ -0,0 +1,86 @@
+//
+// EntityResolver.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX EntityResolver Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_EntityResolver_INCLUDED
+#define SAX_EntityResolver_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class InputSource;
+
+
+class XML_API EntityResolver
+	/// If a SAX application needs to implement customized handling for external entities, 
+	/// it must implement this interface and register an instance with the SAX driver using 
+	/// the setEntityResolver method.
+	/// 
+	/// The XML reader will then allow the application to intercept any external entities 
+	/// (including the external DTD subset and external parameter entities, if any) before 
+	/// including them.
+	/// 
+	/// Many SAX applications will not need to implement this interface, but it will be 
+	/// especially useful for applications that build XML documents from databases or other 
+	/// specialised input sources, or for applications that use URI types other than URLs.
+	///
+	/// The application can also use this interface to redirect system identifiers to local 
+	/// URIs or to look up replacements in a catalog (possibly by using the public identifier).
+{
+public:
+	virtual InputSource* resolveEntity(const XMLString* publicId, const XMLString& systemId) = 0;
+		/// Allow the application to resolve external entities.
+		/// 
+		/// The parser will call this method before opening any external entity except the 
+		/// top-level document entity. Such entities include the external DTD subset and 
+		/// external parameter entities referenced within the DTD (in either case, only 
+		/// if the parser reads external parameter entities), and external general entities 
+		/// referenced within the document element (if the parser reads external general entities). 
+		/// The application may request that the parser locate the entity itself, that it use an 
+		/// alternative URI, or that it use data provided by the application (as a character or 
+		/// byte input stream).
+		/// 
+		/// Application writers can use this method to redirect external system identifiers to 
+		/// secure and/or local URIs, to look up public identifiers in a catalogue, or to read an 
+		/// entity from a database or other input source (including, for example, a dialog box). 
+		/// Neither XML nor SAX specifies a preferred policy for using public or system IDs to resolve 
+		/// resources. However, SAX specifies how to interpret any InputSource returned by this method, 
+		/// and that if none is returned, then the system ID will be dereferenced as a URL.
+		/// 
+		/// If the system identifier is a URL, the SAX parser must resolve it fully before reporting it to 
+		/// the application.
+		/// 
+		/// Note that publicId maybe null, therefore we pass a pointer rather than a reference.
+
+	virtual void releaseInputSource(InputSource* pSource) = 0;
+		/// This is a non-standard extension to SAX!
+		/// Called by the parser when the input source returned by ResolveEntity is
+		/// no longer needed. Should free any resources used by the input source.
+
+protected:
+	virtual ~EntityResolver();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_EntityResolver_INCLUDED
diff --git a/Poco/SAX/EntityResolverImpl.h b/Poco/SAX/EntityResolverImpl.h
new file mode 100644
index 0000000..de088c6
--- /dev/null
+++ b/Poco/SAX/EntityResolverImpl.h
@@ -0,0 +1,78 @@
+//
+// EntityResolverImpl.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// An implementation of EntityResolver.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_EntityResolverImpl_INCLUDED
+#define SAX_EntityResolverImpl_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/SAX/EntityResolver.h"
+#include "Poco/URIStreamOpener.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API EntityResolverImpl: public EntityResolver
+	/// A default implementation of the EntityResolver interface.
+	///
+	/// The system ID is first interpreted as an URI and the
+	/// URIStreamOpener is used to create and open an istream
+	/// for an InputSource.
+	///
+	/// If the system ID is not a valid URI, it is
+	/// interpreted as a filesystem path and a Poco::FileInputStream
+	/// is opened for it.
+{
+public:
+	EntityResolverImpl();
+		/// Creates an EntityResolverImpl that uses the default
+		/// URIStreamOpener.
+		
+	EntityResolverImpl(const Poco::URIStreamOpener& opener);
+		/// Creates an EntityResolverImpl that uses the given
+		/// URIStreamOpener.
+		
+	~EntityResolverImpl();
+		/// Destroys the EntityResolverImpl.
+	
+	InputSource* resolveEntity(const XMLString* publicId, const XMLString& systemId);
+		/// Tries to use the URIStreamOpener to create and open an istream
+		/// for the given systemId, which is interpreted as an URI.
+		///
+		/// If the systemId is not a valid URI, it is interpreted as
+		/// a local filesystem path and a Poco::FileInputStream is opened for it.
+		
+	void releaseInputSource(InputSource* pSource);
+		/// Deletes the InputSource's stream.
+	
+protected:
+	std::istream* resolveSystemId(const XMLString& systemId);	
+	
+private:
+	EntityResolverImpl(const EntityResolverImpl&);
+	EntityResolverImpl& operator = (const EntityResolverImpl&);
+	
+	const Poco::URIStreamOpener& _opener;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_EntityResolverImpl_INCLUDED
diff --git a/Poco/SAX/ErrorHandler.h b/Poco/SAX/ErrorHandler.h
new file mode 100644
index 0000000..3097e20
--- /dev/null
+++ b/Poco/SAX/ErrorHandler.h
@@ -0,0 +1,92 @@
+//
+// ErrorHandler.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX ErrorHandler Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_ErrorHandler_INCLUDED
+#define SAX_ErrorHandler_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class SAXException;
+
+
+class XML_API ErrorHandler
+	/// If a SAX application needs to implement customized error handling, it must 
+	/// implement this interface and then register an instance with the XML reader 
+	/// using the setErrorHandler method. The parser will then report all errors and 
+	/// warnings through this interface.
+	/// 
+	/// WARNING: If an application does not register an ErrorHandler, XML parsing errors 
+	/// will go unreported, except that SAXParseExceptions will be thrown for fatal errors. 
+	/// In order to detect validity errors, an ErrorHandler that does something with error() 
+	/// calls must be registered.
+	/// 
+	/// For XML processing errors, a SAX driver must use this interface in preference to 
+	/// throwing an exception: it is up to the application to decide whether to throw an 
+	/// exception for different types of errors and warnings. Note, however, that there is no 
+	/// requirement that the parser continue to report additional errors after a call to 
+	/// fatalError. In other words, a SAX driver class may throw an exception after reporting 
+	/// any fatalError. Also parsers may throw appropriate exceptions for non-XML errors. For 
+	/// example, XMLReader::parse() would throw an IOException for errors accessing entities or 
+	/// the document.
+{
+public:
+	virtual void warning(const SAXException& exc) = 0;
+		/// Receive notification of a warning.
+		/// 
+		/// SAX parsers will use this method to report conditions that are not errors or fatal 
+		/// errors as defined by the XML recommendation. The default behaviour is to take no action.
+		/// 
+		/// The SAX parser must continue to provide normal parsing events after invoking this method: 
+		/// it should still be possible for the application to process the document through to the end.
+		/// 
+		/// Filters may use this method to report other, non-XML warnings as well.
+
+	virtual void error(const SAXException& exc) = 0;
+		/// Receive notification of a recoverable error.
+		/// 
+		/// This corresponds to the definition of "error" in section 1.2 of the W3C XML 1.0 
+		/// Recommendation. For example, a validating parser would use this callback to report 
+		/// the violation of a validity constraint. The default behaviour is to take no action.
+		/// 
+		/// The SAX parser must continue to provide normal parsing events after invoking this 
+		/// method: it should still be possible for the application to process the document through 
+		/// to the end. If the application cannot do so, then the parser should report a fatal error 
+		/// even if the XML recommendation does not require it to do so.
+		/// 
+		/// Filters may use this method to report other, non-XML errors as well.
+
+	virtual void fatalError(const SAXException& exc) = 0;
+		/// Receive notification of a non-recoverable error.
+		/// The application must assume that the document is unusable after the parser has 
+		/// invoked this method, and should continue (if at all) only for the sake of collecting 
+		/// additional error messages: in fact, SAX parsers are free to stop reporting any other 
+		/// events once this method has been invoked.
+
+protected:
+	virtual ~ErrorHandler();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_ErrorHandler_INCLUDED
diff --git a/Poco/SAX/InputSource.h b/Poco/SAX/InputSource.h
new file mode 100644
index 0000000..7fcecf2
--- /dev/null
+++ b/Poco/SAX/InputSource.h
@@ -0,0 +1,169 @@
+//
+// InputSource.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX InputSource - A single input source for an XML entity.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_InputSource_INCLUDED
+#define SAX_InputSource_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/XML/XMLStream.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API InputSource
+	/// This class allows a SAX application to encapsulate information about an input 
+	/// source in a single object, which may include a public identifier, a system 
+	/// identifier, a byte stream (possibly with a specified encoding), and/or a character 
+	/// stream.
+	/// 
+	/// There are two places that the application can deliver an input source to the 
+	/// parser: as the argument to the Parser.parse method, or as the return value of the 
+	/// EntityResolver::resolveEntity() method.
+	/// 
+	/// The SAX parser will use the InputSource object to determine how to read XML input. 
+	/// If there is a character stream available, the parser will read that stream directly, 
+	/// disregarding any text encoding declaration found in that stream. If there is no character 
+	/// stream, but there is a byte stream, the parser will use that byte stream, using the 
+	/// encoding specified in the InputSource or else (if no encoding is specified) autodetecting 
+	/// the character encoding using an algorithm such as the one in the XML specification. 
+	/// If neither a character stream nor a byte stream is available, the parser will attempt 
+	/// to open a URI connection to the resource identified by the system identifier.
+	/// 
+	/// An InputSource object belongs to the application: the SAX parser shall never modify it in 
+	/// any way (it may modify a copy if necessary). However, standard processing of both byte and 
+	/// character streams is to close them on as part of end-of-parse cleanup, so applications should 
+	/// not attempt to re-use such streams after they have been handed to a parser.
+{
+public:
+	InputSource();
+		/// Zero-argument default constructor.
+		
+	InputSource(const XMLString& systemId);
+		/// Creates a new input source with a system identifier.
+		/// Applications may use setPublicId to include a public identifier as well, 
+		/// or setEncoding to specify the character encoding, if known.
+		/// 
+		/// If the system identifier is a URL, it must be fully resolved (it may not 
+		/// be a relative URL).
+		
+	InputSource(XMLByteInputStream& istr);
+		/// Creates a new input source with a byte stream.
+		/// 
+		/// Application writers should use setSystemId() to provide a base for resolving
+		/// relative URIs, may use setPublicId to include a public identifier, and may use 
+		/// setEncoding to specify the object's character encoding.
+
+	~InputSource();
+		/// Destroys the InputSource.
+
+	void setPublicId(const XMLString& publicId);
+		/// Set the public identifier for this input source.
+		///
+		/// The public identifier is always optional: if the application writer includes one, 
+		/// it will be provided as part of the location information.
+		
+	void setSystemId(const XMLString& systemId);
+		/// Set the system identifier for this input source.
+		///
+		/// The system identifier is optional if there is a byte stream or a character stream, 
+		/// but it is still useful to provide one, since the application can use it to resolve 
+		/// relative URIs and can include it in error messages and warnings (the parser will 
+		/// attempt to open a connection to the URI only if there is no byte stream or character 
+		/// stream specified).
+		/// 
+		/// If the application knows the character encoding of the object pointed to by the system 
+		/// identifier, it can register the encoding using the setEncoding method.
+		/// 
+		/// If the system identifier is a URL, it must be fully resolved (it may not be a relative URL).
+
+	const XMLString& getPublicId() const;
+		/// Get the public identifier for this input source.
+		
+	const XMLString& getSystemId() const;
+		/// Get the system identifier for this input source.
+
+	void setByteStream(XMLByteInputStream& istr);
+		/// Set the byte stream for this input source.
+		/// The SAX parser will ignore this if there is also a character stream specified, but it 
+		/// will use a byte stream in preference to opening a URI connection itself.
+		
+	XMLByteInputStream* getByteStream() const;
+		/// Get the byte stream for this input source.
+
+	void setCharacterStream(XMLCharInputStream& istr);
+		/// Set the character stream for this input source.
+
+	XMLCharInputStream* getCharacterStream() const;
+		/// Get the character stream for this input source.
+
+	void setEncoding(const XMLString& encoding);
+		/// Set the character encoding, if known.
+		/// The encoding must be a string acceptable for an XML encoding declaration 
+		/// (see section 4.3.3 of the XML 1.0 recommendation).
+		
+	const XMLString& getEncoding() const;
+		/// Get the character encoding for a byte stream or URI.
+
+private:
+	XMLString _publicId;
+	XMLString _systemId;
+	XMLString _encoding;
+	XMLByteInputStream* _bistr;
+	XMLCharInputStream* _cistr;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& InputSource::getPublicId() const
+{
+	return _publicId;
+}
+
+
+inline const XMLString& InputSource::getSystemId() const
+{
+	return _systemId;
+}
+
+
+inline const XMLString& InputSource::getEncoding() const
+{
+	return _encoding;
+}
+
+
+inline XMLByteInputStream* InputSource::getByteStream() const
+{
+	return _bistr;
+}
+
+
+inline XMLCharInputStream* InputSource::getCharacterStream() const
+{
+	return _cistr;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_InputSource_INCLUDED
diff --git a/Poco/SAX/LexicalHandler.h b/Poco/SAX/LexicalHandler.h
new file mode 100644
index 0000000..772bd5c
--- /dev/null
+++ b/Poco/SAX/LexicalHandler.h
@@ -0,0 +1,125 @@
+//
+// LexicalHandler.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX2-ext LexicalHandler Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_LexicalHandler_INCLUDED
+#define SAX_LexicalHandler_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API LexicalHandler
+	/// This is an optional extension handler for SAX2 to provide lexical information 
+	/// about an XML document, such as comments and CDATA section boundaries. 
+	/// XML readers are not required to recognize this handler, and it is not part of 
+	/// core-only SAX2 distributions.
+	/// 
+	/// The events in the lexical handler apply to the entire document, not just to the 
+	/// document element, and all lexical handler events must appear between the content 
+	/// handler's startDocument and endDocument events.
+	/// 
+	/// To set the LexicalHandler for an XML reader, use the setProperty method with the 
+	/// property name http://xml.org/sax/properties/lexical-handler and an object implementing 
+	/// this interface (or null) as the value. If the reader does not report lexical events, 
+	/// it will throw a SAXNotRecognizedException when you attempt to register the handler.
+{
+public:
+	virtual void startDTD(const XMLString& name, const XMLString& publicId, const XMLString& systemId) = 0;
+		/// Report the start of DTD declarations, if any.
+		/// 
+		/// This method is intended to report the beginning of the DOCTYPE declaration; 
+		/// if the document has no DOCTYPE declaration, this method will not be invoked.
+		/// 
+		/// All declarations reported through DTDHandler or DeclHandler events must appear 
+		/// between the startDTD and endDTD events. Declarations are assumed to belong to 
+		/// the internal DTD subset unless they appear between startEntity and endEntity 
+		/// events. Comments and processing instructions from the DTD should also be reported 
+		/// between the startDTD and endDTD events, in their original order of (logical) occurrence; 
+		/// they are not required to appear in their correct locations relative to DTDHandler or 
+		/// DeclHandler events, however.
+		/// 
+		/// Note that the start/endDTD events will appear within the start/endDocument events from 
+		/// ContentHandler and before the first startElement event.
+
+	virtual void endDTD() = 0;
+		/// Report the end of DTD declarations.
+		/// 
+		/// This method is intended to report the end of the DOCTYPE declaration; if the document 
+		/// has no DOCTYPE declaration, this method will not be invoked.
+
+	virtual void startEntity(const XMLString& name) = 0;
+		/// Report the beginning of some internal and external XML entities.
+		/// 
+		/// The reporting of parameter entities (including the external DTD subset) is optional, 
+		/// and SAX2 drivers that report LexicalHandler events may not implement it; you can use the 
+		/// http://xml.org/sax/features/lexical-handler/parameter-entities feature to query or control 
+		/// the reporting of parameter entities.
+		/// 
+		/// General entities are reported with their regular names, parameter entities have '%' 
+		/// prepended to their names, and the external DTD subset has the pseudo-entity name "[dtd]".
+		/// 
+		/// When a SAX2 driver is providing these events, all other events must be properly nested 
+		/// within start/end entity events. There is no additional requirement that events from 
+		/// DeclHandler or DTDHandler be properly ordered.
+		/// 
+		/// Note that skipped entities will be reported through the skippedEntity event, which is part of 
+		/// the ContentHandler interface.
+		/// 
+		/// Because of the streaming event model that SAX uses, some entity boundaries cannot be reported under 
+		/// any circumstances:
+		/// 
+		///     * general entities within attribute values
+		///     * parameter entities within declarations
+		///
+		/// These will be silently expanded, with no indication of where the original entity boundaries were.
+		/// 
+		/// Note also that the boundaries of character references (which are not really entities anyway) are not reported.
+		/// 
+		/// All start/endEntity events must be properly nested. 
+
+	virtual void endEntity(const XMLString& name) = 0;
+		/// Report the end of an entity.
+		
+	virtual void startCDATA() = 0;
+		/// Report the start of a CDATA section.
+		///
+		/// The contents of the CDATA section will be reported through the regular characters event; 
+		/// this event is intended only to report the boundary.
+
+	virtual void endCDATA() = 0;
+		/// Report the end of a CDATA section.
+		
+	virtual void comment(const XMLChar ch[], int start, int length) = 0;
+		/// Report an XML comment anywhere in the document.
+		/// 
+		/// This callback will be used for comments inside or outside the document element, 
+		/// including comments in the external DTD subset (if read). Comments in the DTD must 
+		/// be properly nested inside start/endDTD and start/endEntity events (if used).
+
+protected:
+	virtual ~LexicalHandler();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_LexicalHandler_INCLUDED
diff --git a/Poco/SAX/Locator.h b/Poco/SAX/Locator.h
new file mode 100644
index 0000000..4f2b47d
--- /dev/null
+++ b/Poco/SAX/Locator.h
@@ -0,0 +1,103 @@
+//
+// Locator.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX Locator Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_Locator_INCLUDED
+#define SAX_Locator_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Locator
+	/// Interface for associating a SAX event with a document location.
+	/// 
+	/// If a SAX parser provides location information to the SAX application, it does so by 
+	/// implementing this interface and then passing an instance to the application using the 
+	/// content handler's setDocumentLocator method. The application can use the object to obtain 
+	/// the location of any other SAX event in the XML source document.
+	/// 
+	/// Note that the results returned by the object will be valid only during the scope of each 
+	/// callback method: the application will receive unpredictable results if it attempts to use 
+	/// the locator at any other time, or after parsing completes.
+	/// 
+	/// SAX parsers are not required to supply a locator, but they are very strongly encouraged to 
+	/// do so. If the parser supplies a locator, it must do so before reporting any other document 
+	/// events. If no locator has been set by the time the application receives the startDocument event, 
+	/// the application should assume that a locator is not available.
+{
+public:
+	virtual XMLString getPublicId() const = 0;
+		/// Return the public identifier for the current document event.
+		/// 
+		/// The return value is the public identifier of the document entity or of the external 
+		/// parsed entity in which the markup triggering the event appears.
+
+	virtual XMLString getSystemId() const = 0;
+		/// Return the system identifier for the current document event.
+		/// 
+		/// The return value is the system identifier of the document entity or of the external 
+		/// parsed entity in which the markup triggering the event appears.
+		/// 
+		/// If the system identifier is a URL, the parser must resolve it fully before passing 
+		/// it to the application. For example, a file name must always be provided as a 
+		/// file:... URL, and other kinds of relative URI are also resolved against their bases.
+
+	virtual int getLineNumber() const = 0;
+		/// Return the line number where the current document event ends.
+		/// Lines are delimited by line ends, which are defined in the XML specification.
+		/// 
+		/// Warning: The return value from the method is intended only as an approximation for 
+		/// the sake of diagnostics; it is not intended to provide sufficient information to 
+		/// edit the character content of the original XML document. In some cases, these "line" 
+		/// numbers match what would be displayed as columns, and in others they may not match the 
+		/// source text due to internal entity expansion.
+		/// 
+		/// The return value is an approximation of the line number in the document entity or external 
+		/// parsed entity where the markup triggering the event appears.
+		/// 
+		/// If possible, the SAX driver should provide the line position of the first character after 
+		/// the text associated with the document event. The first line is line 1.
+
+	virtual int getColumnNumber() const = 0;
+		/// Return the column number where the current document event ends. 
+		/// This is one-based number of characters since the last line end.
+		/// 
+		/// Warning: The return value from the method is intended only as an approximation 
+		/// for the sake of diagnostics; it is not intended to provide sufficient information 
+		/// to edit the character content of the original XML document. For example, when lines 
+		/// contain combining character sequences, wide characters, surrogate pairs, or bi-directional 
+		/// text, the value may not correspond to the column in a text editor's display.
+		/// 
+		/// The return value is an approximation of the column number in the document entity or external 
+		/// parsed entity where the markup triggering the event appears.
+		/// 
+		/// If possible, the SAX driver should provide the line position of the first character after 
+		/// the text associated with the document event. The first column in each line is column 1.
+
+protected:
+	virtual ~Locator();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_Locator_INCLUDED
diff --git a/Poco/SAX/LocatorImpl.h b/Poco/SAX/LocatorImpl.h
new file mode 100644
index 0000000..2c924b3
--- /dev/null
+++ b/Poco/SAX/LocatorImpl.h
@@ -0,0 +1,88 @@
+//
+// LocatorImpl.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// An implementation of the SAX Locator interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_LocatorImpl_INCLUDED
+#define SAX_LocatorImpl_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/Locator.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API LocatorImpl: public Locator
+	/// Provide an optional convenience implementation of Locator.
+{
+public:
+	LocatorImpl();
+		/// Zero-argument constructor.
+		/// 
+		/// This will not normally be useful, since the main purpose of this class is 
+		/// to make a snapshot of an existing Locator.
+		
+	LocatorImpl(const Locator& loc);
+		/// Copy constructor.
+		/// 
+		/// Create a persistent copy of the current state of a locator. When the original 
+		/// locator changes, this copy will still keep the original values (and it can be 
+		/// used outside the scope of DocumentHandler methods).
+
+	~LocatorImpl();
+		/// Destroys the Locator.
+		
+	LocatorImpl& operator = (const Locator& loc);
+		/// Assignment operator.
+
+	XMLString getPublicId() const;
+		/// Return the saved public identifier.
+		
+	XMLString getSystemId() const;
+		/// Return the saved system identifier.
+
+	int getLineNumber() const;
+		/// Return the saved line number (1-based).
+		
+	int getColumnNumber() const;
+		/// Return the saved column number (1-based).
+		
+	void setPublicId(const XMLString& publicId);
+		/// Set the public identifier for this locator.
+
+	void setSystemId(const XMLString& systemId);
+		/// Set the system identifier for this locator.
+
+	void setLineNumber(int lineNumber);
+		/// Set the line number for this locator (1-based).
+
+	void setColumnNumber(int columnNumber);
+		/// Set the column number for this locator (1-based).
+
+private:
+	XMLString _publicId;
+	XMLString _systemId;
+	int _lineNumber;
+	int _columnNumber;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_LocatorImpl_INCLUDED
diff --git a/Poco/SAX/NamespaceSupport.h b/Poco/SAX/NamespaceSupport.h
new file mode 100644
index 0000000..7441649
--- /dev/null
+++ b/Poco/SAX/NamespaceSupport.h
@@ -0,0 +1,195 @@
+//
+// NamespaceSupport.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// Namespace support for SAX2.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_NamespaceSupport_INCLUDED
+#define SAX_NamespaceSupport_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include <set>
+#include <map>
+#include <vector>
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API NamespaceSupport
+	/// Encapsulate Namespace logic for use by SAX drivers. 
+	/// This class encapsulates the logic of Namespace processing: 
+	/// it tracks the declarations currently in force for each context and
+	/// automatically processes qualified XML 1.0 names into their Namespace 
+	/// parts; it can also be used in reverse for generating
+	/// XML 1.0 from Namespaces.
+	/// Namespace support objects are reusable, but the reset method 
+	/// must be invoked between each session.
+{
+public:
+	typedef std::set<XMLString> PrefixSet;
+
+	NamespaceSupport();
+		/// Creates a NamespaceSupport object.
+		
+	~NamespaceSupport();
+		/// Destroys a NamespaceSupport object.
+	
+	bool declarePrefix(const XMLString& prefix, const XMLString& namespaceURI);
+		/// Declare a Namespace prefix. All prefixes must be declared before they are
+		/// referenced. For example, a SAX driver (parser) would scan an element's attributes
+		/// in two passes: first for namespace declarations, then a second pass using
+		/// processName() to interpret prefixes against (potentially redefined) prefixes.
+		/// 
+		/// This method declares a prefix in the current Namespace context; the prefix
+		/// will remain in force until this context is popped, unless it is shadowed
+		/// in a descendant context.
+		/// 
+		/// To declare the default element Namespace, use the empty string as the prefix.
+		/// 
+		/// Note that you must not declare a prefix after you've pushed and popped another
+		/// Namespace context, or treated the declarations phase as complete by processing
+		/// a prefixed name.
+		///
+		/// Returns true if the prefix was legal, false otherwise.
+	
+	bool undeclarePrefix(const XMLString& prefix);
+		/// Remove the given namespace prefix.
+	
+	void getDeclaredPrefixes(PrefixSet& prefixes) const;
+		/// Return an enumeration of all prefixes declared in this context.
+		/// 
+		/// The empty (default) prefix will be included in this enumeration; note that
+		/// this behaviour differs from that of getPrefix() and getPrefixes().
+
+	const XMLString& getPrefix(const XMLString& namespaceURI) const;
+		/// Return one of the prefixes mapped to a Namespace URI.
+		/// 
+		/// If more than one prefix is currently mapped to the same URI, this method
+		/// will make an arbitrary selection; if you want all of the prefixes, use the
+		/// getPrefixes() method instead.
+
+	bool isMapped(const XMLString& namespaceURI) const;
+		/// Returns true if the given namespaceURI has been mapped to a prefix,
+		/// false otherwise.
+
+	void getPrefixes(PrefixSet& prefixes) const;
+		/// Return an enumeration of all prefixes whose declarations are active in the
+		/// current context. This includes declarations from parent contexts that have
+		/// not been overridden.
+		/// 
+		/// Note: if there is a default prefix, it will not be returned in this enumeration;
+		/// check for the default prefix using the getURI with an argument of "".
+
+	void getPrefixes(const XMLString& namespaceURI, PrefixSet& prefixes) const;
+		/// Return an enumeration of all prefixes for a given URI whose declarations
+		/// are active in the current context. This includes declarations from parent
+		/// contexts that have not been overridden.
+		/// 
+		/// This method returns prefixes mapped to a specific Namespace URI. The xml:
+		/// prefix will be included. If you want only one prefix that's mapped to the
+		/// Namespace URI, and you don't care which one you get, use the getPrefix() method
+		/// instead.
+		/// 
+		/// Note: the empty (default) prefix is never included in this enumeration;
+		/// to check for the presence of a default Namespace, use the getURI() method
+		/// with an argument of "".
+
+	const XMLString& getURI(const XMLString& prefix) const;
+		/// Look up a prefix and get the currently-mapped Namespace URI.
+		/// 
+		/// This method looks up the prefix in the current context. Use the empty string
+		/// ("") for the default Namespace.
+
+	void pushContext();
+		/// Start a new Namespace context. The new context will automatically inherit
+		/// the declarations of its parent context, but it will also keep track of which
+		/// declarations were made within this context.
+		/// 
+		/// Event callback code should start a new context once per element. This means
+		/// being ready to call this in either of two places. For elements that don't
+		/// include namespace declarations, the ContentHandler::startElement() callback
+		/// is the right place. For elements with such a declaration, it'd done in the
+		/// first ContentHandler::startPrefixMapping() callback. A boolean flag can be
+		/// used to track whether a context has been started yet. When either of those
+		/// methods is called, it checks the flag to see if a new context needs to be
+		/// started. If so, it starts the context and sets the flag. After 
+		/// ContentHandler::startElement() does that, it always clears the flag.
+		/// 
+		/// Normally, SAX drivers would push a new context at the beginning of each
+		/// XML element. Then they perform a first pass over the attributes to process
+		/// all namespace declarations, making ContentHandler::startPrefixMapping() callbacks.
+		/// Then a second pass is made, to determine the namespace-qualified names for
+		/// all attributes and for the element name. Finally all the information for
+		/// the ContentHandler::startElement() callback is available, so it can then
+		/// be made.
+		/// 
+		/// The Namespace support object always starts with a base context already in
+		/// force: in this context, only the "xml" prefix is declared.
+
+	void popContext();
+		/// Revert to the previous Namespace context.
+		/// 
+		/// Normally, you should pop the context at the end of each XML element. After
+		/// popping the context, all Namespace prefix mappings that were previously
+		/// in force are restored.
+		/// 
+		/// You must not attempt to declare additional Namespace prefixes after popping
+		/// a context, unless you push another context first.
+
+	bool processName(const XMLString& qname, XMLString& namespaceURI, XMLString& localName, bool isAttribute) const;
+		/// Process a raw XML 1.0 name. 
+		/// This method processes a raw XML 1.0 name in the current context 
+		/// by removing the prefix and looking it up among the
+		/// prefixes currently declared. The result will be returned in
+		/// namespaceURI and localName.
+		/// If the raw name has a prefix that has not been declared, then the return
+		/// value will be false, otherwise true.
+		///
+		/// Note that attribute names are processed differently than element names: 
+		/// an unprefixed element name will receive the
+		/// default Namespace (if any), while an unprefixed attribute name will not.
+
+	void reset();
+		/// Reset this Namespace support object for reuse.
+		/// 
+		/// It is necessary to invoke this method before reusing the Namespace support
+		/// object for a new session. If namespace declaration URIs are to be supported,
+		/// that flag must also be set to a non-default value.
+		/// Reset this Namespace support object for reuse.
+
+	static const XMLString XML_NAMESPACE;
+	static const XMLString XML_NAMESPACE_PREFIX;
+	static const XMLString XMLNS_NAMESPACE;
+	static const XMLString XMLNS_NAMESPACE_PREFIX;
+
+private:
+	NamespaceSupport(const NamespaceSupport&);
+	NamespaceSupport& operator = (const NamespaceSupport&);
+
+	typedef std::map<XMLString, XMLString> Context;
+	typedef std::vector<Context> ContextVec;
+	
+	ContextVec _contexts;
+
+	static const XMLString EMPTY_STRING;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_NamespaceSupport_INCLUDED
diff --git a/Poco/SAX/SAXException.h b/Poco/SAX/SAXException.h
new file mode 100644
index 0000000..d756dd0
--- /dev/null
+++ b/Poco/SAX/SAXException.h
@@ -0,0 +1,176 @@
+//
+// SAXException.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX exception classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_SAXException_INCLUDED
+#define SAX_SAXException_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLException.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+POCO_DECLARE_EXCEPTION(XML_API, SAXException, XMLException)
+	/// The base class for all SAX-related exceptions like SAXParseException,
+	/// SAXNotRecognizedException or SAXNotSupportedException.
+	/// 
+	/// This class can contain basic error or warning information from either the XML parser 
+	/// or the application: a parser writer or application writer can subclass it to provide 
+	/// additional functionality. SAX handlers may throw this exception or any exception subclassed 
+	/// from it.
+	/// 
+	/// If the application needs to pass through other types of exceptions, it must wrap those exceptions 
+	/// in a SAXException or an exception derived from a SAXException.
+	/// 
+	/// If the parser or application needs to include information about a specific location in an XML 
+	/// document, it should use the SAXParseException subclass.
+
+
+POCO_DECLARE_EXCEPTION(XML_API, SAXNotRecognizedException, SAXException)
+	/// Exception class for an unrecognized identifier.
+	/// 
+	/// An XMLReader will throw this exception when it finds an unrecognized feature or property 
+	/// identifier; SAX applications and extensions may use this class for other, similar purposes.
+
+
+POCO_DECLARE_EXCEPTION(XML_API, SAXNotSupportedException, SAXException)
+	/// Exception class for an unsupported operation.
+	/// 
+	/// An XMLReader will throw this exception when it recognizes a feature or property identifier, 
+	/// but cannot perform the requested operation (setting a state or value). Other SAX2 applications 
+	/// and extensions may use this class for similar purposes.
+
+
+class Locator;
+
+
+class XML_API SAXParseException: public SAXException
+	/// Encapsulate an XML parse error or warning.
+	///
+	/// This exception may include information for locating the error in the original XML document, 
+	/// as if it came from a Locator object. Note that although the application will receive a 
+	/// SAXParseException as the argument to the handlers in the ErrorHandler interface, the application 
+	/// is not actually required to throw the exception; instead, it can simply read the information in it 
+	/// and take a different action.
+	/// 
+	/// Since this exception is a subclass of SAXException, it inherits the ability to wrap another exception.
+{
+public:	
+	SAXParseException(const std::string& msg, const Locator& loc);
+		/// Create a new SAXParseException from a message and a Locator.
+
+	SAXParseException(const std::string& msg, const Locator& loc, const Poco::Exception& exc);
+		/// Wrap an existing exception in a SAXParseException.
+
+	SAXParseException(const std::string& msg, const XMLString& publicId, const XMLString& systemId, int lineNumber, int columnNumber);
+		/// Create a new SAXParseException with an embedded exception.
+		/// 
+		/// This constructor is most useful for parser writers.
+		/// All parameters except the message are as if they were provided by a Locator. 
+		/// For example, if the system identifier is a URL (including relative filename), 
+		/// the caller must resolve it fully before creating the exception.
+
+	SAXParseException(const std::string& msg, const XMLString& publicId, const XMLString& systemId, int lineNumber, int columnNumber, const Poco::Exception& exc);
+		/// Create a new SAXParseException.
+		/// 
+		/// This constructor is most useful for parser writers.
+		/// All parameters except the message are as if they were provided by a Locator. 
+		/// For example, if the system identifier is a URL (including relative filename), 
+		/// the caller must resolve it fully before creating the exception.
+
+	SAXParseException(const SAXParseException& exc);
+		/// Creates a new SAXParseException from another one.
+
+	~SAXParseException() throw();
+		/// Destroy the exception.
+
+	SAXParseException& operator = (const SAXParseException& exc);
+		/// Assignment operator.
+		
+	const char* name() const throw();
+		/// Returns a static string describing the exception.
+
+	const char* className() const throw();
+		/// Returns the name of the exception class.
+
+	Poco::Exception* clone() const;
+		/// Creates an exact copy of the exception.
+		
+	void rethrow() const;
+		/// (Re)Throws the exception.
+
+	const XMLString& getPublicId() const;
+		/// Get the public identifier of the entity where the exception occurred.
+		
+	const XMLString& getSystemId() const;
+		/// Get the system identifier of the entity where the exception occurred.
+		
+	int getLineNumber() const;
+		/// The line number of the end of the text where the exception occurred.
+		/// The first line is line 1.
+		
+	int getColumnNumber() const;
+		/// The column number of the end of the text where the exception occurred.
+		/// The first column in a line is position 1.
+
+protected:
+	static std::string buildMessage(const std::string& msg, const XMLString& publicId, const XMLString& systemId, int lineNumber, int columnNumber);
+	
+private:
+	SAXParseException();
+
+	XMLString _publicId;
+	XMLString _systemId;
+	int       _lineNumber;
+	int       _columnNumber;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& SAXParseException::getPublicId() const
+{
+	return _publicId;
+}
+
+
+inline const XMLString& SAXParseException::getSystemId() const
+{
+	return _systemId;
+}
+
+
+inline int SAXParseException::getLineNumber() const
+{
+	return _lineNumber;
+}
+
+
+inline int SAXParseException::getColumnNumber() const
+{
+	return _columnNumber;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_SAXException_INCLUDED
diff --git a/Poco/SAX/SAXParser.h b/Poco/SAX/SAXParser.h
new file mode 100644
index 0000000..587e61c
--- /dev/null
+++ b/Poco/SAX/SAXParser.h
@@ -0,0 +1,103 @@
+//
+// SAXParser.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// Implementation of the XMLReader interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_SAXParser_INCLUDED
+#define SAX_SAXParser_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/XMLReader.h"
+#include "Poco/XML/ParserEngine.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API SAXParser: public XMLReader
+	/// This class provides a SAX2 (Simple API for XML) interface to expat, 
+	/// the XML parser toolkit.
+	/// The following SAX2 features and properties are supported:
+	///   * http://xml.org/sax/features/external-general-entities
+	///   * http://xml.org/sax/features/external-parameter-entities
+	///   * http://xml.org/sax/features/namespaces
+	///   * http://xml.org/sax/features/namespace-prefixes
+	///   * http://xml.org/sax/properties/lexical-handler
+	///   * http://xml.org/sax/properties/declaration-handler
+	///
+	/// The following proprietary extensions are supported:
+	///   * http://www.appinf.com/features/enable-partial-reads --
+	///     see ParserEngine::setEnablePartialReads()
+{
+public:
+	SAXParser();
+		/// Creates an SAXParser.
+
+	SAXParser(const XMLString& encoding);
+		/// Creates an SAXParser with the given encoding.
+		
+	~SAXParser();
+		/// Destroys the SAXParser.
+	
+	void setEncoding(const XMLString& encoding);
+		/// Sets the encoding used by the parser if no
+		/// encoding is specified in the XML document.
+		
+	const XMLString& getEncoding() const;
+		/// Returns the name of the encoding used by
+		/// the parser if no encoding is specified in
+		/// the XML document.
+
+	void addEncoding(const XMLString& name, Poco::TextEncoding* pEncoding);
+		/// Adds an encoding to the parser. Does not take ownership of the pointer!
+
+	/// XMLReader
+	void setEntityResolver(EntityResolver* pResolver);
+	EntityResolver* getEntityResolver() const;
+	void setDTDHandler(DTDHandler* pDTDHandler);
+	DTDHandler* getDTDHandler() const;
+	void setContentHandler(ContentHandler* pContentHandler);
+	ContentHandler* getContentHandler() const;
+	void setErrorHandler(ErrorHandler* pErrorHandler);
+	ErrorHandler* getErrorHandler() const;
+	void setFeature(const XMLString& featureId, bool state);
+	bool getFeature(const XMLString& featureId) const;
+	void setProperty(const XMLString& propertyId, const XMLString& value);
+	void setProperty(const XMLString& propertyId, void* value);
+	void* getProperty(const XMLString& propertyId) const;
+	void parse(InputSource* pSource);
+	void parse(const XMLString& systemId);
+	void parseMemoryNP(const char* xml, std::size_t size);
+	
+	/// Extensions
+	void parseString(const std::string& xml);
+	
+	static const XMLString FEATURE_PARTIAL_READS;
+
+protected:
+	void setupParse();
+
+private:
+	ParserEngine _engine;
+	bool _namespaces;
+	bool _namespacePrefixes;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_SAXParser_INCLUDED
diff --git a/Poco/SAX/WhitespaceFilter.h b/Poco/SAX/WhitespaceFilter.h
new file mode 100644
index 0000000..f4f08bc
--- /dev/null
+++ b/Poco/SAX/WhitespaceFilter.h
@@ -0,0 +1,81 @@
+//
+// WhitespaceFilter.h
+//
+// Library: XML
+// Package: SAX
+// Module:  WhitespaceFilter
+//
+// Definition of the WhitespaceFilter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_WhitespaceFilter_INCLUDED
+#define SAX_WhitespaceFilter_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/XMLFilterImpl.h"
+#include "Poco/SAX/LexicalHandler.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API WhitespaceFilter: public XMLFilterImpl, public LexicalHandler
+	/// This implementation of the SAX2 XMLFilter interface
+	/// filters all whitespace-only character data element
+	/// content.
+{
+public:
+	WhitespaceFilter();
+		/// Creates the WhitespaceFilter, with no parent.
+		
+	WhitespaceFilter(XMLReader* pReader);
+		/// Creates the WhitespaceFilter with the specified parent.
+
+	~WhitespaceFilter();
+		/// Destroys the WhitespaceFilter.
+
+	// XMLReader
+	void setProperty(const XMLString& propertyId, const XMLString& value);
+	void setProperty(const XMLString& propertyId, void* value);
+	void* getProperty(const XMLString& propertyId) const;
+
+	// ContentHandler
+	void startDocument();
+	void endDocument();
+	void startElement(const XMLString& uri, const XMLString& localName, const XMLString& qname, const Attributes& attrList);
+	void endElement(const XMLString& uri, const XMLString& localName, const XMLString& qname);
+	void characters(const XMLChar ch[], int start, int length);
+	void ignorableWhitespace(const XMLChar ch[], int start, int length);
+	void processingInstruction(const XMLString& target, const XMLString& data);
+
+	// LexicalHandler
+	void startDTD(const XMLString& name, const XMLString& publicId, const XMLString& systemId);
+	void endDTD();
+	void startEntity(const XMLString& name);
+	void endEntity(const XMLString& name);
+	void startCDATA();
+	void endCDATA();
+	void comment(const XMLChar ch[], int start, int length);
+
+protected:
+	void setupParse();
+
+private:
+	LexicalHandler* _pLexicalHandler;
+	XMLString       _data;
+	bool            _filter;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_WhitespaceFilter_INCLUDED
diff --git a/Poco/SAX/XMLFilter.h b/Poco/SAX/XMLFilter.h
new file mode 100644
index 0000000..0bc2e96
--- /dev/null
+++ b/Poco/SAX/XMLFilter.h
@@ -0,0 +1,61 @@
+//
+// XMLFilter.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAXFilters
+//
+// SAX2 XMLFilter Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_XMLFilter_INCLUDED
+#define SAX_XMLFilter_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/XMLReader.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API XMLFilter: public XMLReader
+	/// Interface for an XML filter.
+	///
+	/// An XML filter is like an XML reader, except that it obtains its events from another XML reader 
+	/// rather than a primary source like an XML document or database. Filters can modify a stream of 
+	/// events as they pass on to the final application.
+	/// 
+	/// The XMLFilterImpl helper class provides a convenient base for creating SAX2 filters, by passing on 
+	/// all EntityResolver, DTDHandler, ContentHandler and ErrorHandler events automatically.
+{
+public:
+	virtual XMLReader* getParent() const = 0;
+		/// Set the parent reader.
+		/// 
+		/// This method allows the application to link the filter to a parent reader (which may be another 
+		/// filter). The argument may not be null.
+		
+	virtual void setParent(XMLReader* pParent) = 0;
+		/// Get the parent reader.
+		/// 
+		/// This method allows the application to query the parent reader (which may be another filter). 
+		/// It is generally a bad idea to perform any operations on the parent reader directly: they should 
+		/// all pass through this filter.
+	
+protected:
+	virtual ~XMLFilter();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_XMLFilter_INCLUDED
diff --git a/Poco/SAX/XMLFilterImpl.h b/Poco/SAX/XMLFilterImpl.h
new file mode 100644
index 0000000..33c049c
--- /dev/null
+++ b/Poco/SAX/XMLFilterImpl.h
@@ -0,0 +1,132 @@
+//
+// XMLFilterImpl.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAXFilters
+//
+// SAX2 XMLFilterImpl class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_XMLFilterImpl_INCLUDED
+#define SAX_XMLFilterImpl_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/XMLFilter.h"
+#include "Poco/SAX/EntityResolver.h"
+#include "Poco/SAX/DTDHandler.h"
+#include "Poco/SAX/ContentHandler.h"
+#include "Poco/SAX/ErrorHandler.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API XMLFilterImpl: public XMLFilter, public EntityResolver, public DTDHandler, public ContentHandler, public ErrorHandler
+	/// Base class for deriving an XML filter.
+	///
+	/// This class is designed to sit between an XMLReader and the client application's event 
+	/// handlers. By default, it does nothing but pass requests up to the reader and events on to 
+	/// the handlers unmodified, but subclasses can override specific methods to modify the event 
+	/// stream or the configuration requests as they pass through.
+{
+public:
+	XMLFilterImpl();
+		/// Construct an empty XML filter, with no parent.
+		///
+		/// This filter will have no parent: you must assign a parent before you start a parse or do any 
+		/// configuration with setFeature or setProperty, unless you use this as a pure event consumer rather 
+		/// than as an XMLReader.
+		
+	XMLFilterImpl(XMLReader* pParent);
+		/// Construct an XML filter with the specified parent.
+		
+	~XMLFilterImpl();
+		/// Destroys the XMLFilterImpl.
+	
+	// XMLFilter
+	XMLReader* getParent() const;
+	void setParent(XMLReader* pParent);
+
+	// XMLReader
+	void setEntityResolver(EntityResolver* pResolver);
+	EntityResolver* getEntityResolver() const;
+	void setDTDHandler(DTDHandler* pDTDHandler);
+	DTDHandler* getDTDHandler() const;
+	void setContentHandler(ContentHandler* pContentHandler);
+	ContentHandler* getContentHandler() const;
+	void setErrorHandler(ErrorHandler* pErrorHandler);
+	ErrorHandler* getErrorHandler() const;
+	void setFeature(const XMLString& featureId, bool state);
+	bool getFeature(const XMLString& featureId) const;
+	void setProperty(const XMLString& propertyId, const XMLString& value);
+	void setProperty(const XMLString& propertyId, void* value);
+	void* getProperty(const XMLString& propertyId) const;
+	void parse(InputSource* pSource);
+	void parse(const XMLString& systemId);
+	void parseMemoryNP(const char* xml, std::size_t size);
+
+	// EntityResolver
+	InputSource* resolveEntity(const XMLString* publicId, const XMLString& systemId);
+	void releaseInputSource(InputSource* pSource);
+	
+	// DTDHandler
+	void notationDecl(const XMLString& name, const XMLString* publicId, const XMLString* systemId);
+	void unparsedEntityDecl(const XMLString& name, const XMLString* publicId, const XMLString& systemId, const XMLString& notationName);
+
+	// ContentHandler
+	void setDocumentLocator(const Locator* loc);
+	void startDocument();
+	void endDocument();
+	void startElement(const XMLString& uri, const XMLString& localName, const XMLString& qname, const Attributes& attrList);
+	void endElement(const XMLString& uri, const XMLString& localName, const XMLString& qname);
+	void characters(const XMLChar ch[], int start, int length);
+	void ignorableWhitespace(const XMLChar ch[], int start, int length);
+	void processingInstruction(const XMLString& target, const XMLString& data);
+	void startPrefixMapping(const XMLString& prefix, const XMLString& uri);
+	void endPrefixMapping(const XMLString& prefix);
+	void skippedEntity(const XMLString& prefix);
+	void warning(const SAXException& e);
+	void error(const SAXException& e);
+	void fatalError(const SAXException& e);
+
+protected:
+	XMLReader* parent() const;
+		/// Return a pointer to the parent reader.
+		/// Subclasses can use this method instead of
+		/// getParent() for better performance - this method
+		/// is non-virtual and implemented as inline.
+	
+	virtual void setupParse();
+		/// Setup the event handlers in the parent reader.
+	
+private:
+	XMLReader*      _pParent;
+	EntityResolver* _pEntityResolver;
+	DTDHandler*     _pDTDHandler;
+	ContentHandler* _pContentHandler;
+	ErrorHandler*   _pErrorHandler;
+};
+
+
+//
+// inlines
+//
+inline XMLReader* XMLFilterImpl::parent() const
+{
+	return _pParent;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_XMLFilterImpl_INCLUDED
diff --git a/Poco/SAX/XMLReader.h b/Poco/SAX/XMLReader.h
new file mode 100644
index 0000000..0b1d360
--- /dev/null
+++ b/Poco/SAX/XMLReader.h
@@ -0,0 +1,205 @@
+//
+// XMLReader.h
+//
+// Library: XML
+// Package: SAX
+// Module:  SAX
+//
+// SAX2 XMLReader Interface.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SAX_XMLReader_INCLUDED
+#define SAX_XMLReader_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class EntityResolver;
+class DTDHandler;
+class ContentHandler;
+class ErrorHandler;
+class InputSource;
+class LexicalHandler;
+class NamespaceHandler;
+
+
+class XML_API XMLReader
+	/// Interface for reading an XML document using callbacks. 
+	/// XMLReader is the interface that an XML parser's SAX2 driver must 
+	/// implement. This interface allows an application to set and
+	/// query features and properties in the parser, to register event handlers 
+	/// for document processing, and to initiate a document parse.
+	/// All SAX interfaces are assumed to be synchronous: the parse methods must not 
+	/// return until parsing is complete, and readers
+	/// must wait for an event-handler callback to return before reporting the next event.
+{
+public:
+	virtual void setEntityResolver(EntityResolver* pResolver) = 0;
+		/// Allow an application to register an entity resolver.
+		///
+		/// If the application does not register an entity resolver, the 
+		/// XMLReader will perform its own default resolution.
+		/// 
+		/// Applications may register a new or different resolver in the middle of a 
+		/// parse, and the SAX parser must begin using the new resolver immediately.
+
+	virtual EntityResolver* getEntityResolver() const = 0;
+		/// Return the current entity resolver.
+
+	virtual void setDTDHandler(DTDHandler* pDTDHandler) = 0;
+		/// Allow an application to register a DTD event handler.
+		///
+		/// If the application does not register a DTD handler, all DTD events reported by 
+		/// the SAX parser will be silently ignored.
+		/// 
+		/// Applications may register a new or different handler in the middle of a parse, 
+		/// and the SAX parser must begin using the new handler immediately.
+
+	virtual DTDHandler* getDTDHandler() const = 0;
+		/// Return the current DTD handler.
+
+	virtual void setContentHandler(ContentHandler* pContentHandler) = 0;
+		/// Allow an application to register a content event handler.
+		/// 
+		/// If the application does not register a content handler, all content events 
+		/// reported by the SAX parser will be silently ignored.
+		/// 
+		/// Applications may register a new or different handler in the middle of a parse, 
+		/// and the SAX parser must begin using the new handler immediately.
+
+	virtual ContentHandler* getContentHandler() const = 0;
+		/// Return the current content handler.
+
+	virtual void setErrorHandler(ErrorHandler* pErrorHandler) = 0;
+		/// Allow an application to register an error event handler.
+		///
+		/// If the application does not register an error handler, all error events reported by 
+		/// the SAX parser will be silently ignored; however, normal processing may not continue. 
+		/// It is highly recommended that all SAX applications implement an error handler to avoid 
+		/// unexpected bugs.
+		/// 
+		/// Applications may register a new or different handler in the middle of a parse, and the 
+		/// SAX parser must begin using the new handler immediately.
+
+	virtual ErrorHandler* getErrorHandler() const = 0;
+		/// Return the current error handler.
+	
+	virtual void setFeature(const XMLString& featureId, bool state) = 0;
+		/// Set the state of a feature.
+		///
+		/// The feature name is any fully-qualified URI. It is possible for an XMLReader to 
+		/// expose a feature value but to be unable to change the current value. Some feature 
+		/// values may be immutable or mutable only in specific contexts, such as before, during, 
+		/// or after a parse.
+		/// 
+		/// All XMLReaders are required to support setting http://xml.org/sax/features/namespaces 
+		/// to true and http://xml.org/sax/features/namespace-prefixes to false.
+
+	virtual bool getFeature(const XMLString& featureId) const = 0;
+		/// Look up the value of a feature.
+		///
+		/// The feature name is any fully-qualified URI. It is possible for an XMLReader 
+		/// to recognize a feature name but temporarily be unable to return its value. 
+		/// Some feature values may be available only in specific contexts, such as before, 
+		/// during, or after a parse. Also, some feature values may not be programmatically 
+		/// accessible. (In the case of an adapter for SAX1 Parser, there is no 
+		/// implementation-independent way to expose whether the underlying parser is performing 
+		/// validation, expanding external entities, and so forth.)
+		/// 
+		/// All XMLReaders are required to recognize the 
+		/// http://xml.org/sax/features/namespaces and the 
+		/// http://xml.org/sax/features/namespace-prefixes feature names.
+		/// Implementors are free (and encouraged) to invent their own features, 
+		/// using names built on their own URIs.
+		
+	virtual void setProperty(const XMLString& propertyId, const XMLString& value) = 0;
+		/// Set the value of a property.
+		/// 
+		/// The property name is any fully-qualified URI. It is possible for an XMLReader 
+		/// to recognize a property name but to be unable to change the current value. 
+		/// Some property values may be immutable or mutable only in specific contexts, 
+		/// such as before, during, or after a parse.
+		/// 
+		/// XMLReaders are not required to recognize setting any specific property names, though a 
+		/// core set is defined by SAX2.
+		/// 
+		/// This method is also the standard mechanism for setting extended handlers.
+
+	virtual void setProperty(const XMLString& propertyId, void* value) = 0;
+		/// Set the value of a property.
+		/// See also setProperty(const XMLString&, const XMLString&).
+
+	virtual void* getProperty(const XMLString& propertyId) const = 0;
+		/// Look up the value of a property.
+		/// String values are returned as XMLChar*
+		/// The property name is any fully-qualified URI. It is possible for an XMLReader to 
+		/// recognize a property name but temporarily be unable to return its value. Some property 
+		/// values may be available only in specific contexts, such as before, during, or after a parse.
+		///
+		/// XMLReaders are not required to recognize any specific property names, though an initial 
+		/// core set is documented for SAX2.
+		/// 
+		/// Implementors are free (and encouraged) to invent their own properties, using names 
+		/// built on their own URIs.
+
+	virtual void parse(InputSource* pSource) = 0;
+		/// Parse an XML document.
+		/// 
+		/// The application can use this method to instruct the XML reader to begin parsing an 
+		/// XML document from any valid input source (a character stream, a byte stream, or a URI).
+		/// 
+		/// Applications may not invoke this method while a parse is in progress (they should create 
+		/// a new XMLReader instead for each nested XML document). Once a parse is complete, an 
+		/// application may reuse the same XMLReader object, possibly with a different input source. 
+		/// Configuration of the XMLReader object (such as handler bindings and values established for 
+		/// feature flags and properties) is unchanged by completion of a parse, unless the definition of that 
+		/// aspect of the configuration explicitly specifies other behavior. (For example, feature flags or 
+		/// properties exposing characteristics of the document being parsed.)
+		/// 
+		/// During the parse, the XMLReader will provide information about the XML document through the registered 
+		/// event handlers.
+		///
+		/// This method is synchronous: it will not return until parsing has ended. If a client application 
+		/// wants to terminate parsing early, it should throw an exception.
+
+	virtual void parse(const XMLString& systemId) = 0;
+		/// Parse an XML document from a system identifier.
+		/// See also parse(InputSource*).
+		
+	virtual void parseMemoryNP(const char* xml, std::size_t size) = 0;
+		/// Parse an XML document from memory.
+		/// See also parse(InputSource*).
+
+	// SAX Features
+	static const XMLString FEATURE_VALIDATION;
+	static const XMLString FEATURE_NAMESPACES;
+	static const XMLString FEATURE_NAMESPACE_PREFIXES;
+	static const XMLString FEATURE_EXTERNAL_GENERAL_ENTITIES;
+	static const XMLString FEATURE_EXTERNAL_PARAMETER_ENTITIES;
+	static const XMLString FEATURE_STRING_INTERNING;
+	
+	// SAX Properties
+	static const XMLString PROPERTY_DECLARATION_HANDLER;
+	static const XMLString PROPERTY_LEXICAL_HANDLER;
+
+protected:
+	virtual ~XMLReader();
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // SAX_XMLReader_INCLUDED
diff --git a/Poco/SHA1Engine.h b/Poco/SHA1Engine.h
new file mode 100644
index 0000000..81c8a4d
--- /dev/null
+++ b/Poco/SHA1Engine.h
@@ -0,0 +1,81 @@
+//
+// SHA1Engine.h
+//
+// Library: Foundation
+// Package: Crypt
+// Module:  SHA1Engine
+//
+// Definition of class SHA1Engine.
+//
+// Secure Hash Standard SHA-1 algorithm
+// (FIPS 180-1, see http://www.itl.nist.gov/fipspubs/fip180-1.htm)
+//
+// Based on the public domain implementation by Peter C. Gutmann
+// on 2 Sep 1992, modified by Carl Ellison to be SHA-1.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SHA1Engine_INCLUDED
+#define Foundation_SHA1Engine_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/DigestEngine.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SHA1Engine: public DigestEngine
+	/// This class implementes the SHA-1 message digest algorithm.
+	/// (FIPS 180-1, see http://www.itl.nist.gov/fipspubs/fip180-1.htm)
+{
+public:
+	enum
+	{
+		BLOCK_SIZE  = 64,
+		DIGEST_SIZE = 20
+	};
+
+	SHA1Engine();
+	~SHA1Engine();
+		
+	std::size_t digestLength() const;
+	void reset();
+	const DigestEngine::Digest& digest();
+
+protected:
+	void updateImpl(const void* data, std::size_t length);
+
+private:
+	void transform();
+	static void byteReverse(UInt32* buffer, int byteCount);
+
+	typedef UInt8 BYTE;
+
+	struct Context
+	{
+		UInt32 digest[5]; // Message digest
+		UInt32 countLo;   // 64-bit bit count
+		UInt32 countHi;
+		UInt32 data[16];  // SHA data buffer
+		UInt32 slop;      // # of bytes saved in data[]
+	};
+
+	Context _context;
+	DigestEngine::Digest _digest;
+
+	SHA1Engine(const SHA1Engine&);
+	SHA1Engine& operator = (const SHA1Engine&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SHA1Engine_INCLUDED
diff --git a/Poco/ScopedLock.h b/Poco/ScopedLock.h
new file mode 100644
index 0000000..8415c38
--- /dev/null
+++ b/Poco/ScopedLock.h
@@ -0,0 +1,121 @@
+//
+// ScopedLock.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the ScopedLock template class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ScopedLock_INCLUDED
+#define Foundation_ScopedLock_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class M>
+class ScopedLock
+	/// A class that simplifies thread synchronization
+	/// with a mutex.
+	/// The constructor accepts a Mutex (and optionally
+	/// a timeout value in milliseconds) and locks it.
+	/// The destructor unlocks the mutex.
+{
+public:
+	explicit ScopedLock(M& mutex): _mutex(mutex)
+	{
+		_mutex.lock();
+	}
+	
+	ScopedLock(M& mutex, long milliseconds): _mutex(mutex)
+	{
+		_mutex.lock(milliseconds);
+	}
+	
+	~ScopedLock()
+	{
+		try
+		{
+			_mutex.unlock();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+private:
+	M& _mutex;
+
+	ScopedLock();
+	ScopedLock(const ScopedLock&);
+	ScopedLock& operator = (const ScopedLock&);
+};
+
+
+template <class M>
+class ScopedLockWithUnlock
+	/// A class that simplifies thread synchronization
+	/// with a mutex.
+	/// The constructor accepts a Mutex (and optionally
+	/// a timeout value in milliseconds) and locks it.
+	/// The destructor unlocks the mutex.
+	/// The unlock() member function allows for manual
+	/// unlocking of the mutex.
+{
+public:
+	explicit ScopedLockWithUnlock(M& mutex): _pMutex(&mutex)
+	{
+		_pMutex->lock();
+	}
+	
+	ScopedLockWithUnlock(M& mutex, long milliseconds): _pMutex(&mutex)
+	{
+		_pMutex->lock(milliseconds);
+	}
+	
+	~ScopedLockWithUnlock()
+	{
+		try
+		{
+			unlock();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+	
+	void unlock()
+	{
+		if (_pMutex)
+		{
+			_pMutex->unlock();
+			_pMutex = 0;
+		}
+	}
+
+private:
+	M* _pMutex;
+
+	ScopedLockWithUnlock();
+	ScopedLockWithUnlock(const ScopedLockWithUnlock&);
+	ScopedLockWithUnlock& operator = (const ScopedLockWithUnlock&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ScopedLock_INCLUDED
diff --git a/Poco/ScopedUnlock.h b/Poco/ScopedUnlock.h
new file mode 100644
index 0000000..a62fbb3
--- /dev/null
+++ b/Poco/ScopedUnlock.h
@@ -0,0 +1,64 @@
+//
+// ScopedUnlock.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Mutex
+//
+// Definition of the ScopedUnlock template class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ScopedUnlock_INCLUDED
+#define Foundation_ScopedUnlock_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class M>
+class ScopedUnlock
+	/// A class that simplifies thread synchronization
+	/// with a mutex.
+	/// The constructor accepts a Mutex and unlocks it.
+	/// The destructor locks the mutex.
+{
+public:
+	inline ScopedUnlock(M& mutex, bool unlockNow = true): _mutex(mutex)
+	{
+		if (unlockNow)
+			_mutex.unlock();
+	}
+	inline ~ScopedUnlock()
+	{
+		try
+		{
+			_mutex.lock();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+private:
+	M& _mutex;
+
+	ScopedUnlock();
+	ScopedUnlock(const ScopedUnlock&);
+	ScopedUnlock& operator = (const ScopedUnlock&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ScopedUnlock_INCLUDED
diff --git a/Poco/Semaphore.h b/Poco/Semaphore.h
new file mode 100644
index 0000000..7c10c4a
--- /dev/null
+++ b/Poco/Semaphore.h
@@ -0,0 +1,137 @@
+//
+// Semaphore.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Semaphore
+//
+// Definition of the Semaphore class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Semaphore_INCLUDED
+#define Foundation_Semaphore_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/Semaphore_WIN32.h"
+#elif defined(POCO_VXWORKS)
+#include "Poco/Semaphore_VX.h"
+#else
+#include "Poco/Semaphore_POSIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API Semaphore: private SemaphoreImpl
+	/// A Semaphore is a synchronization object with the following 
+	/// characteristics:
+	/// A semaphore has a value that is constrained to be a non-negative
+	/// integer and two atomic operations. The allowable operations are V 
+	/// (here called set()) and P (here called wait()). A V (set()) operation 
+	/// increases the value of the semaphore by one. 
+	/// A P (wait()) operation decreases the value of the semaphore by one, 
+	/// provided that can be done without violating the constraint that the 
+	/// value be non-negative. A P (wait()) operation that is initiated when 
+	/// the value of the semaphore is 0 suspends the calling thread. 
+	/// The calling thread may continue when the value becomes positive again.
+{
+public:
+	Semaphore(int n);
+	Semaphore(int n, int max);
+		/// Creates the semaphore. The current value
+		/// of the semaphore is given in n. The
+		/// maximum value of the semaphore is given
+		/// in max.
+		/// If only n is given, it must be greater than
+		/// zero.
+		/// If both n and max are given, max must be
+		/// greater than zero, n must be greater than
+		/// or equal to zero and less than or equal
+		/// to max.
+		
+	~Semaphore();
+		/// Destroys the semaphore.
+
+	void set();
+		/// Increments the semaphore's value by one and
+		/// thus signals the semaphore. Another thread
+		/// waiting for the semaphore will be able
+		/// to continue.
+
+	void wait();
+		/// Waits for the semaphore to become signalled.
+		/// To become signalled, a semaphore's value must
+		/// be greater than zero. 
+		/// Decrements the semaphore's value by one.
+
+	void wait(long milliseconds);
+		/// Waits for the semaphore to become signalled.
+		/// To become signalled, a semaphore's value must
+		/// be greater than zero.
+		/// Throws a TimeoutException if the semaphore
+		/// does not become signalled within the specified
+		/// time interval.
+		/// Decrements the semaphore's value by one
+		/// if successful.
+
+	bool tryWait(long milliseconds);
+		/// Waits for the semaphore to become signalled.
+		/// To become signalled, a semaphore's value must
+		/// be greater than zero.
+		/// Returns true if the semaphore
+		/// became signalled within the specified
+		/// time interval, false otherwise.
+		/// Decrements the semaphore's value by one
+		/// if successful.
+	
+private:
+	Semaphore();
+	Semaphore(const Semaphore&);
+	Semaphore& operator = (const Semaphore&);
+};
+
+
+//
+// inlines
+//
+inline void Semaphore::set()
+{
+	setImpl();
+}
+
+
+inline void Semaphore::wait()
+{
+	waitImpl();
+}
+
+
+inline void Semaphore::wait(long milliseconds)
+{
+	if (!waitImpl(milliseconds))
+		throw TimeoutException();
+}
+
+
+inline bool Semaphore::tryWait(long milliseconds)
+{
+	return waitImpl(milliseconds);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Semaphore_INCLUDED
diff --git a/Poco/Semaphore_POSIX.h b/Poco/Semaphore_POSIX.h
new file mode 100644
index 0000000..3fc0897
--- /dev/null
+++ b/Poco/Semaphore_POSIX.h
@@ -0,0 +1,75 @@
+//
+// Semaphore_POSIX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Semaphore
+//
+// Definition of the SemaphoreImpl class for POSIX Threads.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Semaphore_POSIX_INCLUDED
+#define Foundation_Semaphore_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <pthread.h>
+#include <errno.h>
+
+
+namespace Poco {
+
+
+class Foundation_API SemaphoreImpl
+{
+protected:
+	SemaphoreImpl(int n, int max);		
+	~SemaphoreImpl();
+	void setImpl();
+	void waitImpl();
+	bool waitImpl(long milliseconds);
+	
+private:
+	volatile int    _n;
+	int             _max;
+	pthread_mutex_t _mutex;
+	pthread_cond_t  _cond;
+};
+
+
+//
+// inlines
+//
+inline void SemaphoreImpl::setImpl()
+{
+	if (pthread_mutex_lock(&_mutex))	
+		throw SystemException("cannot signal semaphore (lock)");
+	if (_n < _max)
+	{
+		++_n;
+	}
+	else
+	{
+		pthread_mutex_unlock(&_mutex);
+		throw SystemException("cannot signal semaphore: count would exceed maximum");
+	}	
+	if (pthread_cond_signal(&_cond))
+	{
+		pthread_mutex_unlock(&_mutex);
+		throw SystemException("cannot signal semaphore");
+	}
+	pthread_mutex_unlock(&_mutex);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Semaphore_POSIX_INCLUDED
diff --git a/Poco/Semaphore_VX.h b/Poco/Semaphore_VX.h
new file mode 100644
index 0000000..181afe2
--- /dev/null
+++ b/Poco/Semaphore_VX.h
@@ -0,0 +1,56 @@
+//
+// Semaphore_VX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Semaphore
+//
+// Definition of the SemaphoreImpl class for VxWorks.
+//
+// Copyright (c) 2004-20011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Semaphore_VX_INCLUDED
+#define Foundation_Semaphore_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <semLib.h>
+
+
+namespace Poco {
+
+
+class Foundation_API SemaphoreImpl
+{
+protected:
+	SemaphoreImpl(int n, int max);		
+	~SemaphoreImpl();
+	void setImpl();
+	void waitImpl();
+	bool waitImpl(long milliseconds);
+	
+private:
+	SEM_ID _sem;
+};
+
+
+//
+// inlines
+//
+inline void SemaphoreImpl::setImpl()
+{
+	if (semGive(_sem) != OK)
+		throw SystemException("cannot signal semaphore");
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Semaphore_VX_INCLUDED
diff --git a/Poco/Semaphore_WIN32.h b/Poco/Semaphore_WIN32.h
new file mode 100644
index 0000000..ac9c313
--- /dev/null
+++ b/Poco/Semaphore_WIN32.h
@@ -0,0 +1,58 @@
+//
+// Semaphore_WIN32.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Semaphore
+//
+// Definition of the SemaphoreImpl class for WIN32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Semaphore_WIN32_INCLUDED
+#define Foundation_Semaphore_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SemaphoreImpl
+{
+protected:
+	SemaphoreImpl(int n, int max);		
+	~SemaphoreImpl();
+	void setImpl();
+	void waitImpl();
+	bool waitImpl(long milliseconds);
+	
+private:
+	HANDLE _sema;
+};
+
+
+//
+// inlines
+//
+inline void SemaphoreImpl::setImpl()
+{
+	if (!ReleaseSemaphore(_sema, 1, NULL))
+	{
+		throw SystemException("cannot signal semaphore");
+	}
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Semaphore_WIN32_INCLUDED
diff --git a/Poco/SevenZip/Archive.h b/Poco/SevenZip/Archive.h
new file mode 100644
index 0000000..e119d21
--- /dev/null
+++ b/Poco/SevenZip/Archive.h
@@ -0,0 +1,119 @@
+//
+// Archive.h
+//
+// Library: SevenZip
+// Package: Archive
+// Module:  Archive
+//
+// Definition of the Archive class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SevenZip_Archive_INCLUDED
+#define SevenZip_Archive_INCLUDED
+
+
+#include "Poco/SevenZip/SevenZip.h"
+#include "Poco/SevenZip/ArchiveEntry.h"
+#include "Poco/BasicEvent.h"
+#include <vector>
+#include <utility>
+
+
+namespace Poco {
+namespace SevenZip {
+
+
+class ArchiveImpl;
+
+
+class SevenZip_API Archive
+	/// This class represents a 7-Zip archive. 
+	///
+	/// The Archive class can be used to enumerate entries in a
+	/// 7-Zip archive, and to extract files or directories from
+	/// an archive.
+{
+public:
+	typedef std::vector<ArchiveEntry> EntryVec;
+	typedef EntryVec::iterator Iterator;
+	typedef EntryVec::const_iterator ConstIterator;
+	
+	struct ExtractedEventArgs
+	{
+		ArchiveEntry entry;
+		std::string extractedPath;
+	};
+	
+	struct FailedEventArgs
+	{
+		ArchiveEntry entry;
+		Poco::Exception* pException;
+	};
+		
+	Poco::BasicEvent<const ExtractedEventArgs> extracted;
+		/// Fired when an archive entry has been successfully extracted.
+		
+	Poco::BasicEvent<const FailedEventArgs> failed;
+		/// Fired when extracting an archive entry failed.
+
+	Archive(const std::string& path);
+		/// Creates an Archive object for the 7-Zip archive
+		/// with the given path. 
+		
+	~Archive();
+		/// Destroys the Archive.
+	
+	const std::string& path() const;
+		/// Returns the path of the archive in the filesystem.
+		
+	std::size_t size() const;
+		/// Returns the number of entries in the archive.
+	
+	ConstIterator begin() const;
+		/// Returns an iterator for iterating over the
+		/// file or directory entries in the archive.
+		
+	ConstIterator end() const;
+		/// Returns the end iterator.
+
+	void extract(const std::string& destPath);
+		/// Extracts the entire archive to the given path.
+		///
+		/// Directories will be created as necessary. File attributes
+		/// will not be restored.
+		///
+		/// Progress and errors for single entries will be reported
+		/// via the extracted and failed events.
+		
+	std::string extract(const ArchiveEntry& entry, const std::string& destPath);
+		/// Extracts a specific entry to the given path.
+		/// 
+		/// Directories will be created as necessary. File attributes
+		/// will not be restored.
+		///
+		/// Returns the absolute path of the extracted entry.
+
+private:
+	Archive();
+	Archive(const Archive&);
+	Archive& operator = (const Archive&);
+
+	ArchiveImpl* _pImpl;
+};
+
+
+//
+// inlines
+//
+
+
+} } // namespace Poco::SevenZip
+
+
+#endif // SevenZip_ArchiveEntry_INCLUDED
diff --git a/Poco/SevenZip/ArchiveEntry.h b/Poco/SevenZip/ArchiveEntry.h
new file mode 100644
index 0000000..278161c
--- /dev/null
+++ b/Poco/SevenZip/ArchiveEntry.h
@@ -0,0 +1,164 @@
+//
+// ArchiveEntry.h
+//
+// Library: SevenZip
+// Package: Archive
+// Module:  ArchiveEntry
+//
+// Definition of the ArchiveEntry class.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SevenZip_ArchiveEntry_INCLUDED
+#define SevenZip_ArchiveEntry_INCLUDED
+
+
+#include "Poco/SevenZip/SevenZip.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+namespace SevenZip {
+
+
+class SevenZip_API ArchiveEntry
+	/// This class represents an entry in 7-Zip archive. The entry can
+	/// be a file or a directory, with a path, modification date/time,
+	/// original size and file attributes.
+	///
+	/// File attributes are based on those supported on Windows and are
+	/// not of much use on non-Windows platforms.
+{
+public:
+	enum EntryType
+	{
+		ENTRY_FILE      = 0,   /// The entry represents an ordinary file.
+		ENTRY_DIRECTORY = 1    /// The entry represents a directory.
+	};
+	
+	enum EntryAttributes
+	{
+		ATTR_READONLY  = 0x01, /// The file or directory is read-only.
+		ATTR_HIDDEN    = 0x02, /// The file or directory is hidden.
+		ATTR_SYSTEM    = 0x04, /// The file or directory is used by the operating system.
+		ATTR_DIRECTORY = 0x10, /// The entry is a directory.
+		ATTR_ARCHIVE   = 0x20  /// The file or directory is marked for backup or removal.
+	};
+
+	ArchiveEntry();
+		/// Creates an empty ArchiveEntry;
+
+	ArchiveEntry(const ArchiveEntry& entry);
+		/// Creates an ArchiveEntry by copying another one.
+		
+	~ArchiveEntry();
+		/// Destroys the ArchiveEntry.
+		
+	ArchiveEntry& operator = (const ArchiveEntry& entry);
+		/// Assignment operator.
+	
+	void swap(ArchiveEntry& entry);
+		/// Swaps the entry with another one.
+	
+	EntryType type() const;
+		/// Returns the type of the entry.	
+		
+	const std::string& path() const;
+		/// Return the UTF-8 encoded path.
+		
+	Poco::UInt64 size() const;
+		/// Returns the original size of the file.
+		
+	Poco::Timestamp lastModified() const;
+		/// Returns the date and time of last modification.
+
+	Poco::UInt32 attributes() const;
+		/// Returns the entry attributes as a bitmask.
+		///
+		/// See the EntryAttributes enumeration for valid values.
+		
+	bool isFile() const;
+		/// Returns true iff the entry represents a file.
+		
+	bool isDirectory() const;
+		/// Returns true iff the entry represents a directory.
+
+protected:
+	ArchiveEntry(EntryType type, const std::string& path, Poco::UInt64 size, Poco::Timestamp lastModified, Poco::UInt32 attributes, Poco::UInt32 index);
+		/// Creates an ArchiveEntry.
+
+	Poco::UInt32 index() const;
+		/// Returns the index of the entry within the archive.
+
+private:
+	EntryType _type;
+	std::string _path;
+	Poco::UInt64 _size;
+	Poco::Timestamp _lastModified;
+	Poco::UInt32 _attributes;
+	Poco::UInt32 _index;
+	
+	friend class ArchiveImpl;
+};
+
+
+//
+// inlines
+//
+inline ArchiveEntry::EntryType ArchiveEntry::type() const
+{
+	return _type;
+}
+
+
+inline const std::string& ArchiveEntry::path() const
+{
+	return _path;
+}
+
+	
+inline Poco::UInt64 ArchiveEntry::size() const
+{
+	return _size;
+}
+
+	
+inline Poco::Timestamp ArchiveEntry::lastModified() const
+{
+	return _lastModified;
+}
+
+
+inline Poco::UInt32 ArchiveEntry::attributes() const
+{
+	return _attributes;
+}
+
+
+inline Poco::UInt32 ArchiveEntry::index() const
+{
+	return _index;
+}
+
+
+inline bool ArchiveEntry::isFile() const
+{
+	return _type == ENTRY_FILE;
+}
+
+
+inline bool ArchiveEntry::isDirectory() const
+{
+	return _type == ENTRY_DIRECTORY;
+}
+
+
+} } // namespace Poco::SevenZip
+
+
+#endif // SevenZip_ArchiveEntry_INCLUDED
diff --git a/Poco/SevenZip/SevenZip.h b/Poco/SevenZip/SevenZip.h
new file mode 100644
index 0000000..f377b52
--- /dev/null
+++ b/Poco/SevenZip/SevenZip.h
@@ -0,0 +1,62 @@
+//
+// SevenZip.h
+//
+// Library: SevenZip
+// Package: SevenZip
+// Module:  SevenZip
+//
+// Basic definitions for the Poco SevenZip library.
+// This file must be the first file included by every other SevenZip
+// header file.
+//
+// Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef SevenZip_SevenZip_INCLUDED
+#define SevenZip_SevenZip_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the SevenZip_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// SevenZip_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(SevenZip_EXPORTS)
+		#define SevenZip_API __declspec(dllexport)
+	#else
+		#define SevenZip_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(SevenZip_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define SevenZip_API __attribute__ ((visibility ("default")))
+	#else
+		#define SevenZip_API
+	#endif
+#endif
+
+
+//
+// Automatically link SevenZip library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(SevenZip_EXPORTS)
+		#pragma comment(lib, "PocoSevenZip" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // SevenZip_SevenZip_INCLUDED
diff --git a/Poco/SharedLibrary.h b/Poco/SharedLibrary.h
new file mode 100644
index 0000000..83af4bd
--- /dev/null
+++ b/Poco/SharedLibrary.h
@@ -0,0 +1,134 @@
+//
+// SharedLibrary.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  SharedLibrary
+//
+// Definition of the SharedLibrary class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedLibrary_INCLUDED
+#define Foundation_SharedLibrary_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(hpux) || defined(_hpux)
+#include "Poco/SharedLibrary_HPUX.h"
+#elif defined(POCO_VXWORKS)
+#include "Poco/SharedLibrary_VX.h"
+#elif defined(POCO_OS_FAMILY_UNIX)
+#include "Poco/SharedLibrary_UNIX.h"
+#elif defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
+#include "Poco/SharedLibrary_WIN32U.h"
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/SharedLibrary_WIN32.h"
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API SharedLibrary: private SharedLibraryImpl
+	/// The SharedLibrary class dynamically
+	/// loads shared libraries at run-time.
+{
+public:
+	enum Flags
+	{
+		SHLIB_GLOBAL = 1,
+			/// On platforms that use dlopen(), use RTLD_GLOBAL. This is the default
+			/// if no flags are given.
+			///
+			/// This flag is ignored on platforms that do not use dlopen().
+
+		SHLIB_LOCAL  = 2
+			/// On platforms that use dlopen(), use RTLD_LOCAL instead of RTLD_GLOBAL.
+			///
+			/// Note that if this flag is specified, RTTI (including dynamic_cast and throw) will
+			/// not work for types defined in the shared library with GCC and possibly other
+			/// compilers as well. See http://gcc.gnu.org/faq.html#dso for more information.
+			///
+			/// This flag is ignored on platforms that do not use dlopen().
+	};
+
+	SharedLibrary();
+		/// Creates a SharedLibrary object.
+
+	SharedLibrary(const std::string& path);
+		/// Creates a SharedLibrary object and loads a library
+		/// from the given path.
+
+	SharedLibrary(const std::string& path, int flags);
+		/// Creates a SharedLibrary object and loads a library
+		/// from the given path, using the given flags.
+		/// See the Flags enumeration for valid values.
+
+	virtual ~SharedLibrary();
+		/// Destroys the SharedLibrary. The actual library
+		/// remains loaded.
+
+	void load(const std::string& path);
+		/// Loads a shared library from the given path.
+		/// Throws a LibraryAlreadyLoadedException if
+		/// a library has already been loaded.
+		/// Throws a LibraryLoadException if the library
+		/// cannot be loaded.
+
+	void load(const std::string& path, int flags);
+		/// Loads a shared library from the given path,
+		/// using the given flags. See the Flags enumeration
+		/// for valid values.
+		/// Throws a LibraryAlreadyLoadedException if
+		/// a library has already been loaded.
+		/// Throws a LibraryLoadException if the library
+		/// cannot be loaded.
+
+	void unload();
+		/// Unloads a shared library.
+
+	bool isLoaded() const;
+		/// Returns true iff a library has been loaded.
+
+	bool hasSymbol(const std::string& name);
+		/// Returns true iff the loaded library contains
+		/// a symbol with the given name.
+
+	void* getSymbol(const std::string& name);
+		/// Returns the address of the symbol with
+		/// the given name. For functions, this
+		/// is the entry point of the function.
+		/// Throws a NotFoundException if the symbol
+		/// does not exist.
+
+	const std::string& getPath() const;
+		/// Returns the path of the library, as
+		/// specified in a call to load() or the
+		/// constructor.
+
+	static std::string suffix();
+		/// Returns the platform-specific filename suffix
+		/// for shared libraries (including the period).
+		/// In debug mode, the suffix also includes a
+		/// "d" to specify the debug version of a library
+		/// (e.g., "d.so", "d.dll") unless the library has
+		/// been compiled with -DPOCO_NO_SHARED_LIBRARY_DEBUG_SUFFIX.
+
+private:
+	SharedLibrary(const SharedLibrary&);
+	SharedLibrary& operator = (const SharedLibrary&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedLibrary_INCLUDED
diff --git a/Poco/SharedLibrary_HPUX.h b/Poco/SharedLibrary_HPUX.h
new file mode 100644
index 0000000..cfb1955
--- /dev/null
+++ b/Poco/SharedLibrary_HPUX.h
@@ -0,0 +1,51 @@
+//
+// SharedLibrary_HPUX.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  SharedLibrary
+//
+// Definition of the SharedLibraryImpl class for HP-UX.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedLibrary_HPUX_INCLUDED
+#define Foundation_SharedLibrary_HPUX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include <dl.h>
+
+
+namespace Poco {
+
+
+class Foundation_API SharedLibraryImpl
+{
+protected:
+	SharedLibraryImpl();
+	~SharedLibraryImpl();
+	void loadImpl(const std::string& path, int flags);
+	void unloadImpl();
+	bool isLoadedImpl() const;
+	void* findSymbolImpl(const std::string& name);
+	const std::string& getPathImpl() const;
+	static std::string suffixImpl();
+
+private:
+	std::string _path;
+	shl_t _handle;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedLibrary_HPUX_INCLUDED
diff --git a/Poco/SharedLibrary_UNIX.h b/Poco/SharedLibrary_UNIX.h
new file mode 100644
index 0000000..66d1a5a
--- /dev/null
+++ b/Poco/SharedLibrary_UNIX.h
@@ -0,0 +1,56 @@
+//
+// SharedLibrary_UNIX.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  SharedLibrary
+//
+// Definition of the SharedLibraryImpl class for UNIX (dlopen).
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedLibrary_UNIX_INCLUDED
+#define Foundation_SharedLibrary_UNIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SharedLibraryImpl
+{
+protected:
+	enum Flags
+	{
+		SHLIB_GLOBAL_IMPL = 1,
+		SHLIB_LOCAL_IMPL  = 2  
+	};
+
+	SharedLibraryImpl();
+	~SharedLibraryImpl();
+	void loadImpl(const std::string& path, int flags);
+	void unloadImpl();
+	bool isLoadedImpl() const;
+	void* findSymbolImpl(const std::string& name);
+	const std::string& getPathImpl() const;
+	static std::string suffixImpl();
+
+private:
+	std::string _path;
+	void* _handle;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedLibrary_UNIX_INCLUDED
diff --git a/Poco/SharedLibrary_VX.h b/Poco/SharedLibrary_VX.h
new file mode 100644
index 0000000..80dda66
--- /dev/null
+++ b/Poco/SharedLibrary_VX.h
@@ -0,0 +1,51 @@
+//
+// SharedLibrary_VX.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  SharedLibrary
+//
+// Definition of the SharedLibraryImpl class for VxWorks.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedLibrary_VX_INCLUDED
+#define Foundation_SharedLibrary_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include <moduleLib.h>
+
+
+namespace Poco {
+
+
+class Foundation_API SharedLibraryImpl
+{
+protected:
+	SharedLibraryImpl();
+	~SharedLibraryImpl();
+	void loadImpl(const std::string& path, int flags);
+	void unloadImpl();
+	bool isLoadedImpl() const;
+	void* findSymbolImpl(const std::string& name);
+	const std::string& getPathImpl() const;
+	static std::string suffixImpl();
+
+private:
+	std::string _path;
+	MODULE_ID _moduleId;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedLibrary_VX_INCLUDED
diff --git a/Poco/SharedLibrary_WIN32.h b/Poco/SharedLibrary_WIN32.h
new file mode 100644
index 0000000..4bfe338
--- /dev/null
+++ b/Poco/SharedLibrary_WIN32.h
@@ -0,0 +1,50 @@
+//
+// SharedLibrary_WIN32.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  SharedLibrary
+//
+// Definition of the SharedLibraryImpl class for Win32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedLibrary_WIN32_INCLUDED
+#define Foundation_SharedLibrary_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SharedLibraryImpl
+{
+protected:
+	SharedLibraryImpl();
+	~SharedLibraryImpl();
+	void loadImpl(const std::string& path, int flags);
+	void unloadImpl();
+	bool isLoadedImpl() const;
+	void* findSymbolImpl(const std::string& name);
+	const std::string& getPathImpl() const;
+	static std::string suffixImpl();
+
+private:
+	std::string _path;
+	void* _handle;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedLibrary_WIN32_INCLUDED
diff --git a/Poco/SharedLibrary_WIN32U.h b/Poco/SharedLibrary_WIN32U.h
new file mode 100644
index 0000000..ee6a87b
--- /dev/null
+++ b/Poco/SharedLibrary_WIN32U.h
@@ -0,0 +1,50 @@
+//
+// SharedLibrary_WIN32U.h
+//
+// Library: Foundation
+// Package: SharedLibrary
+// Module:  SharedLibrary
+//
+// Definition of the SharedLibraryImpl class for Win32.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedLibrary_WIN32U_INCLUDED
+#define Foundation_SharedLibrary_WIN32U_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SharedLibraryImpl
+{
+protected:
+	SharedLibraryImpl();
+	~SharedLibraryImpl();
+	void loadImpl(const std::string& path, int flags);
+	void unloadImpl();
+	bool isLoadedImpl() const;
+	void* findSymbolImpl(const std::string& name);
+	const std::string& getPathImpl() const;
+	static std::string suffixImpl();
+
+private:
+	std::string _path;
+	void* _handle;
+	static FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedLibrary_WIN32U_INCLUDED
diff --git a/Poco/SharedMemory.h b/Poco/SharedMemory.h
new file mode 100644
index 0000000..2338567
--- /dev/null
+++ b/Poco/SharedMemory.h
@@ -0,0 +1,113 @@
+//
+// SharedMemory.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  SharedMemory
+//
+// Definition of the SharedMemory class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedMemory_INCLUDED
+#define Foundation_SharedMemory_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <algorithm>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class SharedMemoryImpl;
+class File;
+
+
+class Foundation_API SharedMemory
+	/// Create and manage a shared memory object.
+	///
+	/// A SharedMemory object has value semantics, but
+	/// is implemented using a handle/implementation idiom.
+	/// Therefore, multiple SharedMemory objects can share
+	/// a single, reference counted SharedMemoryImpl object.
+{
+public:
+	enum AccessMode
+	{
+		AM_READ = 0,
+		AM_WRITE
+	};
+
+	SharedMemory();
+		/// Default constructor creates an unmapped SharedMemory object. 
+		/// No clients can connect to an unmapped SharedMemory object.
+
+	SharedMemory(const std::string& name, std::size_t size, AccessMode mode, const void* addrHint = 0, bool server = true);
+		/// Creates or connects to a shared memory object with the given name.
+		///
+		/// For maximum portability, name should be a valid Unix filename and not
+		/// contain any slashes or backslashes.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+		///
+		/// If server is set to true, the shared memory region will be unlinked
+		/// by calling shm_unlink() (on POSIX platforms) when the SharedMemory object is destroyed.
+		/// The server parameter is ignored on Windows platforms.
+
+	SharedMemory(const File& file, AccessMode mode, const void* addrHint = 0);
+		/// Maps the entire contents of file into a shared memory segment.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+
+	SharedMemory(const SharedMemory& other);
+		/// Creates a SharedMemory object by copying another one.
+
+	~SharedMemory();
+		/// Destroys the SharedMemory.
+
+	SharedMemory& operator = (const SharedMemory& other);
+		/// Assigns another SharedMemory object.
+
+	void swap(SharedMemory& other);
+		/// Swaps the SharedMemory object with another one.
+
+	char* begin() const;
+		/// Returns the start address of the shared memory segment.
+		/// Will be NULL for illegal segments.
+
+	char* end() const;
+		/// Returns the one-past-end end address of the shared memory segment. 
+		/// Will be NULL for illegal segments.
+
+private:
+	SharedMemoryImpl* _pImpl;
+};
+
+
+//
+// inlines
+//
+inline void SharedMemory::swap(SharedMemory& other)
+{
+	using std::swap;
+	swap(_pImpl, other._pImpl);
+}
+
+
+} // namespace Poco::Poco
+
+
+#endif // Foundation_SharedMemory_INCLUDED
diff --git a/Poco/SharedMemory_DUMMY.h b/Poco/SharedMemory_DUMMY.h
new file mode 100644
index 0000000..5a487a0
--- /dev/null
+++ b/Poco/SharedMemory_DUMMY.h
@@ -0,0 +1,88 @@
+//
+// SharedMemoryImpl.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  SharedMemoryImpl
+//
+// Definition of the SharedMemoryImpl class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedMemoryImpl_INCLUDED
+#define Foundation_SharedMemoryImpl_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/SharedMemory.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SharedMemoryImpl: public RefCountedObject
+	/// A dummy implementation of shared memory, for systems
+	/// that do not have shared memory support.
+{
+public:
+	SharedMemoryImpl(const std::string& id, std::size_t size, SharedMemory::AccessMode mode, const void* addr, bool server);
+		/// Creates or connects to a shared memory object with the given name.
+		///
+		/// For maximum portability, name should be a valid Unix filename and not
+		/// contain any slashes or backslashes.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+
+	SharedMemoryImpl(const Poco::File& aFile, SharedMemory::AccessMode mode, const void* addr);
+		/// Maps the entire contents of file into a shared memory segment.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+
+	char* begin() const;
+		/// Returns the start address of the shared memory segment.
+
+	char* end() const;
+		/// Returns the one-past-end end address of the shared memory segment. 
+
+protected:
+	~SharedMemoryImpl();
+		/// Destroys the SharedMemoryImpl.
+
+private:
+	SharedMemoryImpl();
+	SharedMemoryImpl(const SharedMemoryImpl&);
+	SharedMemoryImpl& operator = (const SharedMemoryImpl&);
+};
+
+
+//
+// inlines
+//
+inline char* SharedMemoryImpl::begin() const
+{
+	return 0;
+}
+
+
+inline char* SharedMemoryImpl::end() const
+{
+	return 0;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedMemoryImpl_INCLUDED
diff --git a/Poco/SharedMemory_POSIX.h b/Poco/SharedMemory_POSIX.h
new file mode 100644
index 0000000..4ba6ab5
--- /dev/null
+++ b/Poco/SharedMemory_POSIX.h
@@ -0,0 +1,107 @@
+//
+// SharedMemoryImpl.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  SharedMemoryImpl
+//
+// Definition of the SharedMemoryImpl class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedMemoryImpl_INCLUDED
+#define Foundation_SharedMemoryImpl_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/SharedMemory.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SharedMemoryImpl: public RefCountedObject
+	/// Shared memory implementation for POSIX platforms.
+{
+public:
+	SharedMemoryImpl(const std::string& name, std::size_t size, SharedMemory::AccessMode mode, const void* addrHint, bool server);
+		/// Creates or connects to a shared memory object with the given name.
+		///
+		/// For maximum portability, name should be a valid Unix filename and not
+		/// contain any slashes or backslashes.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+		///
+		/// If server is set to false, the shared memory region will be unlinked
+		/// by calling shm_unlink when the SharedMemory object is destroyed.
+
+	SharedMemoryImpl(const Poco::File& file, SharedMemory::AccessMode mode, const void* addrHint);
+		/// Maps the entire contents of file into a shared memory segment.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+
+	char* begin() const;
+		/// Returns the start address of the shared memory segment.
+
+	char* end() const;
+		/// Returns the one-past-end end address of the shared memory segment. 
+
+protected:
+	void map(const void* addrHint);
+		/// Maps the shared memory object.
+
+	void unmap();
+		/// Unmaps the shared memory object.
+
+	void close();
+		/// Releases the handle for the shared memory segment.
+
+	~SharedMemoryImpl();
+		/// Destroys the SharedMemoryImpl.
+
+private:
+	SharedMemoryImpl();
+	SharedMemoryImpl(const SharedMemoryImpl&);
+	SharedMemoryImpl& operator = (const SharedMemoryImpl&);
+
+	std::size_t _size;
+	int         _fd;
+	char*       _address;
+	SharedMemory::AccessMode _access;
+	std::string _name;
+	bool        _fileMapped;
+	bool        _server;
+};
+
+
+//
+// inlines
+//
+inline char* SharedMemoryImpl::begin() const
+{
+	return _address;
+}
+
+
+inline char* SharedMemoryImpl::end() const
+{
+	return _address + _size;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedMemoryImpl_INCLUDED
diff --git a/Poco/SharedMemory_WIN32.h b/Poco/SharedMemory_WIN32.h
new file mode 100644
index 0000000..bd48b69
--- /dev/null
+++ b/Poco/SharedMemory_WIN32.h
@@ -0,0 +1,103 @@
+//
+// SharedMemoryImpl.h
+//
+// Library: Foundation
+// Package: Processes
+// Module:  SharedMemoryImpl
+//
+// Definition of the SharedMemoryImpl class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedMemoryImpl_INCLUDED
+#define Foundation_SharedMemoryImpl_INCLUDED
+
+
+#include "Poco/Poco.h"
+#include "Poco/SharedMemory.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SharedMemoryImpl: public RefCountedObject
+	/// Shared memory implementation for Windows platforms.
+{
+public:
+	SharedMemoryImpl(const std::string& name, std::size_t size, SharedMemory::AccessMode mode, const void* addrHint, bool server);
+		/// Creates or connects to a shared memory object with the given name.
+		///
+		/// For maximum portability, name should be a valid Unix filename and not
+		/// contain any slashes or backslashes.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+
+	SharedMemoryImpl(const Poco::File& file, SharedMemory::AccessMode mode, const void* addrHint);
+		/// Maps the entire contents of file into a shared memory segment.
+		///
+		/// An address hint can be passed to the system, specifying the desired
+		/// start address of the shared memory area. Whether the hint
+		/// is actually honored is, however, up to the system. Windows platform
+		/// will generally ignore the hint.
+
+	char* begin() const;
+		/// Returns the beginn address of the SharedMemory segment. Will be null for illegal segments.
+
+	char* end() const;
+		/// Points past the last byte of the end address of the SharedMemory segment. Will be null for illegal segments.
+
+protected:
+	void map();
+		/// Maps the shared memory object.
+
+	void unmap();
+		/// Unmaps the shared memory object.
+
+	void close();
+		/// Releases the handle for the shared memory segment.
+
+	~SharedMemoryImpl();
+		/// Destroys the SharedMemoryImpl.
+
+private:
+	SharedMemoryImpl();
+	SharedMemoryImpl(const SharedMemoryImpl&);
+	SharedMemoryImpl& operator = (const SharedMemoryImpl&);
+
+	std::string _name;
+	HANDLE  _memHandle;
+	HANDLE  _fileHandle;
+	DWORD   _size;
+	DWORD   _mode;
+	char*   _address;
+};
+
+
+//
+// inlines
+//
+inline char* SharedMemoryImpl::begin() const
+{
+	return _address;
+}
+
+
+inline char* SharedMemoryImpl::end() const
+{
+	return _address + _size;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedMemoryImpl_INCLUDED
diff --git a/Poco/SharedPtr.h b/Poco/SharedPtr.h
new file mode 100644
index 0000000..899d448
--- /dev/null
+++ b/Poco/SharedPtr.h
@@ -0,0 +1,448 @@
+//
+// SharedPtr.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  SharedPtr
+//
+// Definition of the SharedPtr template class.
+//
+// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SharedPtr_INCLUDED
+#define Foundation_SharedPtr_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/AtomicCounter.h"
+#include <algorithm>
+
+
+namespace Poco {
+
+
+class ReferenceCounter
+	/// Simple ReferenceCounter object, does not delete itself when count reaches 0.
+{
+public:
+	ReferenceCounter(): _cnt(1)
+	{
+	}
+
+	void duplicate()
+	{
+		++_cnt;
+	}
+
+	int release()
+	{
+		return --_cnt;
+	}
+	
+	int referenceCount() const
+	{
+		return _cnt.value();
+	}
+
+private:
+	AtomicCounter _cnt;
+};
+
+
+template <class C>
+class ReleasePolicy
+	/// The default release policy for SharedPtr, which
+	/// simply uses the delete operator to delete an object.
+{
+public:
+	static void release(C* pObj)
+		/// Delete the object.
+		/// Note that pObj can be 0.
+	{
+		delete pObj;
+	}
+};
+
+
+template <class C>
+class ReleaseArrayPolicy
+	/// The release policy for SharedPtr holding arrays.
+{
+public:
+	static void release(C* pObj)
+		/// Delete the object.
+		/// Note that pObj can be 0.
+	{
+		delete [] pObj;
+	}
+};
+
+
+template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >
+class SharedPtr
+	/// SharedPtr is a "smart" pointer for classes implementing
+	/// reference counting based garbage collection.
+	/// SharedPtr is thus similar to AutoPtr. Unlike the
+	/// AutoPtr template, which can only be used with
+	/// classes that support reference counting, SharedPtr
+	/// can be used with any class. For this to work, a
+	/// SharedPtr manages a reference count for the object
+	/// it manages.
+	/// 
+	/// SharedPtr works in the following way:
+	/// If an SharedPtr is assigned an ordinary pointer to
+	/// an object (via the constructor or the assignment operator),
+	/// it takes ownership of the object and the object's reference 
+	/// count is initialized to one.
+	/// If the SharedPtr is assigned another SharedPtr, the
+	/// object's reference count is incremented by one.
+	/// The destructor of SharedPtr decrements the object's
+	/// reference count by one and deletes the object if the
+	/// reference count reaches zero.
+	/// SharedPtr supports dereferencing with both the ->
+	/// and the * operator. An attempt to dereference a null
+	/// SharedPtr results in a NullPointerException being thrown.
+	/// SharedPtr also implements all relational operators and
+	/// a cast operator in case dynamic casting of the encapsulated data types
+	/// is required.
+{
+public:
+	SharedPtr(): _pCounter(new RC), _ptr(0)
+	{
+	}
+
+	SharedPtr(C* ptr)
+	try:
+		_pCounter(new RC), 
+		_ptr(ptr)
+	{
+	}
+	catch (...) 
+	{
+		RP::release(ptr);
+	}
+
+	template <class Other, class OtherRP> 
+	SharedPtr(const SharedPtr<Other, RC, OtherRP>& ptr): _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get()))
+	{
+		_pCounter->duplicate();
+	}
+
+	SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr)
+	{
+		_pCounter->duplicate();
+	}
+
+	~SharedPtr()
+	{
+		try
+		{
+			release();
+		}
+		catch (...)
+		{
+			poco_unexpected();
+		}
+	}
+
+	SharedPtr& assign(C* ptr)
+	{
+		if (get() != ptr)
+		{
+			SharedPtr tmp(ptr);
+			swap(tmp);
+		}
+		return *this;
+	}
+	
+	SharedPtr& assign(const SharedPtr& ptr)
+	{
+		if (&ptr != this)
+		{
+			SharedPtr tmp(ptr);
+			swap(tmp);
+		}
+		return *this;
+	}
+	
+	template <class Other, class OtherRP>
+	SharedPtr& assign(const SharedPtr<Other, RC, OtherRP>& ptr)
+	{
+		if (ptr.get() != _ptr)
+		{
+			SharedPtr tmp(ptr);
+			swap(tmp);
+		}
+		return *this;
+	}
+
+	void reset()
+	{
+		assign(0);
+	}
+
+	void reset(C* ptr)
+	{
+		assign(ptr);
+	}
+
+	void reset(const SharedPtr& ptr)
+	{
+		assign(ptr);
+	}
+
+	template <class Other, class OtherRP>
+	void reset(const SharedPtr<Other, RC, OtherRP>& ptr)
+	{
+		assign<Other, OtherRP>(ptr);
+	}
+
+	SharedPtr& operator = (C* ptr)
+	{
+		return assign(ptr);
+	}
+
+	SharedPtr& operator = (const SharedPtr& ptr)
+	{
+		return assign(ptr);
+	}
+
+	template <class Other, class OtherRP>
+	SharedPtr& operator = (const SharedPtr<Other, RC, OtherRP>& ptr)
+	{
+		return assign<Other>(ptr);
+	}
+
+	void swap(SharedPtr& ptr)
+	{
+		std::swap(_ptr, ptr._ptr);
+		std::swap(_pCounter, ptr._pCounter);
+	}
+
+	template <class Other> 
+	SharedPtr<Other, RC, RP> cast() const
+		/// Casts the SharedPtr via a dynamic cast to the given type.
+		/// Returns an SharedPtr containing NULL if the cast fails.
+		/// Example: (assume class Sub: public Super)
+		///    SharedPtr<Super> super(new Sub());
+		///    SharedPtr<Sub> sub = super.cast<Sub>();
+		///    poco_assert (sub.get());
+	{
+		Other* pOther = dynamic_cast<Other*>(_ptr);
+		if (pOther)
+			return SharedPtr<Other, RC, RP>(_pCounter, pOther);
+		return SharedPtr<Other, RC, RP>();
+	}
+
+	template <class Other> 
+	SharedPtr<Other, RC, RP> unsafeCast() const
+		/// Casts the SharedPtr via a static cast to the given type.
+		/// Example: (assume class Sub: public Super)
+		///    SharedPtr<Super> super(new Sub());
+		///    SharedPtr<Sub> sub = super.unsafeCast<Sub>();
+		///    poco_assert (sub.get());
+	{
+		Other* pOther = static_cast<Other*>(_ptr);
+		return SharedPtr<Other, RC, RP>(_pCounter, pOther);
+	}
+
+	C* operator -> ()
+	{
+		return deref();
+	}
+
+	const C* operator -> () const
+	{
+		return deref();
+	}
+
+	C& operator * ()
+	{
+		return *deref();
+	}
+
+	const C& operator * () const
+	{
+		return *deref();
+	}
+
+	C* get()
+	{
+		return _ptr;
+	}
+
+	const C* get() const
+	{
+		return _ptr;
+	}
+
+	operator C* ()
+	{
+		return _ptr;
+	}
+	
+	operator const C* () const
+	{
+		return _ptr;
+	}
+
+	bool operator ! () const
+	{
+		return _ptr == 0;
+	}
+
+	bool isNull() const
+	{
+		return _ptr == 0;
+	}
+
+	bool operator == (const SharedPtr& ptr) const
+	{
+		return get() == ptr.get();
+	}
+
+	bool operator == (const C* ptr) const
+	{
+		return get() == ptr;
+	}
+
+	bool operator == (C* ptr) const
+	{
+		return get() == ptr;
+	}
+
+	bool operator != (const SharedPtr& ptr) const
+	{
+		return get() != ptr.get();
+	}
+
+	bool operator != (const C* ptr) const
+	{
+		return get() != ptr;
+	}
+
+	bool operator != (C* ptr) const
+	{
+		return get() != ptr;
+	}
+
+	bool operator < (const SharedPtr& ptr) const
+	{
+		return get() < ptr.get();
+	}
+
+	bool operator < (const C* ptr) const
+	{
+		return get() < ptr;
+	}
+
+	bool operator < (C* ptr) const
+	{
+		return get() < ptr;
+	}
+
+	bool operator <= (const SharedPtr& ptr) const
+	{
+		return get() <= ptr.get();
+	}
+
+	bool operator <= (const C* ptr) const
+	{
+		return get() <= ptr;
+	}
+
+	bool operator <= (C* ptr) const
+	{
+		return get() <= ptr;
+	}
+
+	bool operator > (const SharedPtr& ptr) const
+	{
+		return get() > ptr.get();
+	}
+
+	bool operator > (const C* ptr) const
+	{
+		return get() > ptr;
+	}
+
+	bool operator > (C* ptr) const
+	{
+		return get() > ptr;
+	}
+
+	bool operator >= (const SharedPtr& ptr) const
+	{
+		return get() >= ptr.get();
+	}
+
+	bool operator >= (const C* ptr) const
+	{
+		return get() >= ptr;
+	}
+
+	bool operator >= (C* ptr) const
+	{
+		return get() >= ptr;
+	}
+	
+	int referenceCount() const
+	{
+		return _pCounter->referenceCount();
+	}
+
+private:
+	C* deref() const
+	{
+		if (!_ptr)
+			throw NullPointerException();
+
+		return _ptr;
+	}
+
+	void release()
+	{
+		poco_assert_dbg (_pCounter);
+		int i = _pCounter->release();
+		if (i == 0)
+		{
+			RP::release(_ptr);
+			_ptr = 0;
+
+			delete _pCounter;
+			_pCounter = 0;
+		}
+	}
+
+	SharedPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr)
+		/// for cast operation
+	{
+		poco_assert_dbg (_pCounter);
+		_pCounter->duplicate();
+	}
+
+private:
+	RC* _pCounter;
+	C*  _ptr;
+
+	template <class OtherC, class OtherRC, class OtherRP> friend class SharedPtr;
+};
+
+
+template <class C, class RC, class RP>
+inline void swap(SharedPtr<C, RC, RP>& p1, SharedPtr<C, RC, RP>& p2)
+{
+	p1.swap(p2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SharedPtr_INCLUDED
diff --git a/Poco/SignalHandler.h b/Poco/SignalHandler.h
new file mode 100644
index 0000000..22b5f16
--- /dev/null
+++ b/Poco/SignalHandler.h
@@ -0,0 +1,129 @@
+//
+// SignalHandler.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  SignalHandler
+//
+// Definition of the SignalHandler class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SignalHandler_INCLUDED
+#define Foundation_SignalHandler_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
+
+
+#include <vector>
+#include <setjmp.h>
+
+
+namespace Poco {
+
+
+class Foundation_API SignalHandler
+	/// This helper class simplifies the handling of POSIX signals.
+	///
+	/// The class provides a signal handler (installed with
+	/// installHandlers()) that translates certain POSIX
+	/// signals (SIGILL, SIGBUS, SIGSEGV, SIGSYS) into 
+	/// C++ exceptions.
+	///
+	/// Internally, a stack of sigjmp_buf structs is maintained for
+	/// each thread. The constructor pushes a new sigjmp_buf onto
+	/// the current thread's stack. The destructor pops the sigjmp_buf
+	/// from the stack.
+	///
+	/// The poco_throw_on_signal macro creates an instance of SignalHandler
+	/// on the stack, which results in a new sigjmp_buf being created.
+	/// The sigjmp_buf is then set-up with sigsetjmp().
+	///
+	/// The handleSignal() method, which is invoked when a signal arrives,
+	/// checks if a sigjmp_buf is available for the current thread.
+	/// If so, siglongjmp() is used to jump out of the signal handler.
+	///
+	/// Typical usage is as follows:
+	///
+	///     try
+	///     {
+	///          poco_throw_on_signal;
+	///          ...
+	///     }
+	///     catch (Poco::SignalException&)
+	///     {
+	///         ...
+	///     }
+	///
+	/// The best way to deal with a SignalException is to log as much context
+	/// information as possible, to aid in debugging, and then to exit.
+	///
+	/// The SignalHandler can be disabled globally by compiling POCO and client
+	/// code with the POCO_NO_SIGNAL_HANDLER macro defined.
+{
+public:
+	SignalHandler();
+		/// Creates the SignalHandler.
+
+	~SignalHandler();
+		/// Destroys the SignalHandler.
+
+	sigjmp_buf& jumpBuffer();
+		/// Returns the top-most sigjmp_buf for the current thread.
+
+	static void throwSignalException(int sig);
+		/// Throws a SignalException with a textual description  
+		/// of the given signal as argument. 
+	
+	static void install();
+		/// Installs signal handlers for SIGILL, SIGBUS, SIGSEGV
+		/// and SIGSYS.
+
+protected:
+	static void handleSignal(int sig);
+		/// The actual signal handler.
+
+	struct JumpBuffer
+		/// sigjmp_buf cannot be used to instantiate a std::vector,
+		/// so we provide a wrapper struct.
+	{
+		sigjmp_buf buf;
+	};
+	typedef std::vector<JumpBuffer> JumpBufferVec;
+
+	static JumpBufferVec& jumpBufferVec();
+		/// Returns the JumpBufferVec for the current thread.
+
+private:
+	static JumpBufferVec _jumpBufferVec;
+	
+	friend class ThreadImpl;
+};
+
+
+#ifndef POCO_NO_SIGNAL_HANDLER
+#define poco_throw_on_signal \
+	Poco::SignalHandler _poco_signalHandler; \
+	int _poco_signal = sigsetjmp(_poco_signalHandler.jumpBuffer(), 1); \
+	if (_poco_signal) _poco_signalHandler.throwSignalException(_poco_signal);
+#else
+#define poco_throw_on_signal
+#endif
+
+
+} // namespace Poco
+
+
+#endif // POCO_OS_FAMILY_UNIX
+
+
+#endif // Foundation_SignalHandler_INCLUDED
diff --git a/Poco/SimpleFileChannel.h b/Poco/SimpleFileChannel.h
new file mode 100644
index 0000000..29882f4
--- /dev/null
+++ b/Poco/SimpleFileChannel.h
@@ -0,0 +1,150 @@
+//
+// SimpleFileChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  SimpleFileChannel
+//
+// Definition of the SimpleFileChannel class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SimpleFileChannel_INCLUDED
+#define Foundation_SimpleFileChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+class LogFile;
+
+
+class Foundation_API SimpleFileChannel: public Channel
+	/// A Channel that writes to a file. This class only
+	/// supports simple log file rotation.
+	///
+	/// For more features, see the FileChannel class.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is in the text. 
+	///
+	/// Log file rotation based on log file size is supported.
+	///
+	/// If rotation is enabled, the SimpleFileChannel will 
+	/// alternate between two log files. If the size of
+	/// the primary log file exceeds a specified limit,
+	/// the secondary log file will be used, and vice
+	/// versa. 
+	///
+	/// Log rotation is configured with the "rotation"
+	/// property, which supports the following values:
+	///   * never:         no log rotation
+	///   * <n>:           the file is rotated when its size exceeds
+	///                    <n> bytes.
+	///   * <n> K:         the file is rotated when its size exceeds
+	///                    <n> Kilobytes.
+	///   * <n> M:         the file is rotated when its size exceeds
+	///                    <n> Megabytes.
+	///
+	/// The path of the (primary) log file can be specified with
+	/// the "path" property. Optionally, the path of the secondary
+	/// log file can be specified with the "secondaryPath" property.
+	///
+	/// If no secondary path is specified, the secondary path will
+	/// default to <primaryPath>.1.
+	///
+	/// The flush property specifies whether each log message is flushed
+	/// immediately to the log file (which may hurt application performance,
+	/// but ensures that everything is in the log in case of a system crash),
+	//  or whether it's allowed to stay in the system's file buffer for some time.
+	/// Valid values are:
+	///
+	///   * true:   Every essages is immediately flushed to the log file (default).
+	///   * false:  Messages are not immediately flushed to the log file.
+	///
+{
+public:
+	SimpleFileChannel();
+		/// Creates the FileChannel.
+
+	SimpleFileChannel(const std::string& path);
+		/// Creates the FileChannel for a file with the given path.
+
+	void open();
+		/// Opens the FileChannel and creates the log file if necessary.
+		
+	void close();
+		/// Closes the FileChannel.
+
+	void log(const Message& msg);
+		/// Logs the given message to the file.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given name. 
+		/// 
+		/// The following properties are supported:
+		///   * path:          The primary log file's path.
+		///   * secondaryPath: The secondary log file's path.
+		///   * rotation:      The log file's rotation mode. See the 
+		///                    SimpleFileChannel class for details.
+		///   * flush:         Specifies whether messages are immediately
+		///                    flushed to the log file. See the SimpleFileChannel
+		///                    class for details.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+		/// See setProperty() for a description of the supported
+		/// properties.
+
+	Timestamp creationDate() const;
+		/// Returns the log file's creation date.
+		
+	UInt64 size() const;
+		/// Returns the log file's current size in bytes.
+
+	const std::string& path() const;
+		/// Returns the log file's primary path.
+
+	const std::string& secondaryPath() const;
+		/// Returns the log file's secondary path.
+
+	static const std::string PROP_PATH;
+	static const std::string PROP_SECONDARYPATH;
+	static const std::string PROP_ROTATION;
+	static const std::string PROP_FLUSH;
+
+protected:
+	~SimpleFileChannel();
+	void setRotation(const std::string& rotation);
+	void setFlush(const std::string& flush);
+	void rotate();
+
+private:
+	std::string      _path;
+	std::string      _secondaryPath;
+	std::string      _rotation;
+	UInt64           _limit;
+	bool             _flush;
+	LogFile*         _pFile;
+	FastMutex        _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SimpleFileChannel_INCLUDED
diff --git a/Poco/SimpleHashTable.h b/Poco/SimpleHashTable.h
new file mode 100644
index 0000000..c149cd6
--- /dev/null
+++ b/Poco/SimpleHashTable.h
@@ -0,0 +1,398 @@
+//
+// SimpleHashTable.h
+//
+// Library: Foundation
+// Package: Hashing
+// Module:  SimpleHashTable
+//
+// Definition of the SimpleHashTable class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SimpleHashTable_INCLUDED
+#define Foundation_SimpleHashTable_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include "Poco/HashFunction.h"
+#include "Poco/HashStatistic.h"
+#include <vector>
+#include <map>
+#include <cstddef>
+#include <algorithm>
+
+
+namespace Poco {
+
+
+//@ deprecated
+template <class Key, class Value, class KeyHashFunction = HashFunction<Key> >
+class SimpleHashTable
+	/// A SimpleHashTable stores a key value pair that can be looked up via a hashed key.
+	///
+	/// In comparision to a HashTable, this class handles collisions by sequentially searching the next
+	/// free location. This also means that the maximum size of this table is limited, i.e. if the hash table
+	/// is full, it will throw an exception and that this class does not support remove operations.
+	/// On the plus side it is faster than the HashTable.
+	///
+	/// This class is NOT thread safe.
+{
+public:
+	class HashEntry
+	{
+	public:
+		Key   key;
+		Value value;
+		HashEntry(const Key k, const Value v): key(k), value(v)
+		{
+		}
+	};
+
+	typedef std::vector<HashEntry*> HashTableVector;
+
+	SimpleHashTable(UInt32 capacity = 251): _entries(capacity, 0), _size(0), _capacity(capacity)
+		/// Creates the SimpleHashTable.
+	{
+	}
+
+	SimpleHashTable(const SimpleHashTable& ht):
+		_size(ht._size),
+		_capacity(ht._capacity)
+	{
+		_entries.reserve(ht._capacity);
+		for (typename HashTableVector::iterator it = ht._entries.begin(); it != ht._entries.end(); ++it)
+		{
+			if (*it) 
+				_entries.push_back(new HashEntry(*it));
+			else
+				_entries.push_back(0);
+		}
+	}
+
+	~SimpleHashTable()
+		/// Destroys the SimpleHashTable.
+	{
+		clear();
+	}
+
+	SimpleHashTable& operator = (const SimpleHashTable& ht)
+	{
+		if (this != &ht)
+		{
+			SimpleHashTable tmp(ht);
+			swap(tmp);
+		}
+		return *this;
+	}
+	
+	void swap(SimpleHashTable& ht)
+	{
+		using std::swap;
+		swap(_entries, ht._entries);
+		swap(_size, ht._size);
+		swap(_capacity, ht._capacity);
+	}
+
+	void clear()
+	{
+		for (typename HashTableVector::iterator it = _entries.begin(); it != _entries.end(); ++it)
+		{
+			delete *it;
+			*it = 0;
+		}
+		_size = 0;
+	}
+
+	UInt32 insert(const Key& key, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Throws an exception if the entry was already inserted
+	{
+		UInt32 hsh = hash(key);
+		insertRaw(key, hsh, value);
+		return hsh;
+	}
+
+	Value& insertRaw(const Key& key, UInt32 hsh, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Throws an exception if the entry was already inserted
+	{
+		UInt32 pos = hsh;
+		if (!_entries[pos])
+			_entries[pos] = new HashEntry(key, value);
+		else
+		{
+			UInt32 origHash = hsh;
+			while (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+					throw ExistsException();
+				if (hsh - origHash > _capacity)
+					throw PoolOverflowException("SimpleHashTable full");
+				hsh++;
+			}
+			pos = hsh % _capacity;
+			_entries[pos] = new HashEntry(key, value);
+		}
+		_size++;
+		return _entries[pos]->value;
+	}
+
+	UInt32 update(const Key& key, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Replaces an existing entry if it finds one
+	{
+		UInt32 hsh = hash(key);
+		updateRaw(key, hsh, value);
+		return hsh;
+	}
+
+	void updateRaw(const Key& key, UInt32 hsh, const Value& value)
+		/// Returns the hash value of the inserted item.
+		/// Replaces an existing entry if it finds one
+	{
+		if (!_entries[hsh])
+			_entries[hsh] = new HashEntry(key, value);
+		else
+		{
+			UInt32 origHash = hsh;
+			while (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+				{
+					_entries[hsh % _capacity]->value = value;
+					return;
+				}
+				if (hsh - origHash > _capacity)
+					throw PoolOverflowException("SimpleHashTable full");
+				hsh++;
+			}
+			_entries[hsh % _capacity] = new HashEntry(key, value);
+		}
+		_size++;
+	}
+
+	UInt32 hash(const Key& key) const
+	{
+		return _hash(key, _capacity);
+	}
+
+	const Value& get(const Key& key) const
+		/// Throws an exception if the value does not exist
+	{
+		UInt32 hsh = hash(key);
+		return getRaw(key, hsh);
+	}
+
+	const Value& getRaw(const Key& key, UInt32 hsh) const
+		/// Throws an exception if the value does not exist
+	{
+		UInt32 origHash = hsh;
+		while (true)
+		{
+			if (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+				{
+					return _entries[hsh % _capacity]->value;
+				}
+			}
+			else
+				throw InvalidArgumentException("value not found");
+			if (hsh - origHash > _capacity)
+				throw InvalidArgumentException("value not found");
+			hsh++;
+		}
+	}
+
+	Value& get(const Key& key)
+		/// Throws an exception if the value does not exist
+	{
+		UInt32 hsh = hash(key);
+		return const_cast<Value&>(getRaw(key, hsh));
+	}
+	
+	const Value& operator [] (const Key& key) const
+	{
+		return get(key);
+	}
+	
+	Value& operator [] (const Key& key)
+	{
+		UInt32 hsh = hash(key);
+		UInt32 origHash = hsh;
+		while (true)
+		{
+			if (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+				{
+					return _entries[hsh % _capacity]->value;
+				}
+			}
+			else return insertRaw(key, hsh, Value());
+			if (hsh - origHash > _capacity)
+				return insertRaw(key, hsh, Value());
+			hsh++;
+		}
+	}
+
+	const Key& getKeyRaw(const Key& key, UInt32 hsh)
+		/// Throws an exception if the key does not exist. returns a reference to the internally
+		/// stored key. Useful when someone does an insert and wants for performance reason only to store
+		/// a pointer to the key in another collection
+	{
+		UInt32 origHash = hsh;
+		while (true)
+		{
+			if (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+				{
+					return _entries[hsh % _capacity]->key;
+				}
+			}
+			else
+				throw InvalidArgumentException("key not found");
+
+			if (hsh - origHash > _capacity)
+				throw InvalidArgumentException("key not found");
+			hsh++;
+		}
+	}
+
+	bool get(const Key& key, Value& v) const
+		/// Sets v to the found value, returns false if no value was found
+	{
+		UInt32 hsh = hash(key);
+		return getRaw(key, hsh, v);
+	}
+
+	bool getRaw(const Key& key, UInt32 hsh, Value& v) const
+		/// Sets v to the found value, returns false if no value was found
+	{
+		UInt32 origHash = hsh;
+		while (true)
+		{
+			if (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+				{
+					v = _entries[hsh % _capacity]->value;
+					return true;
+				}
+			}
+			else
+				return false;
+			if (hsh - origHash > _capacity)
+				return false;
+			hsh++;
+		}
+	}
+
+	bool exists(const Key& key) const
+	{
+		UInt32 hsh = hash(key);
+		return existsRaw(key, hsh);
+	}
+
+	bool existsRaw(const Key& key, UInt32 hsh) const
+	{
+		UInt32 origHash = hsh;
+		while (true)
+		{
+			if (_entries[hsh % _capacity])
+			{
+				if (_entries[hsh % _capacity]->key == key)
+				{
+					return true;
+				}
+			}
+			else
+				return false;
+			if (hsh - origHash > _capacity)
+				return false;
+			hsh++;
+		}
+	}
+
+	std::size_t size() const
+		/// Returns the number of elements already inserted into the SimpleHashTable
+	{
+		return _size;
+	}
+	
+	UInt32 capacity() const
+	{
+		return _capacity;
+	}
+
+	void resize(UInt32 newSize)
+		/// Resizes the hashtable, rehashes all existing entries. Expensive!
+	{
+		if (_capacity != newSize)
+		{
+			SimpleHashTable tmp(newSize);
+			swap(tmp);
+			for (typename HashTableVector::const_iterator it = tmp._entries.begin(); it != tmp._entries.end(); ++it)
+			{
+				if (*it)
+				{
+					insertRaw((*it)->key, hash((*it)->key), (*it)->value);
+				}
+			}
+		}
+	}
+
+	HashStatistic currentState(bool details = false) const
+		/// Returns the current internal state
+	{
+		UInt32 numberOfEntries = (UInt32)_size;
+		UInt32 numZeroEntries = 0;
+		UInt32 maxEntriesPerHash = 0;
+		std::vector<UInt32> detailedEntriesPerHash;
+	#ifdef _DEBUG
+		UInt32 totalSize = 0;
+	#endif
+		for (int i=0; i < _capacity; ++i)
+		{
+			if (_entries[i])
+			{
+				maxEntriesPerHash = 1;
+				UInt32 size = 1;
+				if (details)
+					detailedEntriesPerHash.push_back(size);
+	#ifdef _DEBUG
+				totalSize += size;
+	#endif
+			}
+			else
+			{
+				numZeroEntries++;
+				if (details)
+					detailedEntriesPerHash.push_back(0);
+			}
+		}
+	#ifdef _DEBUG
+		poco_assert_dbg(totalSize == numberOfEntries);
+	#endif
+		return HashStatistic(_capacity, numberOfEntries, numZeroEntries, maxEntriesPerHash, detailedEntriesPerHash);
+	}
+
+private:
+	HashTableVector _entries;
+	std::size_t     _size;
+	UInt32          _capacity;
+	KeyHashFunction _hash;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_HashTable_INCLUDED
diff --git a/Poco/SingletonHolder.h b/Poco/SingletonHolder.h
new file mode 100644
index 0000000..8735f11
--- /dev/null
+++ b/Poco/SingletonHolder.h
@@ -0,0 +1,77 @@
+//
+// SingletonHolder.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  SingletonHolder
+//
+// Definition of the SingletonHolder template.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SingletonHolder_INCLUDED
+#define Foundation_SingletonHolder_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+
+
+namespace Poco {
+
+
+template <class S>
+class SingletonHolder
+	/// This is a helper template class for managing
+	/// singleton objects allocated on the heap.
+	/// The class ensures proper deletion (including
+	/// calling of the destructor) of singleton objects
+	/// when the application that created them terminates.
+{
+public:
+	SingletonHolder():
+		_pS(0)
+		/// Creates the SingletonHolder.
+	{
+	}
+	
+	~SingletonHolder()
+		/// Destroys the SingletonHolder and the singleton
+		/// object that it holds.
+	{
+		delete _pS;
+	}
+	
+	S* get()
+		/// Returns a pointer to the singleton object
+		/// hold by the SingletonHolder. The first call
+		/// to get will create the singleton.
+	{
+		FastMutex::ScopedLock lock(_m);
+		if (!_pS) _pS = new S;
+		return _pS;
+	}
+	
+	void reset()
+		/// Deletes the singleton object.
+	{
+		FastMutex::ScopedLock lock(_m);
+		delete _pS;
+		_pS = 0;
+	}
+	
+private:
+	S* _pS;
+	FastMutex _m;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SingletonHolder_INCLUDED
diff --git a/Poco/SortedDirectoryIterator.h b/Poco/SortedDirectoryIterator.h
new file mode 100644
index 0000000..94c822b
--- /dev/null
+++ b/Poco/SortedDirectoryIterator.h
@@ -0,0 +1,70 @@
+//
+// SortedDirectoryIterator.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  DirectoryIterator
+//
+// Definition of the SortedDirectoryIterator class.
+//
+// Copyright (c) 2004-2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SortedDirectoryIterator_INCLUDED
+#define Foundation_SortedDirectoryIterator_INCLUDED
+
+#include "Poco/Foundation.h"
+#include "Poco/File.h"
+#include "Poco/Path.h"
+#include "Poco/DirectoryIterator.h"
+#include <deque>
+
+
+namespace Poco
+{
+
+class Foundation_API SortedDirectoryIterator: public DirectoryIterator
+	/// The SortedDirectoryIterator class is similar to
+	/// DirectoryIterator class, but places directories before files
+	/// and sorts content alphabetically.
+{
+public:
+	SortedDirectoryIterator();
+		/// Creates the end iterator.
+
+	SortedDirectoryIterator(const std::string& path);
+		/// Creates a directory iterator for the given path.
+
+	SortedDirectoryIterator(const DirectoryIterator& iterator);
+		/// Creates a directory iterator for the given path.
+
+	SortedDirectoryIterator(const File& file);
+		/// Creates a directory iterator for the given file.
+
+	SortedDirectoryIterator(const Path& path);
+		/// Creates a directory iterator for the given path.
+
+	virtual ~SortedDirectoryIterator();
+		/// Destroys the DirsFirstDirectoryIterator.
+
+	virtual SortedDirectoryIterator& operator ++();   // prefix
+
+private:
+	bool _is_finished;
+	std::deque<std::string> _directories;
+	std::deque<std::string> _files;
+
+	void next();
+		/// Take next item
+	void scan();
+		/// Scan directory to collect its children directories and files
+};
+
+
+} // namespace Poco
+
+#endif //Foundation_SortedDirectoryIterator_INCLUDED
diff --git a/Poco/SplitterChannel.h b/Poco/SplitterChannel.h
new file mode 100644
index 0000000..75aa33b
--- /dev/null
+++ b/Poco/SplitterChannel.h
@@ -0,0 +1,77 @@
+//
+// SplitterChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  SplitterChannel
+//
+// Definition of the SplitterChannel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SplitterChannel_INCLUDED
+#define Foundation_SplitterChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Mutex.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API SplitterChannel: public Channel
+	/// This channel sends a message to multiple
+	/// channels simultaneously.
+{
+public:
+	SplitterChannel();
+		/// Creates the SplitterChannel.
+
+	void addChannel(Channel* pChannel);
+		/// Attaches a channel, which may not be null.
+		
+	void removeChannel(Channel* pChannel);
+		/// Removes a channel.
+
+	void log(const Message& msg);
+		/// Sends the given Message to all
+		/// attaches channels. 
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets or changes a configuration property.
+		///
+		/// Only the "channel" property is supported, which allows
+		/// adding a comma-separated list of channels via the LoggingRegistry.
+		/// The "channel" property is set-only.
+		/// To simplify file-based configuration, all property
+		/// names starting with "channel" are treated as "channel".
+
+	void close();
+		/// Removes all channels.
+		
+	int count() const;
+		/// Returns the number of channels in the SplitterChannel.
+
+protected:
+	~SplitterChannel();
+
+private:
+	typedef std::vector<Channel*> ChannelVec;
+	
+	ChannelVec        _channels;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SplitterChannel_INCLUDED
diff --git a/Poco/Stopwatch.h b/Poco/Stopwatch.h
new file mode 100644
index 0000000..6bc27fc
--- /dev/null
+++ b/Poco/Stopwatch.h
@@ -0,0 +1,108 @@
+//
+// Stopwatch.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  Stopwatch
+//
+// Definition of the Stopwatch class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Stopwatch_INCLUDED
+#define Foundation_Stopwatch_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Clock.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Stopwatch
+	/// A simple facility to measure time intervals
+	/// with microsecond resolution.
+{
+public:
+	Stopwatch();
+	~Stopwatch();
+
+	void start();
+		/// Starts (or restarts) the stopwatch.
+		
+	void stop();
+		/// Stops or pauses the stopwatch.
+	
+	void reset();
+		/// Resets the stopwatch.
+		
+	void restart();
+		/// Resets and starts the stopwatch.
+		
+	Clock::ClockDiff elapsed() const;
+		/// Returns the elapsed time in microseconds
+		/// since the stopwatch started.
+		
+	int elapsedSeconds() const;
+		/// Returns the number of seconds elapsed
+		/// since the stopwatch started.
+
+	static Clock::ClockVal resolution();
+		/// Returns the resolution of the stopwatch.
+
+private:
+	Stopwatch(const Stopwatch&);
+	Stopwatch& operator = (const Stopwatch&);
+
+	Clock            _start;
+	Clock::ClockDiff _elapsed;
+	bool             _running;
+};
+
+
+//
+// inlines
+//
+inline void Stopwatch::start()
+{
+	if (!_running)
+	{
+		_start.update();
+		_running = true;
+	}
+}
+
+
+inline void Stopwatch::stop()
+{
+	if (_running)
+	{
+		Clock current;
+		_elapsed += current - _start;
+		_running = false;
+	}
+}
+
+
+inline int Stopwatch::elapsedSeconds() const
+{
+	return int(elapsed()/resolution());
+}
+
+
+inline Clock::ClockVal Stopwatch::resolution()
+{
+	return Clock::resolution();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Stopwatch_INCLUDED
diff --git a/Poco/StrategyCollection.h b/Poco/StrategyCollection.h
new file mode 100644
index 0000000..6372d46
--- /dev/null
+++ b/Poco/StrategyCollection.h
@@ -0,0 +1,133 @@
+//
+// StrategyCollection.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  StrategyCollection
+//
+// Definition of the StrategyCollection class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StrategyCollection_INCLUDED
+#define Foundation_StrategyCollection_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/AbstractStrategy.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+template <class TKey, class TValue> 
+class StrategyCollection: public AbstractStrategy<TKey, TValue>
+	/// An StrategyCollection is a decorator masking n collections as a single one.
+{
+public:
+	typedef std::vector<SharedPtr<AbstractStrategy<TKey, TValue> > > Strategies;
+	typedef typename Strategies::iterator       Iterator;
+	typedef typename Strategies::const_iterator ConstIterator;
+
+public:
+	StrategyCollection()
+	{
+	}
+
+	~StrategyCollection()
+	{
+	}
+
+	void pushBack(AbstractStrategy<TKey, TValue>* pStrat)
+		/// Adds an AbstractStrategy to the collection. Class takes ownership of pointer
+	{
+		_strategies.push_back(SharedPtr<AbstractStrategy<TKey, TValue> >(pStrat));
+	}
+
+	void popBack()
+		/// Removes the last added AbstractStrategy from the collection.
+	{
+		_strategies.pop_back();
+	}
+
+	void onAdd(const void* pSender, const KeyValueArgs <TKey, TValue>& key)
+		/// Adds the key to the strategy.
+		/// If for the key already an entry exists, it will be overwritten.
+	{
+		Iterator it = _strategies.begin();
+		Iterator endIt = _strategies.end();
+		for (; it != endIt; ++it)
+		{
+			(*it)->onAdd(pSender, key);
+		}
+	}
+
+	void onRemove(const void* pSender, const TKey& key)
+		/// Removes an entry from the strategy. If the entry is not found
+		/// the remove is ignored.
+	{
+		Iterator it = _strategies.begin();
+		Iterator endIt = _strategies.end();
+		for (; it != endIt; ++it)
+		{
+			(*it)->onRemove(pSender, key);
+		}
+	}
+
+	void onGet(const void* pSender, const TKey& key)
+	{
+		Iterator it = _strategies.begin();
+		Iterator endIt = _strategies.end();
+		for (; it != endIt; ++it)
+		{
+			(*it)->onGet(pSender, key);
+		}
+	}
+
+	void onClear(const void* pSender, const EventArgs& args)
+	{
+		Iterator it = _strategies.begin();
+		Iterator endIt = _strategies.end();
+		for (; it != endIt; ++it)
+		{
+			(*it)->onClear(pSender, args);
+		}
+	}
+
+	void onIsValid(const void* pSender, ValidArgs<TKey>& key)
+	{
+		Iterator it = _strategies.begin();
+		Iterator endIt = _strategies.end();
+		for (; it != endIt && key.isValid(); ++it)
+		{
+			(*it)->onIsValid(pSender, key);
+		}
+	}
+
+	void onReplace(const void* pSender, std::set<TKey>& elemsToRemove)
+	{
+		Iterator it = _strategies.begin();
+		Iterator endIt = _strategies.end();
+		for (; it != endIt; ++it)
+		{
+			(*it)->onReplace(pSender, elemsToRemove);
+		}
+	}
+
+protected:
+	Strategies _strategies;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_StrategyCollection_INCLUDED
diff --git a/Poco/StreamChannel.h b/Poco/StreamChannel.h
new file mode 100644
index 0000000..8ecf50a
--- /dev/null
+++ b/Poco/StreamChannel.h
@@ -0,0 +1,59 @@
+//
+// StreamChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  StreamChannel
+//
+// Definition of the StreamChannel class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StreamChannel_INCLUDED
+#define Foundation_StreamChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Mutex.h"
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API StreamChannel: public Channel
+	/// A channel that writes to an ostream.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is contained 
+	/// in the text.
+{
+public:
+	StreamChannel(std::ostream& str);
+		/// Creates the channel.
+
+	void log(const Message& msg);
+		/// Logs the given message to the channel's stream.
+		
+protected:
+	virtual ~StreamChannel();
+
+private:
+	std::ostream& _str;
+	FastMutex     _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_StreamChannel_INCLUDED
diff --git a/Poco/StreamConverter.h b/Poco/StreamConverter.h
new file mode 100644
index 0000000..c880e26
--- /dev/null
+++ b/Poco/StreamConverter.h
@@ -0,0 +1,128 @@
+//
+// StreamConverter.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  StreamConverter
+//
+// Definition of the StreamConverter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StreamConverter_INCLUDED
+#define Foundation_StreamConverter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API StreamConverterBuf: public UnbufferedStreamBuf
+	/// A StreamConverter converts streams from one encoding (inEncoding)
+	/// into another (outEncoding).
+	/// If a character cannot be represented in outEncoding, defaultChar
+	/// is used instead.
+	/// If a byte sequence is not valid in inEncoding, defaultChar is used
+	/// instead and the encoding error count is incremented.
+{
+public:
+	StreamConverterBuf(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+		/// Creates the StreamConverterBuf and connects it
+		/// to the given input stream.
+
+	StreamConverterBuf(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+		/// Creates the StreamConverterBuf and connects it
+		/// to the given output stream.
+
+	~StreamConverterBuf();
+		/// Destroys the StreamConverterBuf.
+
+	int errors() const;
+		/// Returns the number of encoding errors encountered.
+
+protected:
+	int readFromDevice();
+	int writeToDevice(char c);
+
+private:
+	std::istream*       _pIstr;
+	std::ostream*       _pOstr;
+	const TextEncoding& _inEncoding;
+	const TextEncoding& _outEncoding;
+	int                 _defaultChar;
+	unsigned char       _buffer[TextEncoding::MAX_SEQUENCE_LENGTH];
+	int                 _sequenceLength;
+	int                 _pos;
+	int                 _errors;
+};
+
+
+class Foundation_API StreamConverterIOS: public virtual std::ios
+	/// The base class for InputStreamConverter and OutputStreamConverter.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	StreamConverterIOS(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+	StreamConverterIOS(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+	~StreamConverterIOS();
+	StreamConverterBuf* rdbuf();
+	int errors() const;
+
+protected:
+	StreamConverterBuf _buf;
+};
+
+
+class Foundation_API InputStreamConverter: public StreamConverterIOS, public std::istream
+	/// This stream converts all characters read from the
+	/// underlying istream from one character encoding into another.
+	/// If a character cannot be represented in outEncoding, defaultChar
+	/// is used instead.
+	/// If a byte sequence read from the underlying stream is not valid in inEncoding, 
+	/// defaultChar is used instead and the encoding error count is incremented.
+{
+public:
+	InputStreamConverter(std::istream& istr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+		/// Creates the InputStreamConverter and connects it
+		/// to the given input stream.
+
+	~InputStreamConverter();
+		/// Destroys the stream.
+};
+
+
+class Foundation_API OutputStreamConverter: public StreamConverterIOS, public std::ostream
+	/// This stream converts all characters written to the
+	/// underlying ostream from one character encoding into another.
+	/// If a character cannot be represented in outEncoding, defaultChar
+	/// is used instead.
+	/// If a byte sequence written to the stream is not valid in inEncoding, 
+	/// defaultChar is used instead and the encoding error count is incremented.
+{
+public:
+	OutputStreamConverter(std::ostream& ostr, const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+		/// Creates the OutputStreamConverter and connects it
+		/// to the given input stream.
+
+	~OutputStreamConverter();
+		/// Destroys the CountingOutputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_StreamConverter_INCLUDED
diff --git a/Poco/StreamCopier.h b/Poco/StreamCopier.h
new file mode 100644
index 0000000..fda660c
--- /dev/null
+++ b/Poco/StreamCopier.h
@@ -0,0 +1,85 @@
+//
+// StreamCopier.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamCopier
+//
+// Definition of class StreamCopier.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StreamCopier_INCLUDED
+#define Foundation_StreamCopier_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <istream>
+#include <ostream>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class Foundation_API StreamCopier
+	/// This class provides static methods to copy the contents from one stream
+	/// into another.
+{
+public:
+	static std::streamsize copyStream(std::istream& istr, std::ostream& ostr, std::size_t bufferSize = 8192);
+		/// Writes all bytes readable from istr to ostr, using an internal buffer.
+		///
+		/// Returns the number of bytes copied.
+
+#if defined(POCO_HAVE_INT64)
+	static Poco::UInt64 copyStream64(std::istream& istr, std::ostream& ostr, std::size_t bufferSize = 8192);
+		/// Writes all bytes readable from istr to ostr, using an internal buffer.
+		///
+		/// Returns the number of bytes copied as a 64-bit unsigned integer.
+		///
+		/// Note: the only difference to copyStream() is that a 64-bit unsigned
+		/// integer is used to count the number of bytes copied.
+#endif
+
+	static std::streamsize copyStreamUnbuffered(std::istream& istr, std::ostream& ostr);
+		/// Writes all bytes readable from istr to ostr.
+		///
+		/// Returns the number of bytes copied.
+
+#if defined(POCO_HAVE_INT64)
+	static Poco::UInt64 copyStreamUnbuffered64(std::istream& istr, std::ostream& ostr);
+		/// Writes all bytes readable from istr to ostr.
+		///
+		/// Returns the number of bytes copied as a 64-bit unsigned integer.
+		///
+		/// Note: the only difference to copyStreamUnbuffered() is that a 64-bit unsigned
+		/// integer is used to count the number of bytes copied.
+#endif
+
+	static std::streamsize copyToString(std::istream& istr, std::string& str, std::size_t bufferSize = 8192);
+		/// Appends all bytes readable from istr to the given string, using an internal buffer.
+		///
+		/// Returns the number of bytes copied.
+
+#if defined(POCO_HAVE_INT64)
+	static Poco::UInt64 copyToString64(std::istream& istr, std::string& str, std::size_t bufferSize = 8192);
+		/// Appends all bytes readable from istr to the given string, using an internal buffer.
+		///
+		/// Returns the number of bytes copied as a 64-bit unsigned integer.
+		///
+		/// Note: the only difference to copyToString() is that a 64-bit unsigned
+		/// integer is used to count the number of bytes copied.
+#endif
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_StreamCopier_INCLUDED
diff --git a/Poco/StreamTokenizer.h b/Poco/StreamTokenizer.h
new file mode 100644
index 0000000..3c5b696
--- /dev/null
+++ b/Poco/StreamTokenizer.h
@@ -0,0 +1,97 @@
+//
+// StreamTokenizer.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamTokenizer
+//
+// Definition of the StreamTokenizer class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StreamTokenizer_INCLUDED
+#define Foundation_StreamTokenizer_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Token.h"
+#include <istream>
+#include <vector>
+
+
+namespace Poco {
+
+
+class Foundation_API StreamTokenizer
+	/// A stream tokenizer splits an input stream
+	/// into a sequence of tokens of different kinds.
+	/// Various token kinds can be registered with
+	/// the tokenizer.
+{
+public:
+	StreamTokenizer();
+		/// Creates a StreamTokenizer with no attached stream.
+
+	StreamTokenizer(std::istream& istr);
+		/// Creates a StreamTokenizer with no attached stream.
+
+	virtual ~StreamTokenizer();
+		/// Destroys the StreamTokenizer and deletes all
+		/// registered tokens.
+
+	void attachToStream(std::istream& istr);
+		/// Attaches the tokenizer to an input stream.
+
+	void addToken(Token* pToken);
+		/// Adds a token class to the tokenizer. The
+		/// tokenizer takes ownership of the token and
+		/// deletes it when no longer needed. Comment
+		/// and whitespace tokens will be marked as
+		/// ignorable, which means that next() will not
+		/// return them.
+	
+	void addToken(Token* pToken, bool ignore);
+		/// Adds a token class to the tokenizer. The
+		/// tokenizer takes ownership of the token and
+		/// deletes it when no longer needed.
+		/// If ignore is true, the token will be marked
+		/// as ignorable, which means that next() will
+		/// not return it.
+		
+	const Token* next();
+		/// Extracts the next token from the input stream.
+		/// Returns a pointer to an EOFToken if there are
+		/// no more characters to read. 
+		/// Returns a pointer to an InvalidToken if an
+		/// invalid character is encountered.
+		/// If a token is marked as ignorable, it will not
+		/// be returned, and the next token will be
+		/// examined.
+		/// Never returns a NULL pointer.
+		/// You must not delete the token returned by next().
+
+private:
+	struct TokenInfo
+	{
+		Token* pToken;
+		bool   ignore;
+	};
+	
+	typedef std::vector<TokenInfo> TokenVec;
+	
+	TokenVec      _tokens;
+	std::istream* _pIstr;
+	InvalidToken  _invalidToken;
+	EOFToken      _eofToken;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_StreamTokenizer_INCLUDED
diff --git a/Poco/StreamUtil.h b/Poco/StreamUtil.h
new file mode 100644
index 0000000..79c94f5
--- /dev/null
+++ b/Poco/StreamUtil.h
@@ -0,0 +1,92 @@
+//
+// StreamUtil.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamUtil
+//
+// Stream implementation support.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StreamUtil_INCLUDED
+#define Foundation_StreamUtil_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+// poco_ios_init
+//
+// This is a workaround for a bug in the Dinkumware
+// implementation of iostreams.
+//
+// Calling basic_ios::init() multiple times for the
+// same basic_ios instance results in a memory leak
+// caused by the ios' locale being allocated more than
+// once, each time overwriting the old pointer.
+// This usually occurs in the following scenario:
+//
+// class MyStreamBuf: public std::streambuf
+// {
+//     ...
+// };
+//
+// class MyIOS: public virtual std::ios
+// {
+// public:
+//     MyIOS()
+//     {
+//         init(&_buf);
+//     }
+// protected:
+//     MyStreamBuf _buf;
+// };
+//
+// class MyIStream: public MyIOS, public std::istream
+// {
+//     ...
+// };
+//
+// In this scenario, std::ios::init() is called twice
+// (the first time by the MyIOS constructor, the second
+// time by the std::istream constructor), resulting in 
+// two locale objects being allocated, the pointer second 
+// one overwriting the pointer to the first one and thus 
+// causing a memory leak.
+// 
+// The workaround is to call init() only once for each
+// stream object - by the istream, ostream or iostream
+// constructor, and not calling init() in ios-derived
+// base classes.
+//
+// Some stream implementations, however, require that
+// init() is called in the MyIOS constructor.
+// Therefore we replace each call to init() with
+// the poco_ios_init macro defined below.
+
+
+#if !defined(POCO_IOS_INIT_HACK)
+	// Microsoft Visual Studio with Dinkumware STL (but not STLport)
+#	if defined(_MSC_VER) && (!defined(_STLP_MSVC) || defined(_STLP_NO_OWN_IOSTREAMS))
+#		define POCO_IOS_INIT_HACK 1
+    // QNX with Dinkumware but not GNU C++ Library
+#	elif defined(__QNX__) && !defined(__GLIBCPP__)
+#		define POCO_IOS_INIT_HACK 1
+#	endif
+#endif
+
+
+#if defined(POCO_IOS_INIT_HACK)
+#	define poco_ios_init(buf)
+#else
+#	define poco_ios_init(buf) init(buf)
+#endif
+
+
+#endif // Foundation_StreamUtil_INCLUDED
diff --git a/Poco/String.h b/Poco/String.h
new file mode 100644
index 0000000..fcf10d6
--- /dev/null
+++ b/Poco/String.h
@@ -0,0 +1,706 @@
+//
+// String.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  String
+//
+// String utility functions.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_String_INCLUDED
+#define Foundation_String_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Ascii.h"
+#include <cstring>
+#include <algorithm>
+
+
+namespace Poco {
+
+
+template <class S>
+S trimLeft(const S& str)
+	/// Returns a copy of str with all leading
+	/// whitespace removed.
+{
+	typename S::const_iterator it  = str.begin();
+	typename S::const_iterator end = str.end();
+
+	while (it != end && Ascii::isSpace(*it)) ++it;
+	return S(it, end);
+}
+
+
+template <class S>
+S& trimLeftInPlace(S& str)
+	/// Removes all leading whitespace in str.
+{
+	typename S::iterator it  = str.begin();
+	typename S::iterator end = str.end();
+
+	while (it != end && Ascii::isSpace(*it)) ++it;
+	str.erase(str.begin(), it);
+	return str;
+}
+
+
+template <class S>
+S trimRight(const S& str)
+	/// Returns a copy of str with all trailing
+	/// whitespace removed.
+{
+	int pos = int(str.size()) - 1;
+
+	while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
+	return S(str, 0, pos + 1);
+}
+
+
+template <class S>
+S& trimRightInPlace(S& str)
+	/// Removes all trailing whitespace in str.
+{
+	int pos = int(str.size()) - 1;
+
+	while (pos >= 0 && Ascii::isSpace(str[pos])) --pos;
+	str.resize(pos + 1);
+
+	return str;
+}
+
+
+template <class S>
+S trim(const S& str)
+	/// Returns a copy of str with all leading and
+	/// trailing whitespace removed.
+{
+	int first = 0;
+	int last  = int(str.size()) - 1;
+
+	while (first <= last && Ascii::isSpace(str[first])) ++first;
+	while (last >= first && Ascii::isSpace(str[last])) --last;
+
+	return S(str, first, last - first + 1);
+}
+
+
+template <class S>
+S& trimInPlace(S& str)
+	/// Removes all leading and trailing whitespace in str.
+{
+	int first = 0;
+	int last  = int(str.size()) - 1;
+
+	while (first <= last && Ascii::isSpace(str[first])) ++first;
+	while (last >= first && Ascii::isSpace(str[last])) --last;
+
+	str.resize(last + 1);
+	str.erase(0, first);
+
+	return str;
+}
+
+
+template <class S>
+S toUpper(const S& str)
+	/// Returns a copy of str containing all upper-case characters.
+{
+	typename S::const_iterator it  = str.begin();
+	typename S::const_iterator end = str.end();
+
+	S result;
+	result.reserve(str.size());
+	while (it != end) result += static_cast<typename S::value_type>(Ascii::toUpper(*it++));
+	return result;
+}
+
+
+template <class S>
+S& toUpperInPlace(S& str)
+	/// Replaces all characters in str with their upper-case counterparts.
+{
+	typename S::iterator it  = str.begin();
+	typename S::iterator end = str.end();
+
+	while (it != end) { *it = static_cast<typename S::value_type>(Ascii::toUpper(*it)); ++it; }
+	return str;
+}
+
+
+template <class S>
+S toLower(const S& str)
+	/// Returns a copy of str containing all lower-case characters.
+{
+	typename S::const_iterator it  = str.begin();
+	typename S::const_iterator end = str.end();
+
+	S result;
+	result.reserve(str.size());
+	while (it != end) result += static_cast<typename S::value_type>(Ascii::toLower(*it++));
+	return result;
+}
+
+
+template <class S>
+S& toLowerInPlace(S& str)
+	/// Replaces all characters in str with their lower-case counterparts.
+{
+	typename S::iterator it  = str.begin();
+	typename S::iterator end = str.end();
+
+	while (it != end) { *it = static_cast<typename S::value_type>(Ascii::toLower(*it)); ++it; }
+	return str;
+}
+
+
+#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
+
+
+template <class S, class It>
+int icompare(
+	const S& str,
+	typename S::size_type pos,
+	typename S::size_type n,
+	It it2,
+	It end2)
+	/// Case-insensitive string comparison
+{
+	typename S::size_type sz = str.size();
+	if (pos > sz) pos = sz;
+	if (pos + n > sz) n = sz - pos;
+	It it1  = str.begin() + pos;
+	It end1 = str.begin() + pos + n;
+	while (it1 != end1 && it2 != end2)
+	{
+		typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it1)));
+		typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*it2)));
+		if (c1 < c2)
+			return -1;
+		else if (c1 > c2)
+			return 1;
+		++it1; ++it2;
+	}
+
+	if (it1 == end1)
+		return it2 == end2 ? 0 : -1;
+	else
+		return 1;
+}
+
+
+template <class S>
+int icompare(const S& str1, const S& str2)
+	// A special optimization for an often used case.
+{
+	typename S::const_iterator it1(str1.begin());
+	typename S::const_iterator end1(str1.end());
+	typename S::const_iterator it2(str2.begin());
+	typename S::const_iterator end2(str2.end());
+	while (it1 != end1 && it2 != end2)
+	{
+		typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it1)));
+		typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*it2)));
+		if (c1 < c2)
+			return -1;
+		else if (c1 > c2)
+			return 1;
+		++it1; ++it2;
+	}
+
+	if (it1 == end1)
+		return it2 == end2 ? 0 : -1;
+	else
+		return 1;
+}
+
+
+template <class S>
+int icompare(const S& str1, typename S::size_type n1, const S& str2, typename S::size_type n2)
+{
+	if (n2 > str2.size()) n2 = str2.size();
+	return icompare(str1, 0, n1, str2.begin(), str2.begin() + n2);
+}
+
+
+template <class S>
+int icompare(const S& str1, typename S::size_type n, const S& str2)
+{
+	if (n > str2.size()) n = str2.size();
+	return icompare(str1, 0, n, str2.begin(), str2.begin() + n);
+}
+
+
+template <class S>
+int icompare(const S& str1, typename S::size_type pos, typename S::size_type n, const S& str2)
+{
+	return icompare(str1, pos, n, str2.begin(), str2.end());
+}
+
+
+template <class S>
+int icompare(
+	const S& str1,
+	typename S::size_type pos1,
+	typename S::size_type n1,
+	const S& str2,
+	typename S::size_type pos2,
+	typename S::size_type n2)
+{
+	typename S::size_type sz2 = str2.size();
+	if (pos2 > sz2) pos2 = sz2;
+	if (pos2 + n2 > sz2) n2 = sz2 - pos2;
+	return icompare(str1, pos1, n1, str2.begin() + pos2, str2.begin() + pos2 + n2);
+}
+
+
+template <class S>
+int icompare(
+	const S& str1,
+	typename S::size_type pos1,
+	typename S::size_type n,
+	const S& str2,
+	typename S::size_type pos2)
+{
+	typename S::size_type sz2 = str2.size();
+	if (pos2 > sz2) pos2 = sz2;
+	if (pos2 + n > sz2) n = sz2 - pos2;
+	return icompare(str1, pos1, n, str2.begin() + pos2, str2.begin() + pos2 + n);
+}
+
+
+template <class S>
+int icompare(
+	const S& str,
+	typename S::size_type pos,
+	typename S::size_type n,
+	const typename S::value_type* ptr)
+{
+	poco_check_ptr (ptr);
+	typename S::size_type sz = str.size();
+	if (pos > sz) pos = sz;
+	if (pos + n > sz) n = sz - pos;
+	typename S::const_iterator it  = str.begin() + pos;
+	typename S::const_iterator end = str.begin() + pos + n;
+	while (it != end && *ptr)
+	{
+		typename S::value_type c1(static_cast<typename S::value_type>(Ascii::toLower(*it)));
+		typename S::value_type c2(static_cast<typename S::value_type>(Ascii::toLower(*ptr)));
+		if (c1 < c2)
+			return -1;
+		else if (c1 > c2)
+			return 1;
+		++it; ++ptr;
+	}
+
+	if (it == end)
+		return *ptr == 0 ? 0 : -1;
+	else
+		return 1;
+}
+
+
+template <class S>
+int icompare(
+	const S& str,
+	typename S::size_type pos,
+	const typename S::value_type* ptr)
+{
+	return icompare(str, pos, str.size() - pos, ptr);
+}
+
+
+template <class S>
+int icompare(
+	const S& str,
+	const typename S::value_type* ptr)
+{
+	return icompare(str, 0, str.size(), ptr);
+}
+
+
+#else
+
+
+int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2);
+int Foundation_API icompare(const std::string& str1, const std::string& str2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type n, const std::string& str2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n1, const std::string& str2, std::string::size_type pos2, std::string::size_type n2);
+int Foundation_API icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n, const std::string& str2, std::string::size_type pos2);
+int Foundation_API icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr);
+int Foundation_API icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr);
+int Foundation_API icompare(const std::string& str, const std::string::value_type* ptr);
+
+
+#endif
+
+
+template <class S>
+S translate(const S& str, const S& from, const S& to)
+	/// Returns a copy of str with all characters in
+	/// from replaced by the corresponding (by position)
+	/// characters in to. If there is no corresponding
+	/// character in to, the character is removed from
+	/// the copy.
+{
+	S result;
+	result.reserve(str.size());
+	typename S::const_iterator it  = str.begin();
+	typename S::const_iterator end = str.end();
+	typename S::size_type toSize = to.size();
+	while (it != end)
+	{
+		typename S::size_type pos = from.find(*it);
+		if (pos == S::npos)
+		{
+			result += *it;
+		}
+		else
+		{
+			if (pos < toSize) result += to[pos];
+		}
+		++it;
+	}
+	return result;
+}
+
+
+template <class S>
+S translate(const S& str, const typename S::value_type* from, const typename S::value_type* to)
+{
+	poco_check_ptr (from);
+	poco_check_ptr (to);
+	return translate(str, S(from), S(to));
+}
+
+
+template <class S>
+S& translateInPlace(S& str, const S& from, const S& to)
+	/// Replaces in str all occurrences of characters in from
+	/// with the corresponding (by position) characters in to.
+	/// If there is no corresponding character, the character
+	/// is removed.
+{
+	str = translate(str, from, to);
+	return str;
+}
+
+
+template <class S>
+S translateInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to)
+{
+	poco_check_ptr (from);
+	poco_check_ptr (to);
+	str = translate(str, S(from), S(to));
+#if defined(__SUNPRO_CC)
+// Fix around the RVO bug in SunStudio 12.4
+	S ret(str);
+	return ret;
+#else
+	return str;
+#endif
+}
+
+
+#if !defined(POCO_NO_TEMPLATE_ICOMPARE)
+
+
+template <class S>
+S& replaceInPlace(S& str, const S& from, const S& to, typename S::size_type start = 0)
+{
+	poco_assert (from.size() > 0);
+
+	S result;
+	typename S::size_type pos = 0;
+	result.append(str, 0, start);
+	do
+	{
+		pos = str.find(from, start);
+		if (pos != S::npos)
+		{
+			result.append(str, start, pos - start);
+			result.append(to);
+			start = pos + from.length();
+		}
+		else result.append(str, start, str.size() - start);
+	}
+	while (pos != S::npos);
+	str.swap(result);
+	return str;
+}
+
+
+template <class S>
+S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
+{
+	poco_assert (*from);
+
+	S result;
+	typename S::size_type pos = 0;
+	typename S::size_type fromLen = std::strlen(from);
+	result.append(str, 0, start);
+	do
+	{
+		pos = str.find(from, start);
+		if (pos != S::npos)
+		{
+			result.append(str, start, pos - start);
+			result.append(to);
+			start = pos + fromLen;
+		}
+		else result.append(str, start, str.size() - start);
+	}
+	while (pos != S::npos);
+	str.swap(result);
+	return str;
+}
+
+
+template <class S>
+S& replaceInPlace(S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
+{
+	if (from == to) return str;
+
+	typename S::size_type pos = 0;
+	do
+	{
+		pos = str.find(from, start);
+		if (pos != S::npos)
+		{
+			if (to) str[pos] = to;
+			else str.erase(pos, 1);
+		}
+	} while (pos != S::npos);
+
+	return str;
+}
+
+
+template <class S>
+S& removeInPlace(S& str, const typename S::value_type ch, typename S::size_type start = 0)
+{
+	return replaceInPlace(str, ch, 0, start);
+}
+
+
+template <class S>
+S replace(const S& str, const S& from, const S& to, typename S::size_type start = 0)
+	/// Replace all occurrences of from (which must not be the empty string)
+	/// in str with to, starting at position start.
+{
+	S result(str);
+	replaceInPlace(result, from, to, start);
+	return result;
+}
+
+
+template <class S>
+S replace(const S& str, const typename S::value_type* from, const typename S::value_type* to, typename S::size_type start = 0)
+{
+	S result(str);
+	replaceInPlace(result, from, to, start);
+	return result;
+}
+
+
+template <class S>
+S replace(const S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
+{
+	S result(str);
+	replaceInPlace(result, from, to, start);
+	return result;
+}
+
+
+template <class S>
+S remove(const S& str, const typename S::value_type ch, typename S::size_type start = 0)
+{
+	S result(str);
+	replaceInPlace(result, ch, 0, start);
+	return result;
+}
+
+
+#else
+
+
+Foundation_API std::string replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
+Foundation_API std::string replace(const std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
+Foundation_API std::string replace(const std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
+Foundation_API std::string remove(const std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
+Foundation_API std::string& replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
+Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
+Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
+Foundation_API std::string& removeInPlace(std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
+
+
+#endif
+
+
+template <class S>
+S cat(const S& s1, const S& s2)
+	/// Concatenates two strings.
+{
+	S result = s1;
+	result.reserve(s1.size() + s2.size());
+	result.append(s2);
+	return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3)
+	/// Concatenates three strings.
+{
+	S result = s1;
+	result.reserve(s1.size() + s2.size() + s3.size());
+	result.append(s2);
+	result.append(s3);
+	return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3, const S& s4)
+	/// Concatenates four strings.
+{
+	S result = s1;
+	result.reserve(s1.size() + s2.size() + s3.size() + s4.size());
+	result.append(s2);
+	result.append(s3);
+	result.append(s4);
+	return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5)
+	/// Concatenates five strings.
+{
+	S result = s1;
+	result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size());
+	result.append(s2);
+	result.append(s3);
+	result.append(s4);
+	result.append(s5);
+	return result;
+}
+
+
+template <class S>
+S cat(const S& s1, const S& s2, const S& s3, const S& s4, const S& s5, const S& s6)
+	/// Concatenates six strings.
+{
+	S result = s1;
+	result.reserve(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size());
+	result.append(s2);
+	result.append(s3);
+	result.append(s4);
+	result.append(s5);
+	result.append(s6);
+	return result;
+}
+
+
+template <class S, class It>
+S cat(const S& delim, const It& begin, const It& end)
+	/// Concatenates a sequence of strings, delimited
+	/// by the string given in delim.
+{
+	S result;
+	for (It it = begin; it != end; ++it)
+	{
+		if (!result.empty()) result.append(delim);
+		result += *it;
+	}
+	return result;
+}
+
+
+//
+// case-insensitive string equality
+//
+
+
+template <typename charT>
+struct i_char_traits : public std::char_traits<charT>
+{
+	inline static bool eq(charT c1, charT c2)
+	{
+		return Ascii::toLower(c1) == Ascii::toLower(c2);
+	}
+
+	inline static bool ne(charT c1, charT c2)
+	{
+		return !eq(c1, c2);
+	}
+
+	inline static bool lt(charT c1, charT c2)
+	{
+		return Ascii::toLower(c1) < Ascii::toLower(c2);
+	}
+
+	static int compare(const charT* s1, const charT* s2, std::size_t n)
+	{
+		for (int i = 0; i < n && s1 && s2; ++i, ++s1, ++s2)
+		{
+			if (Ascii::toLower(*s1) == Ascii::toLower(*s2)) continue;
+			else if (Ascii::toLower(*s1) < Ascii::toLower(*s2)) return -1;
+			else return 1;
+		}
+
+		return 0;
+	}
+
+	static const charT* find(const charT* s, int n, charT a)
+	{
+		while(n-- > 0 && Ascii::toLower(*s) != Ascii::toLower(a)) { ++s; }
+		return s;
+	}
+};
+
+
+typedef std::basic_string<char, i_char_traits<char> > istring;
+	/// Case-insensitive std::string counterpart.
+
+
+template<typename T>
+std::size_t isubstr(const T& str, const T& sought)
+	/// Case-insensitive substring; searches for a substring
+	/// without regards to case.
+{
+	typename T::const_iterator it = std::search(str.begin(), str.end(),
+		sought.begin(), sought.end(),
+		i_char_traits<typename T::value_type>::eq);
+
+	if (it != str.end()) return it - str.begin();
+	else return static_cast<std::size_t>(T::npos);
+}
+
+
+struct CILess
+	/// Case-insensitive less-than functor; useful for standard maps
+	/// and sets with std::strings keys and case-insensitive ordering
+	/// requirement.
+{
+	inline bool operator() (const std::string& s1, const std::string& s2) const
+	{
+		return icompare(s1, s2) < 0;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_String_INCLUDED
diff --git a/Poco/StringTokenizer.h b/Poco/StringTokenizer.h
new file mode 100644
index 0000000..e4bfd46
--- /dev/null
+++ b/Poco/StringTokenizer.h
@@ -0,0 +1,135 @@
+//
+// StringTokenizer.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  StringTokenizer
+//
+// Definition of the StringTokenizer class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_StringTokenizer_INCLUDED
+#define Foundation_StringTokenizer_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Exception.h"
+#include <vector>
+#include <cstddef>
+
+
+namespace Poco {
+
+
+class Foundation_API StringTokenizer
+	/// A simple tokenizer that splits a string into
+	/// tokens, which are separated by separator characters.
+	/// An iterator is used to iterate over all tokens.
+{
+public:
+	enum Options
+	{
+		TOK_IGNORE_EMPTY = 1, /// ignore empty tokens
+		TOK_TRIM	 = 2  /// remove leading and trailing whitespace from tokens
+	};
+	
+	typedef std::vector<std::string> TokenVec;
+	typedef TokenVec::const_iterator Iterator;
+	
+	StringTokenizer(const std::string& str, const std::string& separators, int options = 0);
+		/// Splits the given string into tokens. The tokens are expected to be
+		/// separated by one of the separator characters given in separators.
+		/// Additionally, options can be specified:
+		///   * TOK_IGNORE_EMPTY: empty tokens are ignored
+		///   * TOK_TRIM: trailing and leading whitespace is removed from tokens.
+
+	~StringTokenizer();
+		/// Destroys the tokenizer.
+	
+	Iterator begin() const;
+	Iterator end() const;
+	
+	const std::string& operator [] (std::size_t index) const;
+		/// Returns const reference the index'th token.
+		/// Throws a RangeException if the index is out of range.
+
+	std::string& operator [] (std::size_t index);
+		/// Returns reference to the index'th token.
+		/// Throws a RangeException if the index is out of range.
+
+	bool has(const std::string& token) const;
+		/// Returns true if token exists, false otherwise.
+
+	std::string::size_type find(const std::string& token, std::string::size_type pos = 0) const;
+		/// Returns the index of the first occurence of the token
+		/// starting at position pos.
+		/// Throws a NotFoundException if the token is not found.
+
+	std::size_t replace(const std::string& oldToken, const std::string& newToken, std::string::size_type pos = 0);
+		/// Starting at position pos, replaces all subsequent tokens having value 
+		/// equal to oldToken with newToken.
+		/// Returns the number of modified tokens.
+		
+	std::size_t count() const;
+		/// Returns the total number of tokens.
+
+	std::size_t count(const std::string& token) const;
+		/// Returns the number of tokens equal to the specified token.
+
+private:
+	StringTokenizer(const StringTokenizer&);
+	StringTokenizer& operator = (const StringTokenizer&);
+	
+	void trim(std::string& token);
+
+	TokenVec _tokens;
+};
+
+
+//
+// inlines
+//
+
+
+inline StringTokenizer::Iterator StringTokenizer::begin() const
+{
+	return _tokens.begin();
+}
+
+
+inline StringTokenizer::Iterator StringTokenizer::end() const
+{
+	return _tokens.end();
+}
+
+
+inline std::string& StringTokenizer::operator [] (std::size_t index)
+{
+	if (index >= _tokens.size()) throw RangeException();
+	return _tokens[index];
+}
+
+
+inline const std::string& StringTokenizer::operator [] (std::size_t index) const
+{
+	if (index >= _tokens.size()) throw RangeException();
+	return _tokens[index];
+}
+
+
+inline std::size_t StringTokenizer::count() const
+{
+	return _tokens.size();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_StringTokenizer_INCLUDED
diff --git a/Poco/SynchronizedObject.h b/Poco/SynchronizedObject.h
new file mode 100644
index 0000000..b697f48
--- /dev/null
+++ b/Poco/SynchronizedObject.h
@@ -0,0 +1,131 @@
+//
+// SynchronizedObject.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  SynchronizedObject
+//
+// Definition of the SynchronizedObject class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SynchronizedObject_INCLUDED
+#define Foundation_SynchronizedObject_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SynchronizedObject
+	/// This class aggregates a Mutex and an Event
+	/// and can act as a base class for all objects
+	/// requiring synchronization in a multithreaded
+	/// scenario.
+{
+public:
+	typedef Poco::ScopedLock<SynchronizedObject> ScopedLock;
+	
+	SynchronizedObject();
+		/// Creates the object.
+		
+	virtual ~SynchronizedObject();
+		/// Destroys the object.
+
+	void lock() const;
+		/// Locks the object. Blocks if the object
+		/// is locked by another thread.
+
+	bool tryLock() const;
+		/// Tries to lock the object. Returns false immediately
+		/// if the object is already locked by another thread
+		/// Returns true if the object was successfully locked.
+	
+	void unlock() const;
+		/// Unlocks the object so that it can be locked by
+		/// other threads.
+		
+	void notify() const;
+		/// Signals the object. 
+		/// Exactly only one thread waiting for the object 
+		/// can resume execution.
+
+	void wait() const;
+		/// Waits for the object to become signalled.
+
+	void wait(long milliseconds) const;
+		/// Waits for the object to become signalled.
+		/// Throws a TimeoutException if the object
+		/// does not become signalled within the specified
+		/// time interval.
+
+	bool tryWait(long milliseconds) const;
+		/// Waits for the object to become signalled.
+		/// Returns true if the object
+		/// became signalled within the specified
+		/// time interval, false otherwise.
+
+private:
+	mutable Mutex _mutex;
+	mutable Event _event;
+};
+
+
+//
+// inlines
+//
+inline void SynchronizedObject::lock() const
+{
+	_mutex.lock();
+}
+
+
+inline bool SynchronizedObject::tryLock() const
+{
+	return _mutex.tryLock();
+}
+
+
+inline void SynchronizedObject::unlock() const
+{
+	_mutex.unlock();
+}
+
+
+inline void SynchronizedObject::notify() const
+{
+	_event.set();
+}
+
+
+inline void SynchronizedObject::wait() const
+{
+	_event.wait();
+}
+
+
+inline void SynchronizedObject::wait(long milliseconds) const
+{
+	_event.wait(milliseconds);
+}
+
+
+inline bool SynchronizedObject::tryWait(long milliseconds) const
+{
+	return _event.tryWait(milliseconds);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SynchronizedObject_INCLUDED
diff --git a/Poco/SyslogChannel.h b/Poco/SyslogChannel.h
new file mode 100644
index 0000000..4c304e8
--- /dev/null
+++ b/Poco/SyslogChannel.h
@@ -0,0 +1,109 @@
+//
+// SyslogChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  SyslogChannel
+//
+// Definition of the SyslogChannel class specific to UNIX.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_SyslogChannel_INCLUDED
+#define Foundation_SyslogChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+
+
+namespace Poco {
+
+
+class Foundation_API SyslogChannel: public Channel
+	/// This Unix-only channel works with the Unix syslog service.
+{
+public:
+	enum Option
+	{
+		SYSLOG_PID    = 0x01, /// log the pid with each message
+		SYSLOG_CONS   = 0x02, /// log on the console if errors in sending
+		SYSLOG_NDELAY = 0x08, /// don't delay open
+		SYSLOG_PERROR = 0x20  /// log to stderr as well (not supported on all platforms)
+	};
+	
+	enum Facility
+	{
+		SYSLOG_KERN     = ( 0<<3), /// kernel messages
+		SYSLOG_USER     = ( 1<<3), /// random user-level messages
+		SYSLOG_MAIL     = ( 2<<3), /// mail system
+		SYSLOG_DAEMON   = ( 3<<3), /// system daemons
+		SYSLOG_AUTH     = ( 4<<3), /// security/authorization messages
+		SYSLOG_SYSLOG   = ( 5<<3), /// messages generated internally by syslogd
+		SYSLOG_LPR      = ( 6<<3), /// line printer subsystem
+		SYSLOG_NEWS     = ( 7<<3), /// network news subsystem
+		SYSLOG_UUCP     = ( 8<<3), /// UUCP subsystem
+		SYSLOG_CRON     = ( 9<<3), /// clock daemon
+		SYSLOG_AUTHPRIV = (10<<3), /// security/authorization messages (private)
+		SYSLOG_FTP      = (11<<3), /// ftp daemon
+		SYSLOG_LOCAL0   = (16<<3), /// reserved for local use
+		SYSLOG_LOCAL1   = (17<<3), /// reserved for local use
+		SYSLOG_LOCAL2   = (18<<3), /// reserved for local use
+		SYSLOG_LOCAL3   = (19<<3), /// reserved for local use
+		SYSLOG_LOCAL4   = (20<<3), /// reserved for local use
+		SYSLOG_LOCAL5   = (21<<3), /// reserved for local use
+		SYSLOG_LOCAL6   = (22<<3), /// reserved for local use
+		SYSLOG_LOCAL7   = (23<<3)  /// reserved for local use
+	};
+	
+	SyslogChannel();
+		/// Creates a SyslogChannel.
+		
+	SyslogChannel(const std::string& name, int options = SYSLOG_CONS, int facility = SYSLOG_USER);
+		/// Creates a SyslogChannel with the given name, options and facility.
+	
+	void open();
+		/// Opens the SyslogChannel.
+		
+	void close();
+		/// Closes the SyslogChannel.
+		
+	void log(const Message& msg);
+		/// Sens the message's text to the syslog service.
+		
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given value.
+		///
+		/// The following properties are supported:
+		///     * name:     The name used to identify the source of log messages.
+		///     * facility: The facility added to each log message. See the Facility enumeration for a list of supported values.
+		///     * options:  The logging options. See the Option enumeration for a list of supported values.
+		
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+
+	static const std::string PROP_NAME;
+	static const std::string PROP_FACILITY;
+	static const std::string PROP_OPTIONS;
+
+protected:
+	~SyslogChannel();
+	static int getPrio(const Message& msg);
+
+private:
+	std::string _name;
+	int  _options;
+	int  _facility;
+	bool _open;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_SyslogChannel_INCLUDED
diff --git a/Poco/Task.h b/Poco/Task.h
new file mode 100644
index 0000000..01b5249
--- /dev/null
+++ b/Poco/Task.h
@@ -0,0 +1,189 @@
+//
+// Task.h
+//
+// Library: Foundation
+// Package: Tasks
+// Module:  Tasks
+//
+// Definition of the Task class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Task_INCLUDED
+#define Foundation_Task_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+
+
+namespace Poco {
+
+
+class TaskManager;
+class Notification;
+class NotificationCenter;
+
+
+class Foundation_API Task: public Runnable, public RefCountedObject
+	/// A Task is a subclass of Runnable that has a name 
+	/// and supports progress reporting and cancellation.
+	///
+	/// A TaskManager object can be used to take care of the
+	/// lifecycle of a Task.
+{
+public:
+	enum TaskState
+	{
+		TASK_IDLE,
+		TASK_STARTING,
+		TASK_RUNNING,
+		TASK_CANCELLING,
+		TASK_FINISHED
+	};
+	
+	Task(const std::string& name);
+		/// Creates the Task.
+
+	const std::string& name() const;
+		/// Returns the task's name.	
+		
+	float progress() const;
+		/// Returns the task's progress.
+		/// The value will be between 0.0 (just started)
+		/// and 1.0 (completed).
+
+	virtual void cancel();
+		/// Requests the task to cancel itself. For cancellation
+		/// to work, the task's runTask() method must periodically
+		/// call isCancelled() and react accordingly.
+		///
+		/// Can be overridden to implement custom behavior,
+		/// but the base class implementation of cancel() should
+		/// be called to ensure proper behavior.
+
+	bool isCancelled() const;
+		/// Returns true if cancellation of the task has been
+		/// requested. 
+		///
+		/// A Task's runTask() method should periodically
+		/// call this method and stop whatever it is doing in an
+		/// orderly way when this method returns true.
+
+	TaskState state() const;
+		/// Returns the task's current state.
+
+	void reset();
+		/// Sets the task's progress to zero and clears the
+		/// cancel flag.
+		
+	virtual void runTask() = 0;
+		/// Do whatever the task needs to do. Must
+		/// be overridden by subclasses.
+		
+	void run();
+		/// Calls the task's runTask() method and notifies the owner
+		/// of the task's start and completion.
+
+protected:
+	bool sleep(long milliseconds);
+		/// Suspends the current thread for the specified
+		/// amount of time.
+		///
+		/// If the task is cancelled while it is sleeping,
+		/// sleep() will return immediately and the return
+		/// value will be true. If the time interval
+		/// passes without the task being cancelled, the
+		/// return value is false.
+		///
+		/// A Task should use this method in favor of Thread::sleep().
+
+	void setProgress(float progress);
+		/// Sets the task's progress.
+		/// The value should be between 0.0 (just started)
+		/// and 1.0 (completed).
+
+	virtual void postNotification(Notification* pNf);
+		/// Posts a notification to the task manager's
+		/// notification center.
+		///
+		/// A task can use this method to post custom
+		/// notifications about its progress.
+
+	void setOwner(TaskManager* pOwner);
+		/// Sets the (optional) owner of the task.
+		
+	TaskManager* getOwner() const;
+		/// Returns the owner of the task, which may be NULL.
+
+	void setState(TaskState state);
+		/// Sets the task's state.
+
+	virtual ~Task();
+		/// Destroys the Task.
+		
+private:
+	Task();
+	Task(const Task&);
+	Task& operator = (const Task&);
+	
+	std::string       _name;
+	TaskManager*      _pOwner;
+	float             _progress;
+	TaskState         _state;
+	Event             _cancelEvent;
+	mutable FastMutex _mutex;
+	
+	friend class TaskManager;
+};
+
+
+//
+// inlines
+//
+inline const std::string& Task::name() const
+{
+	return _name;
+}
+
+
+inline float Task::progress() const
+{
+	FastMutex::ScopedLock lock(_mutex);
+
+	return _progress;
+}
+
+
+inline bool Task::isCancelled() const
+{
+	return _state == TASK_CANCELLING;
+}
+
+
+inline Task::TaskState Task::state() const
+{
+	return _state;
+}
+
+
+inline TaskManager* Task::getOwner() const
+{
+	FastMutex::ScopedLock lock(_mutex);
+
+	return _pOwner;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Task_INCLUDED
diff --git a/Poco/TaskManager.h b/Poco/TaskManager.h
new file mode 100644
index 0000000..3d6e7f1
--- /dev/null
+++ b/Poco/TaskManager.h
@@ -0,0 +1,137 @@
+//
+// TaskManager.h
+//
+// Library: Foundation
+// Package: Tasks
+// Module:  Tasks
+//
+// Definition of the TaskManager class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TaskManager_INCLUDED
+#define Foundation_TaskManager_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include "Poco/Task.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/NotificationCenter.h"
+#include "Poco/Timestamp.h"
+#include <list>
+
+
+namespace Poco {
+
+
+class Notification;
+class ThreadPool;
+class Exception;
+
+
+class Foundation_API TaskManager
+	/// The TaskManager manages a collection of tasks
+	/// and monitors their lifetime.
+	///
+	/// A TaskManager has a built-in NotificationCenter that
+	/// is used to send out notifications on task progress
+	/// and task states. See the TaskNotification class and its
+	/// subclasses for the various events that result in a notification.
+	/// To keep the number of notifications small, a TaskProgressNotification
+	/// will only be sent out once in 100 milliseconds.
+{
+public:
+	typedef AutoPtr<Task>      TaskPtr;
+	typedef std::list<TaskPtr> TaskList;
+
+	TaskManager();
+		/// Creates the TaskManager, using the
+		/// default ThreadPool.
+
+	TaskManager(ThreadPool& pool);
+		/// Creates the TaskManager, using the
+		/// given ThreadPool.
+
+	~TaskManager();
+		/// Destroys the TaskManager.
+
+	void start(Task* pTask);
+		/// Starts the given task in a thread obtained
+		/// from the thread pool.
+		///
+		/// The TaskManager takes ownership of the Task object
+		/// and deletes it when it it finished.
+
+	void cancelAll();
+		/// Requests cancellation of all tasks.
+		
+	void joinAll();
+		/// Waits for the completion of all the threads
+		/// in the TaskManager's thread pool.
+		///
+		/// Note: joinAll() will wait for ALL tasks in the
+		/// TaskManager's ThreadPool to complete. If the
+		/// ThreadPool has threads created by other
+		/// facilities, these threads must also complete
+		/// before joinAll() can return.
+
+	TaskList taskList() const;
+		/// Returns a copy of the internal task list.
+
+	int count() const;
+		/// Returns the number of tasks in the internal task list.
+
+	void addObserver(const AbstractObserver& observer);
+		/// Registers an observer with the NotificationCenter.
+		/// Usage:
+		///     Observer<MyClass, MyNotification> obs(*this, &MyClass::handleNotification);
+		///     notificationCenter.addObserver(obs);
+
+	void removeObserver(const AbstractObserver& observer);
+		/// Unregisters an observer with the NotificationCenter.
+
+	static const int MIN_PROGRESS_NOTIFICATION_INTERVAL;
+
+protected:
+	void postNotification(const Notification::Ptr& pNf);
+		/// Posts a notification to the task manager's 
+		/// notification center.
+
+	void taskStarted(Task* pTask);
+	void taskProgress(Task* pTask, float progress);
+	void taskCancelled(Task* pTask);
+	void taskFinished(Task* pTask);
+	void taskFailed(Task* pTask, const Exception& exc);
+
+private:
+	ThreadPool&        _threadPool;
+	TaskList           _taskList;
+	Timestamp          _lastProgressNotification;
+	NotificationCenter _nc;
+	mutable FastMutex  _mutex;
+
+	friend class Task;
+};
+
+
+//
+// inlines
+//
+inline int TaskManager::count() const
+{
+	FastMutex::ScopedLock lock(_mutex);
+
+	return (int) _taskList.size();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TaskManager_INCLUDED
diff --git a/Poco/TaskNotification.h b/Poco/TaskNotification.h
new file mode 100644
index 0000000..92d8a95
--- /dev/null
+++ b/Poco/TaskNotification.h
@@ -0,0 +1,170 @@
+//
+// TaskNotification.h
+//
+// Library: Foundation
+// Package: Tasks
+// Module:  Tasks
+//
+// Definition of the TaskNotification class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TaskNotification_INCLUDED
+#define Foundation_TaskNotification_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Notification.h"
+#include "Poco/Task.h"
+
+
+namespace Poco {
+
+
+class Foundation_API TaskNotification: public Notification
+	/// Base class for TaskManager notifications.
+{
+public:
+	TaskNotification(Task* pTask);
+		/// Creates the TaskNotification.
+
+	Task* task() const;
+		/// Returns the subject of the notification.
+
+protected:
+	virtual ~TaskNotification();
+		/// Destroys the TaskNotification.
+
+private:
+	Task* _pTask;
+};
+
+
+class Foundation_API TaskStartedNotification: public TaskNotification
+	/// This notification is posted by the TaskManager for
+	/// every task that has been started.
+{
+public:
+	TaskStartedNotification(Task* pTask);
+	
+protected:
+	~TaskStartedNotification();
+};
+
+
+class Foundation_API TaskCancelledNotification: public TaskNotification
+	/// This notification is posted by the TaskManager for
+	/// every task that has been cancelled.
+{
+public:
+	TaskCancelledNotification(Task* pTask);
+
+protected:
+	~TaskCancelledNotification();
+};
+
+
+class Foundation_API TaskFinishedNotification: public TaskNotification
+	/// This notification is posted by the TaskManager for
+	/// every task that has finished.
+{
+public:
+	TaskFinishedNotification(Task* pTask);
+
+protected:
+	~TaskFinishedNotification();
+};
+
+
+class Foundation_API TaskFailedNotification: public TaskNotification
+	/// This notification is posted by the TaskManager for
+	/// every task that has failed with an exception.
+{
+public:
+	TaskFailedNotification(Task* pTask, const Exception& exc);
+
+	const Exception& reason() const;
+
+protected:
+	~TaskFailedNotification();
+	
+private:
+	Exception* _pException;
+};
+
+
+class Foundation_API TaskProgressNotification: public TaskNotification
+	/// This notification is posted by the TaskManager for
+	/// a task when its progress changes.
+{
+public:
+	TaskProgressNotification(Task* pTask, float progress);
+
+	float progress() const;
+
+protected:
+	~TaskProgressNotification();
+	
+private:
+	float _progress;
+};
+
+
+template <class C>
+class TaskCustomNotification: public TaskNotification
+	/// This is a template for "custom" notification.
+	/// Unlike other notifications, this notification
+	/// is instantiated and posted by the task itself.
+	/// The purpose is to provide generic notifiation
+	/// mechanism between the task and its observer(s).
+{
+public:
+	TaskCustomNotification(Task* pTask, const C& custom):
+		TaskNotification(pTask),
+		_custom(custom)
+	{
+	}
+
+	const C& custom() const
+	{
+		return _custom;
+	}
+
+protected:
+	~TaskCustomNotification(){};
+	
+private:
+	C _custom;
+};
+
+
+//
+// inlines
+//
+inline Task* TaskNotification::task() const
+{
+	return _pTask;
+}
+
+
+inline const Exception& TaskFailedNotification::reason() const
+{
+	return *_pException;
+}
+
+
+inline float TaskProgressNotification::progress() const
+{
+	return _progress;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TaskNotification_INCLUDED
diff --git a/Poco/TeeStream.h b/Poco/TeeStream.h
new file mode 100644
index 0000000..07744d8
--- /dev/null
+++ b/Poco/TeeStream.h
@@ -0,0 +1,132 @@
+//
+// TeeStream.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  TeeStream
+//
+// Definition of the TeeStream class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TeeStream_INCLUDED
+#define Foundation_TeeStream_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UnbufferedStreamBuf.h"
+#include <vector>
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+
+
+class Foundation_API TeeStreamBuf: public UnbufferedStreamBuf
+	/// This stream buffer copies all data written to or
+	/// read from it to one or multiple output streams.
+{
+public:
+	TeeStreamBuf();
+		/// Creates an unconnected CountingStreamBuf.
+		/// Use addStream() to attach output streams.
+	
+	TeeStreamBuf(std::istream& istr);
+		/// Creates the CountingStreamBuf and connects it
+		/// to the given input stream.
+
+	TeeStreamBuf(std::ostream& ostr);
+		/// Creates the CountingStreamBuf and connects it
+		/// to the given output stream.
+
+	~TeeStreamBuf();
+		/// Destroys the CountingStream.
+
+	void addStream(std::ostream& ostr);
+		/// Adds the given output stream.
+
+protected:
+	int readFromDevice();
+	int writeToDevice(char c);
+
+private:
+	typedef std::vector<std::ostream*> StreamVec;
+	
+	std::istream* _pIstr;
+	StreamVec     _streams;
+};
+
+
+class Foundation_API TeeIOS: public virtual std::ios
+	/// The base class for TeeInputStream and TeeOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	TeeIOS();
+		/// Creates the basic stream and leaves it unconnected.
+
+	TeeIOS(std::istream& istr);
+		/// Creates the basic stream and connects it
+		/// to the given input stream.
+
+	TeeIOS(std::ostream& ostr);
+		/// Creates the basic stream and connects it
+		/// to the given output stream.
+
+	~TeeIOS();
+		/// Destroys the stream.
+
+	void addStream(std::ostream& ostr);
+		/// Adds the given output stream.
+
+	TeeStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	TeeStreamBuf _buf;
+};
+
+
+class Foundation_API TeeInputStream: public TeeIOS, public std::istream
+	/// This stream copies all characters read through it
+	/// to one or multiple output streams.
+{
+public:
+	TeeInputStream(std::istream& istr);
+		/// Creates the TeeInputStream and connects it
+		/// to the given input stream.
+
+	~TeeInputStream();
+		/// Destroys the TeeInputStream.
+};
+
+
+class Foundation_API TeeOutputStream: public TeeIOS, public std::ostream
+	/// This stream copies all characters written to it
+	/// to one or multiple output streams.
+{
+public:
+	TeeOutputStream();
+		/// Creates an unconnected TeeOutputStream.
+	
+	TeeOutputStream(std::ostream& ostr);
+		/// Creates the TeeOutputStream and connects it
+		/// to the given input stream.
+
+	~TeeOutputStream();
+		/// Destroys the TeeOutputStream.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TeeStream_INCLUDED
diff --git a/Poco/TemporaryFile.h b/Poco/TemporaryFile.h
new file mode 100644
index 0000000..9246846
--- /dev/null
+++ b/Poco/TemporaryFile.h
@@ -0,0 +1,84 @@
+//
+// TemporaryFile.h
+//
+// Library: Foundation
+// Package: Filesystem
+// Module:  TemporaryFile
+//
+// Definition of the TemporaryFile class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TemporaryFile_INCLUDED
+#define Foundation_TemporaryFile_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/File.h"
+
+
+namespace Poco {
+
+
+class Foundation_API TemporaryFile: public File
+	/// The TemporaryFile class helps with the handling
+	/// of temporary files.
+	/// A unique name for the temporary file is
+	/// automatically chosen and the file is placed
+	/// in the directory reserved for temporary
+	/// files (see Path::temp()).
+	/// Obtain the path by calling the path() method
+	/// (inherited from File).
+	///
+	/// The TemporaryFile class does not actually
+	/// create the file - this is up to the application.
+	/// The class does, however, delete the temporary
+	/// file - either in the destructor, or immediately
+	/// before the application terminates.
+{
+public:
+	TemporaryFile();
+		/// Creates the TemporaryFile.
+
+	TemporaryFile(const std::string& tempDir);
+		/// Creates the TemporaryFile using the given directory.
+
+	~TemporaryFile();
+		/// Destroys the TemporaryFile and
+		/// deletes the corresponding file on
+		/// disk unless keep() or keepUntilExit()
+		/// has been called.
+
+	void keep();
+		/// Disables automatic deletion of the file in
+		/// the destructor.
+
+	void keepUntilExit();
+		/// Disables automatic deletion of the file in
+		/// the destructor, but registers the file
+		/// for deletion at process termination.
+
+	static void registerForDeletion(const std::string& path);
+		/// Registers the given file for deletion
+		/// at process termination.
+
+	static std::string tempName(const std::string& tempDir = "");
+		/// Returns a unique path name for a temporary
+		/// file in the system's scratch directory (see Path::temp())
+		/// if tempDir is empty or in the directory specified in tempDir
+		/// otherwise.
+
+private:
+	bool _keep;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TemporaryFile_INCLUDED
diff --git a/Poco/TextBufferIterator.h b/Poco/TextBufferIterator.h
new file mode 100644
index 0000000..d8eda84
--- /dev/null
+++ b/Poco/TextBufferIterator.h
@@ -0,0 +1,145 @@
+//
+// TextBufferIterator.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  TextBufferIterator
+//
+// Definition of the TextBufferIterator class.
+//
+// Copyright (c) 2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TextBufferIterator_INCLUDED
+#define Foundation_TextBufferIterator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <cstdlib>
+
+
+namespace Poco {
+
+
+class TextEncoding;
+
+
+class Foundation_API TextBufferIterator
+	/// An unidirectional iterator for iterating over characters in a buffer.
+	/// The TextBufferIterator uses a TextEncoding object to
+	/// work with multi-byte character encodings like UTF-8.
+	/// Characters are reported in Unicode.
+	///
+	/// Example: Count the number of UTF-8 characters in a buffer.
+	///
+	///     UTF8Encoding utf8Encoding;
+	///     char buffer[] = "...";
+	///     TextBufferIterator it(buffer, utf8Encoding);
+	///     TextBufferIterator end(it.end());
+	///     int n = 0;
+	///     while (it != end) { ++n; ++it; }
+	///
+	/// NOTE: When an UTF-16 encoding is used, surrogate pairs will be
+	/// reported as two separate characters, due to restrictions of
+	/// the TextEncoding class.
+	///
+	/// For iterating over the characters in a std::string, see the
+	/// TextIterator class.
+{
+public:
+	TextBufferIterator();
+		/// Creates an uninitialized TextBufferIterator.
+		
+	TextBufferIterator(const char* begin, const TextEncoding& encoding);
+		/// Creates a TextBufferIterator for the given buffer, which must be 0-terminated.
+		/// The encoding object must not be deleted as long as the iterator
+		/// is in use.
+
+	TextBufferIterator(const char* begin, std::size_t size, const TextEncoding& encoding);
+		/// Creates a TextBufferIterator for the given buffer with the given size.
+		/// The encoding object must not be deleted as long as the iterator
+		/// is in use.
+
+	TextBufferIterator(const char* begin, const char* end, const TextEncoding& encoding);
+		/// Creates a TextBufferIterator for the given range.
+		/// The encoding object must not be deleted as long as the iterator
+		/// is in use.
+
+	TextBufferIterator(const char* end);
+		/// Creates an end TextBufferIterator for the given buffer.
+
+	~TextBufferIterator();
+		/// Destroys the TextBufferIterator.
+	
+	TextBufferIterator(const TextBufferIterator& it);
+		/// Copy constructor.
+	
+	TextBufferIterator& operator = (const TextBufferIterator& it);
+		/// Assignment operator.
+		
+	void swap(TextBufferIterator& it);
+		/// Swaps the iterator with another one.
+	
+	int operator * () const;
+		/// Returns the Unicode value of the current character.
+		/// If there is no valid character at the current position,
+		/// -1 is returned.
+		
+	TextBufferIterator& operator ++ (); 
+		/// Prefix increment operator.
+
+	TextBufferIterator operator ++ (int);		
+		/// Postfix increment operator.
+
+	bool operator == (const TextBufferIterator& it) const;
+		/// Compares two iterators for equality.
+		
+	bool operator != (const TextBufferIterator& it) const;
+		/// Compares two iterators for inequality.
+
+	TextBufferIterator end() const;
+		/// Returns the end iterator for the range handled
+		/// by the iterator.
+		
+private:
+	const TextEncoding* _pEncoding;
+	const char* _it;
+	const char* _end;
+};
+
+
+//
+// inlines
+//
+inline bool TextBufferIterator::operator == (const TextBufferIterator& it) const
+{
+	return _it == it._it;
+}
+
+
+inline bool TextBufferIterator::operator != (const TextBufferIterator& it) const
+{
+	return _it != it._it;
+}
+
+
+inline void swap(TextBufferIterator& it1, TextBufferIterator& it2)
+{
+	it1.swap(it2);
+}
+
+
+inline TextBufferIterator TextBufferIterator::end() const
+{
+	return TextBufferIterator(_end);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TextBufferIterator_INCLUDED
diff --git a/Poco/TextConverter.h b/Poco/TextConverter.h
new file mode 100644
index 0000000..ebf978f
--- /dev/null
+++ b/Poco/TextConverter.h
@@ -0,0 +1,93 @@
+//
+// TextConverter.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  TextConverter
+//
+// Definition of the TextConverter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TextConverter_INCLUDED
+#define Foundation_TextConverter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class TextEncoding;
+
+
+class Foundation_API TextConverter
+	/// A TextConverter converts strings from one encoding
+	/// into another.
+{
+public:
+	typedef int (*Transform)(int);
+		/// Transform function for convert.
+		
+	TextConverter(const TextEncoding& inEncoding, const TextEncoding& outEncoding, int defaultChar = '?');
+		/// Creates the TextConverter. The encoding objects must not be deleted while the
+		/// TextConverter is in use.
+
+	~TextConverter();
+		/// Destroys the TextConverter.
+		
+	int convert(const std::string& source, std::string& destination, Transform trans);
+		/// Converts the source string from inEncoding to outEncoding
+		/// and appends the result to destination. Every character is
+		/// passed to the transform function.
+		/// If a character cannot be represented in outEncoding, defaultChar
+		/// is used instead.
+		/// Returns the number of encoding errors (invalid byte sequences
+		/// in source).
+
+	int convert(const void* source, int length, std::string& destination, Transform trans);
+		/// Converts the source buffer from inEncoding to outEncoding
+		/// and appends the result to destination. Every character is
+		/// passed to the transform function.
+		/// If a character cannot be represented in outEncoding, defaultChar
+		/// is used instead.
+		/// Returns the number of encoding errors (invalid byte sequences
+		/// in source).
+
+	int convert(const std::string& source, std::string& destination);
+		/// Converts the source string from inEncoding to outEncoding
+		/// and appends the result to destination.
+		/// If a character cannot be represented in outEncoding, defaultChar
+		/// is used instead.
+		/// Returns the number of encoding errors (invalid byte sequences
+		/// in source).
+
+	int convert(const void* source, int length, std::string& destination);
+		/// Converts the source buffer from inEncoding to outEncoding
+		/// and appends the result to destination.
+		/// If a character cannot be represented in outEncoding, defaultChar
+		/// is used instead.
+		/// Returns the number of encoding errors (invalid byte sequences
+		/// in source).
+
+private:
+	TextConverter();
+	TextConverter(const TextConverter&);
+	TextConverter& operator = (const TextConverter&);
+
+	const TextEncoding& _inEncoding;
+	const TextEncoding& _outEncoding;
+	int                 _defaultChar;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TextConverter_INCLUDED
diff --git a/Poco/TextEncoding.h b/Poco/TextEncoding.h
new file mode 100644
index 0000000..40d64b7
--- /dev/null
+++ b/Poco/TextEncoding.h
@@ -0,0 +1,185 @@
+//
+// TextEncoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  TextEncoding
+//
+// Definition of the abstract TextEncoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TextEncoding_INCLUDED
+#define Foundation_TextEncoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/SharedPtr.h"
+
+
+namespace Poco {
+
+
+class TextEncodingManager;
+
+
+class Foundation_API TextEncoding
+	/// An abstract base class for implementing text encodings
+	/// like UTF-8 or ISO 8859-1.
+	///
+	/// Subclasses must override the canonicalName(), isA(),
+	/// characterMap() and convert() methods and need to be
+	/// thread safe and stateless.
+	///
+	/// TextEncoding also provides static member functions
+	/// for managing mappings from encoding names to
+	/// TextEncoding objects.
+{
+public:
+	typedef SharedPtr<TextEncoding> Ptr;
+
+	enum
+	{
+		MAX_SEQUENCE_LENGTH = 4 /// The maximum character byte sequence length supported.
+	};
+
+	typedef int CharacterMap[256];
+		/// The map[b] member gives information about byte sequences
+		/// whose first byte is b.
+		/// If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c.
+		/// If map[b] is -1, then the byte sequence is malformed.
+		/// If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
+		/// sequence that encodes a single Unicode scalar value. Byte sequences up
+		/// to 4 bytes in length are supported.
+
+	virtual ~TextEncoding();
+		/// Destroys the encoding.
+
+	virtual const char* canonicalName() const = 0;
+		/// Returns the canonical name of this encoding,
+		/// e.g. "ISO-8859-1". Encoding name comparisons are case
+		/// insensitive.
+
+	virtual bool isA(const std::string& encodingName) const = 0;
+		/// Returns true if the given name is one of the names of this encoding.
+		/// For example, the "ISO-8859-1" encoding is also known as "Latin-1".
+		///
+		/// Encoding name comparisions are case insensitive.
+
+	virtual const CharacterMap& characterMap() const = 0;
+		/// Returns the CharacterMap for the encoding.
+		/// The CharacterMap should be kept in a static member. As
+		/// characterMap() can be called frequently, it should be
+		/// implemented in such a way that it just returns a static
+		/// map. If the map is built at runtime, this should be
+		/// done in the constructor.
+
+	virtual int convert(const unsigned char* bytes) const;
+		/// The convert function is used to convert multibyte sequences;
+		/// bytes will point to a byte sequence of n bytes where
+		/// sequenceLength(bytes, length) == -n, with length >= n.
+		///
+		/// The convert function must return the Unicode scalar value
+		/// represented by this byte sequence or -1 if the byte sequence is malformed.
+		///
+		/// The default implementation returns (int) bytes[0].
+
+	virtual	int queryConvert(const unsigned char* bytes, int length) const;
+		/// The queryConvert function is used to convert single byte characters
+		/// or multibyte sequences;
+		/// bytes will point to a byte sequence of length bytes.
+		///
+		/// The queryConvert function must return the Unicode scalar value
+		/// represented by this byte sequence or -1 if the byte sequence is malformed
+		/// or -n where n is number of bytes requested for the sequence, if length is
+		/// shorter than the sequence.
+		/// The length of the sequence might not be determined by the first byte,
+		/// in which case the conversion becomes an iterative process:
+		/// First call with length == 1 might return -2,
+		/// Then a second call with length == 2 might return -4
+		/// Eventually, the third call with length == 4 should return either a
+		/// Unicode scalar value, or -1 if the byte sequence is malformed.
+		///
+		/// The default implementation returns (int) bytes[0].
+
+	virtual int sequenceLength(const unsigned char* bytes, int length) const;
+		/// The sequenceLength function is used to get the lenth of the sequence pointed
+		/// by bytes. The length parameter should be greater or equal to the length of
+		/// the sequence.
+		///
+		/// The sequenceLength function must return the length of the sequence
+		/// represented by this byte sequence or a negative value -n if length is
+		/// shorter than the sequence, where n is the number of byte requested
+		/// to determine the length of the sequence.
+		/// The length of the sequence might not be determined by the first byte,
+		/// in which case the conversion becomes an iterative process as long as the
+		/// result is negative:
+		/// First call with length == 1 might return -2,
+		/// Then a second call with length == 2 might return -4
+		/// Eventually, the third call with length == 4 should return 4.
+		/// The default implementation returns 1.
+
+	virtual int convert(int ch, unsigned char* bytes, int length) const;
+		/// Transform the Unicode character ch into the encoding's
+		/// byte sequence. The method returns the number of bytes
+		/// used. The method must not use more than length characters.
+		/// Bytes and length can also be null - in this case only the number
+		/// of bytes required to represent ch is returned.
+		/// If the character cannot be converted, 0 is returned and
+		/// the byte sequence remains unchanged.
+		/// The default implementation simply returns 0.
+
+	static TextEncoding& byName(const std::string& encodingName);
+		/// Returns the TextEncoding object for the given encoding name.
+		///
+		/// Throws a NotFoundException if the encoding with given name is not available.
+
+	static TextEncoding::Ptr find(const std::string& encodingName);
+		/// Returns a pointer to the TextEncoding object for the given encodingName,
+		/// or NULL if no such TextEncoding object exists.
+
+	static void add(TextEncoding::Ptr encoding);
+		/// Adds the given TextEncoding to the table of text encodings,
+		/// under the encoding's canonical name.
+		///
+		/// If an encoding with the given name is already registered,
+		/// it is replaced.
+
+	static void add(TextEncoding::Ptr encoding, const std::string& name);
+		/// Adds the given TextEncoding to the table of text encodings,
+		/// under the given name.
+		///
+		/// If an encoding with the given name is already registered,
+		/// it is replaced.
+
+	static void remove(const std::string& encodingName);
+		/// Removes the encoding with the given name from the table
+		/// of text encodings.
+
+	static TextEncoding::Ptr global(TextEncoding::Ptr encoding);
+		/// Sets global TextEncoding object.
+		///
+		/// This function sets the global encoding to the argument and returns a
+		/// reference of the previous global encoding.
+
+	static TextEncoding& global();
+		/// Return the current global TextEncoding object
+
+	static const std::string GLOBAL;
+		/// Name of the global TextEncoding, which is the empty string.
+
+protected:
+	static TextEncodingManager& manager();
+		/// Returns the TextEncodingManager.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TextEncoding_INCLUDED
diff --git a/Poco/TextIterator.h b/Poco/TextIterator.h
new file mode 100644
index 0000000..17f48a4
--- /dev/null
+++ b/Poco/TextIterator.h
@@ -0,0 +1,141 @@
+//
+// TextIterator.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  TextIterator
+//
+// Definition of the TextIterator class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TextIterator_INCLUDED
+#define Foundation_TextIterator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class TextEncoding;
+
+
+class Foundation_API TextIterator
+	/// An unidirectional iterator for iterating over characters in a string.
+	/// The TextIterator uses a TextEncoding object to
+	/// work with multi-byte character encodings like UTF-8.
+	/// Characters are reported in Unicode.
+	///
+	/// Example: Count the number of UTF-8 characters in a string.
+	///
+	///     UTF8Encoding utf8Encoding;
+	///     std::string utf8String("....");
+	///     TextIterator it(utf8String, utf8Encoding);
+	///     TextIterator end(utf8String);
+	///     int n = 0;
+	///     while (it != end) { ++n; ++it; }
+	///
+	/// NOTE: When an UTF-16 encoding is used, surrogate pairs will be
+	/// reported as two separate characters, due to restrictions of
+	/// the TextEncoding class.
+	///
+	/// For iterating over char buffers, see the TextBufferIterator class.
+{
+public:
+	TextIterator();
+		/// Creates an uninitialized TextIterator.
+		
+	TextIterator(const std::string& str, const TextEncoding& encoding);
+		/// Creates a TextIterator for the given string.
+		/// The encoding object must not be deleted as long as the iterator
+		/// is in use.
+
+	TextIterator(const std::string::const_iterator& begin, const std::string::const_iterator& end, const TextEncoding& encoding);
+		/// Creates a TextIterator for the given range.
+		/// The encoding object must not be deleted as long as the iterator
+		/// is in use.
+
+	TextIterator(const std::string& str);
+		/// Creates an end TextIterator for the given string.
+
+	TextIterator(const std::string::const_iterator& end);
+		/// Creates an end TextIterator.
+
+	~TextIterator();
+		/// Destroys the TextIterator.
+	
+	TextIterator(const TextIterator& it);
+		/// Copy constructor.
+	
+	TextIterator& operator = (const TextIterator& it);
+		/// Assignment operator.
+		
+	void swap(TextIterator& it);
+		/// Swaps the iterator with another one.
+	
+	int operator * () const;
+		/// Returns the Unicode value of the current character.
+		/// If there is no valid character at the current position,
+		/// -1 is returned.
+		
+	TextIterator& operator ++ (); 
+		/// Prefix increment operator.
+
+	TextIterator operator ++ (int);		
+		/// Postfix increment operator.
+
+	bool operator == (const TextIterator& it) const;
+		/// Compares two iterators for equality.
+		
+	bool operator != (const TextIterator& it) const;
+		/// Compares two iterators for inequality.
+		
+	TextIterator end() const;
+		/// Returns the end iterator for the range handled
+		/// by the iterator.
+		
+private:
+	const TextEncoding*         _pEncoding;
+	std::string::const_iterator _it;
+	std::string::const_iterator _end;
+};
+
+
+//
+// inlines
+//
+inline bool TextIterator::operator == (const TextIterator& it) const
+{
+	return _it == it._it;
+}
+
+
+inline bool TextIterator::operator != (const TextIterator& it) const
+{
+	return _it != it._it;
+}
+
+
+inline void swap(TextIterator& it1, TextIterator& it2)
+{
+	it1.swap(it2);
+}
+
+
+inline TextIterator TextIterator::end() const
+{
+	return TextIterator(_end);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TextIterator_INCLUDED
diff --git a/Poco/Thread.h b/Poco/Thread.h
new file mode 100644
index 0000000..bfd6f03
--- /dev/null
+++ b/Poco/Thread.h
@@ -0,0 +1,367 @@
+//
+// Thread.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the Thread class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Thread_INCLUDED
+#define Foundation_Thread_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Event.h"
+#include "Poco/Mutex.h"
+
+
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#if defined(_WIN32_WCE)
+#include "Poco/Thread_WINCE.h"
+#else
+#include "Poco/Thread_WIN32.h"
+#endif
+#elif defined(POCO_VXWORKS)
+#include "Poco/Thread_VX.h"
+#else
+#include "Poco/Thread_POSIX.h"
+#endif
+
+
+namespace Poco {
+
+
+class Runnable;
+class ThreadLocalStorage;
+
+
+class Foundation_API Thread: private ThreadImpl
+	/// This class implements a platform-independent
+	/// wrapper to an operating system thread.
+	///
+	/// Every Thread object gets a unique (within
+	/// its process) numeric thread ID.
+	/// Furthermore, a thread can be assigned a name.
+	/// The name of a thread can be changed at any time.
+{
+public:	
+	typedef ThreadImpl::TIDImpl TID;
+
+	using ThreadImpl::Callable;
+
+	enum Priority
+		/// Thread priorities.
+	{
+		PRIO_LOWEST  = PRIO_LOWEST_IMPL, /// The lowest thread priority.
+		PRIO_LOW     = PRIO_LOW_IMPL,    /// A lower than normal thread priority.
+		PRIO_NORMAL  = PRIO_NORMAL_IMPL, /// The normal thread priority.
+		PRIO_HIGH    = PRIO_HIGH_IMPL,   /// A higher than normal thread priority.
+		PRIO_HIGHEST = PRIO_HIGHEST_IMPL /// The highest thread priority.
+	};
+	
+	enum Policy
+	{
+		POLICY_DEFAULT = POLICY_DEFAULT_IMPL
+	};
+
+	Thread();
+		/// Creates a thread. Call start() to start it.
+		
+	Thread(const std::string& name);
+		/// Creates a named thread. Call start() to start it.
+		
+	~Thread();
+		/// Destroys the thread.
+
+	int id() const;
+		/// Returns the unique thread ID of the thread.
+
+	TID tid() const;
+		/// Returns the native thread ID of the thread.
+
+	std::string name() const;
+		/// Returns the name of the thread.
+
+	std::string getName() const;
+		/// Returns the name of the thread.
+
+	void setName(const std::string& name);
+		/// Sets the name of the thread.
+
+	void setPriority(Priority prio);
+		/// Sets the thread's priority.
+		///
+		/// Some platform only allow changing a thread's priority
+		/// if the process has certain privileges.
+
+	Priority getPriority() const;
+		/// Returns the thread's priority.
+
+	void setOSPriority(int prio, int policy = POLICY_DEFAULT);
+		/// Sets the thread's priority, using an operating system specific
+		/// priority value. Use getMinOSPriority() and getMaxOSPriority() to
+		/// obtain mininum and maximum priority values. Additionally,
+		/// a scheduling policy can be specified. The policy is currently
+		/// only used on POSIX platforms where the values SCHED_OTHER (default),
+		/// SCHED_FIFO and SCHED_RR are supported.
+		
+	int getOSPriority() const;
+		/// Returns the thread's priority, expressed as an operating system
+		/// specific priority value.
+		///
+		/// May return 0 if the priority has not been explicitly set.
+		
+	static int getMinOSPriority(int policy = POLICY_DEFAULT);
+		/// Returns the minimum operating system-specific priority value,
+		/// which can be passed to setOSPriority() for the given policy.
+		
+	static int getMaxOSPriority(int policy = POLICY_DEFAULT);
+		/// Returns the maximum operating system-specific priority value,
+		/// which can be passed to setOSPriority() for the given policy.
+
+	void setStackSize(int size);
+		/// Sets the thread's stack size in bytes.
+		/// Setting the stack size to 0 will use the default stack size.
+		/// Typically, the real stack size is rounded up to the nearest
+		/// page size multiple.
+
+	int getStackSize() const;
+		/// Returns the thread's stack size in bytes.
+		/// If the default stack size is used, 0 is returned.
+
+	void start(Runnable& target);
+		/// Starts the thread with the given target.
+		///
+		/// Note that the given Runnable object must remain
+		/// valid during the entire lifetime of the thread, as
+		/// only a reference to it is stored internally.
+
+	void start(Callable target, void* pData = 0);
+		/// Starts the thread with the given target and parameter.
+
+	template <class Functor>
+	void startFunc(Functor fn)
+		/// Starts the thread with the given functor object or lambda.
+	{
+		startImpl(new FunctorRunnable<Functor>(fn));
+	}
+
+	void join();
+		/// Waits until the thread completes execution.	
+		/// If multiple threads try to join the same
+		/// thread, the result is undefined.
+		
+	void join(long milliseconds);
+		/// Waits for at most the given interval for the thread
+		/// to complete. Throws a TimeoutException if the thread
+		/// does not complete within the specified time interval.
+		
+	bool tryJoin(long milliseconds);
+		/// Waits for at most the given interval for the thread
+		/// to complete. Returns true if the thread has finished,
+		/// false otherwise.
+
+	bool isRunning() const;
+		/// Returns true if the thread is running.
+
+	static bool trySleep(long milliseconds);
+		/// Starts an interruptible sleep. When trySleep() is called,
+		/// the thread will remain suspended until:
+		///   - the timeout expires or 
+		///   - wakeUp() is called
+		/// 
+		/// Function returns true if sleep attempt was completed, false
+		/// if sleep was interrupted by a wakeUp() call.
+		/// A frequent scenario where trySleep()/wakeUp() pair of functions
+		/// is useful is with threads spending most of the time idle,
+		/// with periodic activity between the idle times; trying to sleep
+		/// (as opposed to sleeping) allows immediate ending of idle thread
+		/// from the outside.
+		/// 
+		/// The trySleep() and wakeUp() calls should be used with 
+		/// understanding that the suspended state is not a true sleep, 
+		/// but rather a state of waiting for an event, with timeout 
+		/// expiration. This makes order of calls significant; calling 
+		/// wakeUp() before calling trySleep() will prevent the next  
+		/// trySleep() call to actually suspend the thread (which, in 
+		/// some scenarios, may be desirable behavior).
+
+	void wakeUp();
+		/// Wakes up the thread which is in the state of interruptible
+		/// sleep. For threads that are not suspended, calling this
+		/// function has the effect of preventing the subsequent
+		/// trySleep() call to put thread in a suspended state.
+
+	static void sleep(long milliseconds);
+		/// Suspends the current thread for the specified
+		/// amount of time.
+
+	static void yield();
+		/// Yields cpu to other threads.
+
+	static Thread* current();
+		/// Returns the Thread object for the currently active thread.
+		/// If the current thread is the main thread, 0 is returned.
+
+ 	static TID currentTid();
+ 		/// Returns the native thread ID for the current thread.    
+
+protected:
+	ThreadLocalStorage& tls();
+		/// Returns a reference to the thread's local storage.
+
+	void clearTLS();
+		/// Clears the thread's local storage.
+
+	std::string makeName();
+		/// Creates a unique name for a thread.
+		
+	static int uniqueId();
+		/// Creates and returns a unique id for a thread.
+
+	template <class Functor>
+	class FunctorRunnable: public Runnable
+	{
+	public:
+		FunctorRunnable(const Functor& functor):
+			_functor(functor)
+		{
+		}
+
+		~FunctorRunnable()
+		{
+		}
+
+		void run()
+		{
+			_functor();
+		}
+	
+	private:
+		Functor _functor;
+	};
+
+private:
+	Thread(const Thread&);
+	Thread& operator = (const Thread&);
+
+	int                 _id;
+	std::string         _name;
+	ThreadLocalStorage* _pTLS;
+	Event               _event;
+	mutable FastMutex   _mutex;
+
+	friend class ThreadLocalStorage;
+	friend class PooledThread;
+};
+
+
+//
+// inlines
+//
+inline Thread::TID Thread::tid() const
+{
+	return tidImpl();
+}
+
+
+inline int Thread::id() const
+{
+	return _id;
+}
+
+
+inline std::string Thread::name() const
+{
+	FastMutex::ScopedLock lock(_mutex);
+	
+	return _name;
+}
+
+
+inline std::string Thread::getName() const
+{
+	FastMutex::ScopedLock lock(_mutex);
+	
+	return _name;
+}
+
+
+inline bool Thread::isRunning() const
+{
+	return isRunningImpl();
+}
+
+
+inline void Thread::sleep(long milliseconds)
+{
+	sleepImpl(milliseconds);
+}
+
+
+inline void Thread::yield()
+{
+	yieldImpl();
+}
+
+
+inline Thread* Thread::current()
+{
+	return static_cast<Thread*>(currentImpl());
+}
+
+
+inline void Thread::setOSPriority(int prio, int policy)
+{
+	setOSPriorityImpl(prio, policy);	
+}
+
+	
+inline int Thread::getOSPriority() const
+{
+	return getOSPriorityImpl();
+}
+
+	
+inline int Thread::getMinOSPriority(int policy)
+{
+	return ThreadImpl::getMinOSPriorityImpl(policy);
+}
+
+	
+inline int Thread::getMaxOSPriority(int policy)
+{
+	return ThreadImpl::getMaxOSPriorityImpl(policy);
+}
+
+
+inline void Thread::setStackSize(int size)
+{
+	setStackSizeImpl(size);
+}
+
+
+inline int Thread::getStackSize() const
+{
+	return getStackSizeImpl();
+}
+
+
+inline Thread::TID Thread::currentTid()
+{
+	return currentTidImpl();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Thread_INCLUDED
diff --git a/Poco/ThreadLocal.h b/Poco/ThreadLocal.h
new file mode 100644
index 0000000..cea17d5
--- /dev/null
+++ b/Poco/ThreadLocal.h
@@ -0,0 +1,157 @@
+//
+// ThreadLocal.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the ThreadLocal template and related classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ThreadLocal_INCLUDED
+#define Foundation_ThreadLocal_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Foundation_API TLSAbstractSlot
+	/// This is the base class for all objects
+	/// that the ThreadLocalStorage class manages.
+{
+public:
+	TLSAbstractSlot();
+	virtual ~TLSAbstractSlot();
+};
+
+
+template <class C>
+class TLSSlot: public TLSAbstractSlot
+	/// The Slot template wraps another class
+	/// so that it can be stored in a ThreadLocalStorage
+	/// object. This class is used internally, and you
+	/// must not create instances of it yourself.
+{
+public:
+	TLSSlot():
+		_value()
+	{
+	}
+	
+	~TLSSlot()
+	{
+	}
+	
+	C& value()
+	{
+		return _value;
+	}
+	
+private:
+	TLSSlot(const TLSSlot&);
+	TLSSlot& operator = (const TLSSlot&);
+
+	C _value;
+};
+
+
+class Foundation_API ThreadLocalStorage
+	/// This class manages the local storage for each thread.
+	/// Never use this class directly, always use the
+	/// ThreadLocal template for managing thread local storage.
+{
+public:
+	ThreadLocalStorage();
+		/// Creates the TLS.
+		
+	~ThreadLocalStorage();
+		/// Deletes the TLS.
+
+	TLSAbstractSlot*& get(const void* key);
+		/// Returns the slot for the given key.
+		
+	static ThreadLocalStorage& current();
+		/// Returns the TLS object for the current thread
+		/// (which may also be the main thread).
+		
+	static void clear();
+		/// Clears the current thread's TLS object.
+		/// Does nothing in the main thread.
+	
+private:
+	typedef std::map<const void*, TLSAbstractSlot*> TLSMap;
+	
+	TLSMap _map;
+
+	friend class Thread;
+};
+
+
+template <class C>
+class ThreadLocal
+	/// This template is used to declare type safe thread
+	/// local variables. It can basically be used like
+	/// a smart pointer class with the special feature
+	/// that it references a different object
+	/// in every thread. The underlying object will
+	/// be created when it is referenced for the first
+	/// time.
+	/// See the NestedDiagnosticContext class for an
+	/// example how to use this template.
+	/// Every thread only has access to its own
+	/// thread local data. There is no way for a thread
+	/// to access another thread's local data.
+{
+	typedef TLSSlot<C> Slot;
+
+public:
+	ThreadLocal()
+	{
+	}
+	
+	~ThreadLocal()
+	{
+	}
+	
+	C* operator -> ()
+	{
+		return &get();
+	}
+	
+	C& operator * ()
+		/// "Dereferences" the smart pointer and returns a reference
+		/// to the underlying data object. The reference can be used
+		/// to modify the object.
+	{
+		return get();
+	}
+
+	C& get()
+		/// Returns a reference to the underlying data object.
+		/// The reference can be used to modify the object.
+	{
+		TLSAbstractSlot*& p = ThreadLocalStorage::current().get(this);
+		if (!p) p = new Slot;
+		return static_cast<Slot*>(p)->value();
+	}
+	
+private:
+	ThreadLocal(const ThreadLocal&);
+	ThreadLocal& operator = (const ThreadLocal&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ThreadLocal_INCLUDED
diff --git a/Poco/ThreadPool.h b/Poco/ThreadPool.h
new file mode 100644
index 0000000..fa8bc6c
--- /dev/null
+++ b/Poco/ThreadPool.h
@@ -0,0 +1,208 @@
+//
+// ThreadPool.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ThreadPool
+//
+// Definition of the ThreadPool class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ThreadPool_INCLUDED
+#define Foundation_ThreadPool_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Thread.h"
+#include "Poco/Mutex.h"
+#include <vector>
+
+
+namespace Poco {
+
+
+class Runnable;
+class PooledThread;
+
+
+class Foundation_API ThreadPool
+	/// A thread pool always keeps a number of threads running, ready
+	/// to accept work.
+	/// Creating and starting a threads can impose a significant runtime
+	/// overhead to an application. A thread pool helps to improve
+	/// the performance of an application by reducing the number
+	/// of threads that have to be created (and destroyed again).
+	/// Threads in a thread pool are re-used once they become
+	/// available again.
+	/// The thread pool always keeps a minimum number of threads
+	/// running. If the demans for threads increases, additional
+	/// threads are created. Once the demand for threads sinks
+	/// again, no-longer used threads are stopped and removed
+	/// from the pool.
+{
+public:
+	ThreadPool(int minCapacity = 2,
+		int maxCapacity = 16,
+		int idleTime = 60,
+		int stackSize = POCO_THREAD_STACK_SIZE);
+		/// Creates a thread pool with minCapacity threads.
+		/// If required, up to maxCapacity threads are created
+		/// a NoThreadAvailableException exception is thrown.
+		/// If a thread is running idle for more than idleTime seconds,
+		/// and more than minCapacity threads are running, the thread
+		/// is killed. Threads are created with given stack size.
+
+	ThreadPool(const std::string& name,
+		int minCapacity = 2,
+		int maxCapacity = 16,
+		int idleTime = 60,
+		int stackSize = POCO_THREAD_STACK_SIZE);
+		/// Creates a thread pool with the given name and minCapacity threads.
+		/// If required, up to maxCapacity threads are created
+		/// a NoThreadAvailableException exception is thrown.
+		/// If a thread is running idle for more than idleTime seconds,
+		/// and more than minCapacity threads are running, the thread
+		/// is killed. Threads are created with given stack size.
+
+	~ThreadPool();
+		/// Currently running threads will remain active
+		/// until they complete. 
+	
+	void addCapacity(int n);
+		/// Increases (or decreases, if n is negative)
+		/// the maximum number of threads.
+
+	int capacity() const;
+		/// Returns the maximum capacity of threads.
+
+	void setStackSize(int stackSize);
+		/// Sets the stack size for threads.
+		/// New stack size applies only for newly created threads.
+
+	int getStackSize() const;
+		/// Returns the stack size used to create new threads.
+
+	int used() const;
+		/// Returns the number of currently used threads.
+
+	int allocated() const;
+		/// Returns the number of currently allocated threads.
+
+	int available() const;
+		/// Returns the number available threads.
+
+	void start(Runnable& target);
+		/// Obtains a thread and starts the target.
+		/// Throws a NoThreadAvailableException if no more
+		/// threads are available.
+
+	void start(Runnable& target, const std::string& name);
+		/// Obtains a thread and starts the target.
+		/// Assigns the given name to the thread.
+		/// Throws a NoThreadAvailableException if no more
+		/// threads are available.
+
+	void startWithPriority(Thread::Priority priority, Runnable& target);
+		/// Obtains a thread, adjusts the thread's priority, and starts the target.
+		/// Throws a NoThreadAvailableException if no more
+		/// threads are available.
+
+	void startWithPriority(Thread::Priority priority, Runnable& target, const std::string& name);
+		/// Obtains a thread, adjusts the thread's priority, and starts the target.
+		/// Assigns the given name to the thread.
+		/// Throws a NoThreadAvailableException if no more
+		/// threads are available.
+
+	void stopAll();
+		/// Stops all running threads and waits for their completion.
+		///
+		/// Will also delete all thread objects.
+		/// If used, this method should be the last action before
+		/// the thread pool is deleted.
+		///
+		/// Note: If a thread fails to stop within 10 seconds 
+		/// (due to a programming error, for example), the
+		/// underlying thread object will not be deleted and
+		/// this method will return anyway. This allows for a
+		/// more or less graceful shutdown in case of a misbehaving
+		/// thread.
+
+	void joinAll();
+		/// Waits for all threads to complete.
+		///
+		/// Note that this will not actually join() the underlying
+		/// thread, but rather wait for the thread's runnables
+		/// to finish.
+
+	void collect();
+		/// Stops and removes no longer used threads from the
+		/// thread pool. Can be called at various times in an
+		/// application's life time to help the thread pool
+		/// manage its threads. Calling this method is optional,
+		/// as the thread pool is also implicitly managed in
+		/// calls to start(), addCapacity() and joinAll().
+
+	const std::string& name() const;
+		/// Returns the name of the thread pool,
+		/// or an empty string if no name has been
+		/// specified in the constructor.
+
+	static ThreadPool& defaultPool();
+		/// Returns a reference to the default
+		/// thread pool.
+
+protected:
+	PooledThread* getThread();
+	PooledThread* createThread();
+
+	void housekeep();
+
+private:
+	ThreadPool(const ThreadPool& pool);
+	ThreadPool& operator = (const ThreadPool& pool);
+
+	typedef std::vector<PooledThread*> ThreadVec;
+
+	std::string _name;
+	int _minCapacity;
+	int _maxCapacity;
+	int _idleTime;
+	int _serial;
+	int _age;
+	int _stackSize;
+	ThreadVec _threads;
+	mutable FastMutex _mutex;
+};
+
+
+//
+// inlines
+//
+inline void ThreadPool::setStackSize(int stackSize)
+{
+	_stackSize = stackSize;
+}
+
+
+inline int ThreadPool::getStackSize() const
+{
+	return _stackSize;
+}
+
+
+inline const std::string& ThreadPool::name() const
+{
+	return _name;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ThreadPool_INCLUDED
diff --git a/Poco/ThreadTarget.h b/Poco/ThreadTarget.h
new file mode 100644
index 0000000..8845269
--- /dev/null
+++ b/Poco/ThreadTarget.h
@@ -0,0 +1,87 @@
+//
+// ThreadTarget.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  ThreadTarget
+//
+// Definition of the ThreadTarget class.
+//
+// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ThreadTarget_INCLUDED
+#define Foundation_ThreadTarget_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+
+
+namespace Poco {
+
+
+class Foundation_API ThreadTarget: public Runnable
+	/// This adapter simplifies using static member functions as well as 
+	/// standalone functions as targets for threads.
+	/// Note that it is possible to pass those entities directly to Thread::start().
+	/// This adapter is provided as a convenience for higher abstraction level
+	/// scenarios where Runnable abstract class is used.
+	///
+	/// For using a non-static member function as a thread target, please
+	/// see the RunnableAdapter class.
+	/// 
+	/// Usage:
+	///    class MyObject
+	///    {
+	///        static void doSomething() {}
+	///    };
+	///    ThreadTarget ra(&MyObject::doSomething);
+	///    Thread thr;
+	///    thr.start(ra);
+	///
+	/// or:
+	/// 
+	///    void doSomething() {}
+	/// 
+	///    ThreadTarget ra(doSomething);
+	///    Thread thr;
+	///    thr.start(ra);
+{
+public:
+	typedef void (*Callback)();
+	
+	ThreadTarget(Callback method);
+	
+	ThreadTarget(const ThreadTarget& te);
+
+	~ThreadTarget();
+
+	ThreadTarget& operator = (const ThreadTarget& te);
+
+	void run();
+	
+private:
+	ThreadTarget();
+
+	Callback _method;
+};
+
+
+//
+// inlines
+//
+inline void ThreadTarget::run()
+{
+	_method();
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ThreadTarget_INCLUDED
diff --git a/Poco/Thread_POSIX.h b/Poco/Thread_POSIX.h
new file mode 100644
index 0000000..6b70907
--- /dev/null
+++ b/Poco/Thread_POSIX.h
@@ -0,0 +1,198 @@
+//
+// Thread_POSIX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the ThreadImpl class for POSIX Threads.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Thread_POSIX_INCLUDED
+#define Foundation_Thread_POSIX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/SignalHandler.h"
+#include "Poco/Event.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/SharedPtr.h"
+#include <pthread.h>
+// must be limits.h (not <climits>) for PTHREAD_STACK_MIN on Solaris
+#include <limits.h>
+#if !defined(POCO_NO_SYS_SELECT_H)
+#include <sys/select.h>
+#endif
+#include <errno.h>
+#if defined(POCO_VXWORKS)
+#include <cstring>
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API ThreadImpl
+{
+public:
+	typedef pthread_t TIDImpl;
+	typedef void (*Callable)(void*);
+
+	enum Priority
+	{
+		PRIO_LOWEST_IMPL,
+		PRIO_LOW_IMPL,
+		PRIO_NORMAL_IMPL,
+		PRIO_HIGH_IMPL,
+		PRIO_HIGHEST_IMPL
+	};
+
+	enum Policy
+	{
+		POLICY_DEFAULT_IMPL = SCHED_OTHER
+	};
+	
+	ThreadImpl();
+	~ThreadImpl();
+
+	TIDImpl tidImpl() const;
+	void setPriorityImpl(int prio);
+	int getPriorityImpl() const;
+	void setOSPriorityImpl(int prio, int policy = SCHED_OTHER);
+	int getOSPriorityImpl() const;
+	static int getMinOSPriorityImpl(int policy);
+	static int getMaxOSPriorityImpl(int policy);
+	void setStackSizeImpl(int size);
+	int getStackSizeImpl() const;
+	void startImpl(SharedPtr<Runnable> pTarget);
+	void joinImpl();
+	bool joinImpl(long milliseconds);
+	bool isRunningImpl() const;
+	static void sleepImpl(long milliseconds);
+	static void yieldImpl();
+	static ThreadImpl* currentImpl();
+	static TIDImpl currentTidImpl();
+
+protected:
+	static void* runnableEntry(void* pThread);
+	static int mapPrio(int prio, int policy = SCHED_OTHER);
+	static int reverseMapPrio(int osPrio, int policy = SCHED_OTHER);
+
+private:
+	class CurrentThreadHolder
+	{
+	public:
+		CurrentThreadHolder()
+		{
+			if (pthread_key_create(&_key, NULL))
+				throw SystemException("cannot allocate thread context key");
+		}
+		~CurrentThreadHolder()
+		{
+			pthread_key_delete(_key);
+		}
+		ThreadImpl* get() const
+		{
+			return reinterpret_cast<ThreadImpl*>(pthread_getspecific(_key));
+		}
+		void set(ThreadImpl* pThread)
+		{
+			pthread_setspecific(_key, pThread);
+		}
+
+	private:
+		pthread_key_t _key;
+	};
+
+	struct ThreadData: public RefCountedObject
+	{
+		ThreadData():
+			thread(0),
+			prio(PRIO_NORMAL_IMPL),
+			osPrio(),
+			policy(SCHED_OTHER),
+			done(false),
+			stackSize(POCO_THREAD_STACK_SIZE),
+			started(false),
+			joined(false)
+		{
+		#if defined(POCO_VXWORKS)
+			// This workaround is for VxWorks 5.x where
+			// pthread_init() won't properly initialize the thread.
+			std::memset(&thread, 0, sizeof(thread));
+		#endif
+		}
+
+		SharedPtr<Runnable> pRunnableTarget;
+		pthread_t     thread;
+		int           prio;
+		int           osPrio;
+		int           policy;
+		Event         done;
+		std::size_t   stackSize;
+		bool          started;
+		bool          joined;
+	};
+
+	AutoPtr<ThreadData> _pData;
+
+	static CurrentThreadHolder _currentThreadHolder;
+	
+#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
+	SignalHandler::JumpBufferVec _jumpBufferVec;
+	friend class SignalHandler;
+#endif
+};
+
+
+//
+// inlines
+//
+inline int ThreadImpl::getPriorityImpl() const
+{
+	return _pData->prio;
+}
+
+
+inline int ThreadImpl::getOSPriorityImpl() const
+{
+	return _pData->osPrio;
+}
+
+
+inline bool ThreadImpl::isRunningImpl() const
+{
+	return !_pData->pRunnableTarget.isNull();
+}
+
+
+inline void ThreadImpl::yieldImpl()
+{
+	sched_yield();
+}
+
+
+inline int ThreadImpl::getStackSizeImpl() const
+{
+	return static_cast<int>(_pData->stackSize);
+}
+
+
+inline ThreadImpl::TIDImpl ThreadImpl::tidImpl() const
+{
+	return _pData->thread;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Thread_POSIX_INCLUDED
diff --git a/Poco/Thread_VX.h b/Poco/Thread_VX.h
new file mode 100644
index 0000000..a6dad9d
--- /dev/null
+++ b/Poco/Thread_VX.h
@@ -0,0 +1,169 @@
+//
+// Thread_VX.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the ThreadImpl class for VxWorks tasks.
+//
+// Copyright (c) 2004-2011, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Thread_VX_INCLUDED
+#define Foundation_Thread_VX_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/SignalHandler.h"
+#include "Poco/Event.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <taskLib.h>
+#include <taskVarLib.h>
+
+
+namespace Poco {
+
+
+class Foundation_API ThreadImpl
+{
+public:	
+	typedef int TIDImpl;
+	typedef void (*Callable)(void*);
+
+	enum Priority
+	{
+		PRIO_LOWEST_IMPL,
+		PRIO_LOW_IMPL,
+		PRIO_NORMAL_IMPL,
+		PRIO_HIGH_IMPL,
+		PRIO_HIGHEST_IMPL
+	};
+
+	enum Policy
+	{
+		POLICY_DEFAULT_IMPL = 0
+	};
+
+	enum
+	{
+		DEFAULT_THREAD_STACK_SIZE = 65536
+	};
+
+	struct CallbackData: public RefCountedObject
+	{
+		CallbackData(): callback(0), pData(0)
+		{
+		}
+
+		Callable  callback;
+		void*     pData; 
+	};
+
+	ThreadImpl();
+	~ThreadImpl();
+
+	TIDImpl tidImpl() const;
+	void setPriorityImpl(int prio);
+	int getPriorityImpl() const;
+	void setOSPriorityImpl(int prio, int policy = 0);
+	int getOSPriorityImpl() const;
+	static int getMinOSPriorityImpl(int policy);
+	static int getMaxOSPriorityImpl(int policy);
+	void setStackSizeImpl(int size);
+	int getStackSizeImpl() const;
+	void startImpl(Runnable& target);
+	void startImpl(Callable target, void* pData = 0);
+
+	void joinImpl();
+	bool joinImpl(long milliseconds);
+	bool isRunningImpl() const;
+	static void sleepImpl(long milliseconds);
+	static void yieldImpl();
+	static ThreadImpl* currentImpl();
+	static TIDImpl currentTidImpl();
+
+protected:
+	static void runnableEntry(void* pThread, int, int, int, int, int, int, int, int, int);
+	static void callableEntry(void* pThread, int, int, int, int, int, int, int, int, int);
+	static int mapPrio(int prio);
+	static int reverseMapPrio(int osPrio);
+
+	struct ThreadData: public RefCountedObject
+	{
+		ThreadData():
+			pRunnableTarget(0),
+			pCallbackTarget(0),
+			task(0),
+			prio(PRIO_NORMAL_IMPL),
+			osPrio(127),
+			done(false),
+			stackSize(POCO_THREAD_STACK_SIZE)
+		{
+		}
+
+		Runnable* pRunnableTarget;
+		AutoPtr<CallbackData> pCallbackTarget;
+		int       task;
+		int       prio;
+		int       osPrio;
+		Event     done;
+		int       stackSize;
+	};
+
+private:
+	AutoPtr<ThreadData> _pData;
+	static ThreadImpl* _pCurrent;
+};
+
+
+//
+// inlines
+//
+inline int ThreadImpl::getPriorityImpl() const
+{
+	return _pData->prio;
+}
+
+
+inline int ThreadImpl::getOSPriorityImpl() const
+{
+	return _pData->osPrio;
+}
+
+
+inline bool ThreadImpl::isRunningImpl() const
+{
+	return _pData->pRunnableTarget != 0 ||
+		(_pData->pCallbackTarget.get() != 0 && _pData->pCallbackTarget->callback != 0);
+}
+
+
+inline void ThreadImpl::yieldImpl()
+{
+	taskDelay(0);
+}
+
+
+inline int ThreadImpl::getStackSizeImpl() const
+{
+	return _pData->stackSize;
+}
+
+
+inline ThreadImpl::TIDImpl ThreadImpl::tidImpl() const
+{
+	return _pData->task;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Thread_VX_INCLUDED
diff --git a/Poco/Thread_WIN32.h b/Poco/Thread_WIN32.h
new file mode 100644
index 0000000..194b0a3
--- /dev/null
+++ b/Poco/Thread_WIN32.h
@@ -0,0 +1,183 @@
+//
+// Thread_WIN32.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the ThreadImpl class for WIN32.
+//
+// Copyright (c) 2004-2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Thread_WIN32_INCLUDED
+#define Foundation_Thread_WIN32_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API ThreadImpl
+{
+public:	
+	typedef DWORD TIDImpl;
+	typedef void (*Callable)(void*);
+
+#if defined(_DLL)
+	typedef DWORD (WINAPI *Entry)(LPVOID);
+#else
+	typedef unsigned (__stdcall *Entry)(void*);
+#endif
+
+	enum Priority
+	{
+		PRIO_LOWEST_IMPL  = THREAD_PRIORITY_LOWEST,
+		PRIO_LOW_IMPL     = THREAD_PRIORITY_BELOW_NORMAL,
+		PRIO_NORMAL_IMPL  = THREAD_PRIORITY_NORMAL,
+		PRIO_HIGH_IMPL    = THREAD_PRIORITY_ABOVE_NORMAL,
+		PRIO_HIGHEST_IMPL = THREAD_PRIORITY_HIGHEST
+	};
+
+	enum Policy
+	{
+		POLICY_DEFAULT_IMPL = 0
+	};
+
+	ThreadImpl();				
+	~ThreadImpl();
+
+	TIDImpl tidImpl() const;
+	void setPriorityImpl(int prio);
+	int getPriorityImpl() const;
+	void setOSPriorityImpl(int prio, int policy = 0);
+	int getOSPriorityImpl() const;
+	static int getMinOSPriorityImpl(int policy);
+	static int getMaxOSPriorityImpl(int policy);
+	void setStackSizeImpl(int size);
+	int getStackSizeImpl() const;
+	void startImpl(SharedPtr<Runnable> pTarget);
+	void joinImpl();
+	bool joinImpl(long milliseconds);
+	bool isRunningImpl() const;
+	static void sleepImpl(long milliseconds);
+	static void yieldImpl();
+	static ThreadImpl* currentImpl();
+	static TIDImpl currentTidImpl();
+    
+protected:
+#if defined(_DLL)
+	static DWORD WINAPI runnableEntry(LPVOID pThread);
+#else
+	static unsigned __stdcall runnableEntry(void* pThread);
+#endif
+
+	void createImpl(Entry ent, void* pData);
+	void threadCleanup();
+
+private:
+	class CurrentThreadHolder
+	{
+	public:
+		CurrentThreadHolder(): _slot(TlsAlloc())
+		{
+			if (_slot == TLS_OUT_OF_INDEXES)
+				throw SystemException("cannot allocate thread context key");
+		}
+		~CurrentThreadHolder()
+		{
+			TlsFree(_slot);
+		}
+		ThreadImpl* get() const
+		{
+			return reinterpret_cast<ThreadImpl*>(TlsGetValue(_slot));
+		}
+		void set(ThreadImpl* pThread)
+		{
+			TlsSetValue(_slot, pThread);
+		}
+	
+	private:
+		DWORD _slot;
+	};
+
+	SharedPtr<Runnable> _pRunnableTarget;
+	HANDLE _thread;
+	DWORD _threadId;
+	int _prio;
+	int _stackSize;
+
+	static CurrentThreadHolder _currentThreadHolder;
+};
+
+
+//
+// inlines
+//
+inline int ThreadImpl::getPriorityImpl() const
+{
+	return _prio;
+}
+
+
+inline int ThreadImpl::getOSPriorityImpl() const
+{
+	return _prio;
+}
+
+
+inline int ThreadImpl::getMinOSPriorityImpl(int /* policy */)
+{
+	return PRIO_LOWEST_IMPL;
+}
+
+
+inline int ThreadImpl::getMaxOSPriorityImpl(int /* policy */)
+{
+	return PRIO_HIGHEST_IMPL;
+}
+
+
+inline void ThreadImpl::sleepImpl(long milliseconds)
+{
+	Sleep(DWORD(milliseconds));
+}
+
+
+inline void ThreadImpl::yieldImpl()
+{
+	Sleep(0);
+}
+
+
+inline void ThreadImpl::setStackSizeImpl(int size)
+{
+	_stackSize = size;
+}
+
+
+inline int ThreadImpl::getStackSizeImpl() const
+{
+	return _stackSize;
+}
+
+
+inline ThreadImpl::TIDImpl ThreadImpl::tidImpl() const
+{
+	return _threadId;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Thread_WIN32_INCLUDED
diff --git a/Poco/Thread_WINCE.h b/Poco/Thread_WINCE.h
new file mode 100644
index 0000000..29f08aa
--- /dev/null
+++ b/Poco/Thread_WINCE.h
@@ -0,0 +1,179 @@
+//
+// Thread_WINCE.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Thread
+//
+// Definition of the ThreadImpl class for WIN32.
+//
+// Copyright (c) 2004-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Thread_WINCE_INCLUDED
+#define Foundation_Thread_WINCE_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/UnWindows.h"
+
+
+#if !defined(TLS_OUT_OF_INDEXES) // Windows CE 5.x does not define this
+#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
+#endif
+
+
+namespace Poco {
+
+
+class Foundation_API ThreadImpl
+{
+public:	
+    typedef DWORD TIDImpl;
+	typedef void (*Callable)(void*);
+	typedef DWORD (WINAPI *Entry)(LPVOID);
+
+	enum Priority
+	{
+		PRIO_LOWEST_IMPL  = THREAD_PRIORITY_LOWEST,
+		PRIO_LOW_IMPL     = THREAD_PRIORITY_BELOW_NORMAL,
+		PRIO_NORMAL_IMPL  = THREAD_PRIORITY_NORMAL,
+		PRIO_HIGH_IMPL    = THREAD_PRIORITY_ABOVE_NORMAL,
+		PRIO_HIGHEST_IMPL = THREAD_PRIORITY_HIGHEST
+	};
+
+	enum Policy
+	{
+		POLICY_DEFAULT_IMPL = 0
+	};
+
+	ThreadImpl();				
+	~ThreadImpl();
+
+	TIDImpl tidImpl() const;
+	void setPriorityImpl(int prio);
+	int getPriorityImpl() const;
+	void setOSPriorityImpl(int prio, int policy = 0);
+	int getOSPriorityImpl() const;
+	static int getMinOSPriorityImpl(int policy);
+	static int getMaxOSPriorityImpl(int policy);
+	void setStackSizeImpl(int size);
+	int getStackSizeImpl() const;
+	void startImpl(SharedPtr<Runnable> pTarget);
+	void joinImpl();
+	bool joinImpl(long milliseconds);
+	bool isRunningImpl() const;
+	static void sleepImpl(long milliseconds);
+	static void yieldImpl();
+	static ThreadImpl* currentImpl();
+	static TIDImpl currentTidImpl();
+
+protected:
+	static DWORD WINAPI runnableEntry(LPVOID pThread);
+
+	void createImpl(Entry ent, void* pData);
+	void threadCleanup();
+
+private:
+	class CurrentThreadHolder
+	{
+	public:
+		CurrentThreadHolder(): _slot(TlsAlloc())
+		{
+			if (_slot == TLS_OUT_OF_INDEXES)
+				throw SystemException("cannot allocate thread context key");
+		}
+		~CurrentThreadHolder()
+		{
+			TlsFree(_slot);
+		}
+		ThreadImpl* get() const
+		{
+			return reinterpret_cast<ThreadImpl*>(TlsGetValue(_slot));
+		}
+		void set(ThreadImpl* pThread)
+		{
+			TlsSetValue(_slot, pThread);
+		}
+	
+	private:
+		DWORD _slot;
+	};
+
+	SharedPtr<Runnable> _pRunnableTarget;
+	HANDLE       _thread;
+	DWORD        _threadId;
+	int          _prio;
+	int          _stackSize;
+
+	static CurrentThreadHolder _currentThreadHolder;
+};
+
+
+//
+// inlines
+//
+inline int ThreadImpl::getPriorityImpl() const
+{
+	return _prio;
+}
+
+
+inline int ThreadImpl::getOSPriorityImpl() const
+{
+	return _prio;
+}
+
+
+inline int ThreadImpl::getMinOSPriorityImpl(int /* policy */)
+{
+	return PRIO_LOWEST_IMPL;
+}
+
+
+inline int ThreadImpl::getMaxOSPriorityImpl(int /* policy */)
+{
+	return PRIO_HIGHEST_IMPL;
+}
+
+
+inline void ThreadImpl::sleepImpl(long milliseconds)
+{
+	Sleep(DWORD(milliseconds));
+}
+
+
+inline void ThreadImpl::yieldImpl()
+{
+	Sleep(0);
+}
+
+
+inline void ThreadImpl::setStackSizeImpl(int size)
+{
+	_stackSize = size;
+}
+
+
+inline int ThreadImpl::getStackSizeImpl() const
+{
+	return _stackSize;
+}
+
+
+inline ThreadImpl::TIDImpl ThreadImpl::tidImpl() const
+{
+	return _threadId;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Thread_WINCE_INCLUDED
diff --git a/Poco/TimedNotificationQueue.h b/Poco/TimedNotificationQueue.h
new file mode 100644
index 0000000..841ace6
--- /dev/null
+++ b/Poco/TimedNotificationQueue.h
@@ -0,0 +1,143 @@
+//
+// TimedNotificationQueue.h
+//
+// Library: Foundation
+// Package: Notifications
+// Module:  TimedNotificationQueue
+//
+// Definition of the TimedNotificationQueue class.
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TimedNotificationQueue_INCLUDED
+#define Foundation_TimedNotificationQueue_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Notification.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Clock.h"
+#include <map>
+
+
+namespace Poco {
+
+
+class Foundation_API TimedNotificationQueue
+	/// A TimedNotificationQueue object provides a way to implement timed, asynchronous
+	/// notifications. This is especially useful for sending notifications
+	/// from one thread to another, for example from a background thread to 
+	/// the main (user interface) thread. 
+	///
+	/// The TimedNotificationQueue is quite similar to the NotificationQueue class.
+	/// The only difference to NotificationQueue is that each Notification is tagged
+	/// with a Timestamp. When inserting a Notification into the queue, the
+	/// Notification is inserted according to the given Timestamp, with 
+	/// lower Timestamp values being inserted before higher ones.
+	///
+	/// Notifications are dequeued in order of their timestamps.
+	///
+	/// TimedNotificationQueue has some restrictions regarding multithreaded use.
+	/// While multiple threads may enqueue notifications, only one thread at a
+	/// time may dequeue notifications from the queue.
+	///
+	/// If two threads try to dequeue a notification simultaneously, the results
+	/// are undefined.
+{
+public:
+	TimedNotificationQueue();
+		/// Creates the TimedNotificationQueue.
+
+	~TimedNotificationQueue();
+		/// Destroys the TimedNotificationQueue.
+
+	void enqueueNotification(Notification::Ptr pNotification, Timestamp timestamp);
+		/// Enqueues the given notification by adding it to
+		/// the queue according to the given timestamp.
+		/// Lower timestamp values are inserted before higher ones.
+		/// The queue takes ownership of the notification, thus
+		/// a call like
+		///     notificationQueue.enqueueNotification(new MyNotification, someTime);
+		/// does not result in a memory leak.
+		///
+		/// The Timestamp is converted to an equivalent Clock value.
+
+	void enqueueNotification(Notification::Ptr pNotification, Clock clock);
+		/// Enqueues the given notification by adding it to
+		/// the queue according to the given clock value.
+		/// Lower clock values are inserted before higher ones.
+		/// The queue takes ownership of the notification, thus
+		/// a call like
+		///     notificationQueue.enqueueNotification(new MyNotification, someTime);
+		/// does not result in a memory leak.
+
+	Notification* dequeueNotification();
+		/// Dequeues the next pending notification with a timestamp
+		/// less than or equal to the current time.
+		/// Returns 0 (null) if no notification is available.
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+		
+	Notification* waitDequeueNotification();
+		/// Dequeues the next pending notification.
+		/// If no notification is available, waits for a notification
+		/// to be enqueued. 
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	Notification* waitDequeueNotification(long milliseconds);
+		/// Dequeues the next pending notification.
+		/// If no notification is available, waits for a notification
+		/// to be enqueued up to the specified time.
+		/// Returns 0 (null) if no notification is available.
+		/// The caller gains ownership of the notification and
+		/// is expected to release it when done with it.
+		///
+		/// It is highly recommended that the result is immediately
+		/// assigned to a Notification::Ptr, to avoid potential
+		/// memory management issues.
+
+	bool empty() const;
+		/// Returns true iff the queue is empty.
+		
+	int size() const;
+		/// Returns the number of notifications in the queue.
+
+	void clear();
+		/// Removes all notifications from the queue.
+		///
+		/// Calling clear() while another thread executes one of
+		/// the dequeue member functions will result in undefined
+		/// behavior.
+
+protected:
+	typedef std::multimap<Clock, Notification::Ptr> NfQueue;
+	Notification::Ptr dequeueOne(NfQueue::iterator& it);
+	bool wait(Clock::ClockDiff interval);
+	
+private:
+	NfQueue _nfQueue;
+	Event   _nfAvailable;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TimedNotificationQueue_INCLUDED
diff --git a/Poco/Timer.h b/Poco/Timer.h
new file mode 100644
index 0000000..d9f7fc2
--- /dev/null
+++ b/Poco/Timer.h
@@ -0,0 +1,229 @@
+//
+// Timer.h
+//
+// Library: Foundation
+// Package: Threading
+// Module:  Timer
+//
+// Definition of the Timer and related classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Timer_INCLUDED
+#define Foundation_Timer_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Runnable.h"
+#include "Poco/Mutex.h"
+#include "Poco/Event.h"
+#include "Poco/Thread.h"
+#include "Poco/Clock.h"
+
+
+namespace Poco {
+
+
+class AbstractTimerCallback;
+class ThreadPool;
+
+
+class Foundation_API Timer: protected Runnable
+	/// This class implements a thread-based timer.
+	/// A timer starts a thread that first waits for a given start interval.
+	/// Once that interval expires, the timer callback is called repeatedly
+	/// in the given periodic interval. If the interval is 0, the timer is only
+	/// called once.
+	/// The timer callback method can stop the timer by setting the 
+	/// timer's periodic interval to 0.
+	///
+	/// The timer callback runs in its own thread, so multithreading
+	/// issues (proper synchronization) have to be considered when writing 
+	/// the callback method.
+	///
+	/// The exact interval at which the callback is called depends on many 
+	/// factors like operating system, CPU performance and system load and
+	/// may differ from the specified interval.
+	///
+	/// The time needed to execute the timer callback is not included
+	/// in the interval between invocations. For example, if the interval
+	/// is 500 milliseconds, and the callback needs 400 milliseconds to
+	/// execute, the callback function is nevertheless called every 500
+	/// milliseconds. If the callback takes longer to execute than the
+	/// interval, the callback function will not be called until the next
+	/// proper interval. The number of skipped invocations since the last
+	/// invocation will be recorded and can be obtained by the callback
+	/// by calling skipped().
+	///
+	/// The timer thread is taken from a thread pool, so
+	/// there is a limit to the number of available concurrent timers.
+{
+public:
+	Timer(long startInterval = 0, long periodicInterval = 0);
+		/// Creates a new timer object. StartInterval and periodicInterval
+		/// are given in milliseconds. If a periodicInterval of zero is 
+		/// specified, the callback will only be called once, after the
+		/// startInterval expires.
+		/// To start the timer, call the Start() method.
+
+	virtual ~Timer();
+		/// Stops and destroys the timer.
+
+	void start(const AbstractTimerCallback& method);
+		/// Starts the timer.
+		/// Create the TimerCallback as follows:
+		///     TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
+		///     timer.start(callback);
+		///
+		/// The timer thread is taken from the global default thread pool.
+
+	void start(const AbstractTimerCallback& method, Thread::Priority priority);
+		/// Starts the timer in a thread with the given priority.
+		/// Create the TimerCallback as follows:
+		///     TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
+		///     timer.start(callback);
+		///
+		/// The timer thread is taken from the global default thread pool.
+
+	void start(const AbstractTimerCallback& method, ThreadPool& threadPool);
+		/// Starts the timer.
+		/// Create the TimerCallback as follows:
+		///     TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
+		///     timer.start(callback);
+
+	void start(const AbstractTimerCallback& method, Thread::Priority priority, ThreadPool& threadPool);
+		/// Starts the timer in a thread with the given priority.
+		/// Create the TimerCallback as follows:
+		///     TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
+		///     timer.start(callback);
+		
+	void stop();
+		/// Stops the timer. If the callback method is currently running
+		/// it will be allowed to finish first.
+		/// WARNING: Never call this method from within the callback method,
+		/// as a deadlock would result. To stop the timer from within the
+		/// callback method, call restart(0).
+
+	void restart();
+		/// Restarts the periodic interval. If the callback method is already running,
+		/// nothing will happen.
+
+	void restart(long milliseconds);
+		/// Sets a new periodic interval and restarts the timer.
+		/// An interval of 0 will stop the timer.
+
+	long getStartInterval() const;
+		/// Returns the start interval.
+
+	void setStartInterval(long milliseconds);
+		/// Sets the start interval. Will only be 
+		/// effective before start() is called.
+
+	long getPeriodicInterval() const;
+		/// Returns the periodic interval.
+
+	void setPeriodicInterval(long milliseconds);
+		/// Sets the periodic interval. If the timer is already running
+		/// the new interval will be effective when the current interval
+		/// expires.
+		
+	long skipped() const;
+		/// Returns the number of skipped invocations since the last invocation.
+		/// Skipped invocations happen if the timer callback function takes
+		/// longer to execute than the timer interval.
+
+protected:
+	void run();
+
+private:
+	volatile long _startInterval;
+	volatile long _periodicInterval;
+	Event         _wakeUp;
+	Event         _done;
+	long          _skipped;
+	AbstractTimerCallback* _pCallback;
+	Clock                  _nextInvocation;
+	mutable FastMutex      _mutex;
+	
+	Timer(const Timer&);
+	Timer& operator = (const Timer&);
+};
+
+
+class Foundation_API AbstractTimerCallback
+	/// This is the base class for all instantiations of
+	/// the TimerCallback template.
+{
+public:
+	AbstractTimerCallback();
+	AbstractTimerCallback(const AbstractTimerCallback& callback);
+	virtual ~AbstractTimerCallback();
+	
+	AbstractTimerCallback& operator = (const AbstractTimerCallback& callback);
+
+	virtual void invoke(Timer& timer) const = 0;
+	virtual AbstractTimerCallback* clone() const = 0;
+};
+
+
+template <class C> 
+class TimerCallback: public AbstractTimerCallback
+	/// This template class implements an adapter that sits between
+	/// a Timer and an object's method invoked by the timer.
+	/// It is quite similar in concept to the RunnableAdapter, but provides 
+	/// some Timer specific additional methods.
+	/// See the Timer class for information on how
+	/// to use this template class.
+{
+public:
+	typedef void (C::*Callback)(Timer&);
+
+	TimerCallback(C& object, Callback method): _pObject(&object), _method(method)
+	{
+	}
+
+	TimerCallback(const TimerCallback& callback): _pObject(callback._pObject), _method(callback._method)
+	{
+	}
+
+	~TimerCallback()
+	{
+	}
+
+	TimerCallback& operator = (const TimerCallback& callback)
+	{
+		if (&callback != this)
+		{
+			_pObject = callback._pObject;
+			_method  = callback._method;
+		}
+		return *this;
+	}
+
+	void invoke(Timer& timer) const
+	{
+		(_pObject->*_method)(timer);
+	}
+
+	AbstractTimerCallback* clone() const
+	{
+		return new TimerCallback(*this);
+	}
+
+private:
+	TimerCallback();
+
+	C*       _pObject;
+	Callback _method;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Timer_INCLUDED
diff --git a/Poco/Timespan.h b/Poco/Timespan.h
new file mode 100644
index 0000000..fcd742b
--- /dev/null
+++ b/Poco/Timespan.h
@@ -0,0 +1,303 @@
+//
+// Timespan.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  Timespan
+//
+// Definition of the Timespan class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Timespan_INCLUDED
+#define Foundation_Timespan_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Timespan
+	/// A class that represents time spans up to microsecond resolution.
+{
+public:
+	typedef Timestamp::TimeDiff TimeDiff;
+
+	Timespan();
+		/// Creates a zero Timespan.
+		
+	Timespan(TimeDiff microseconds);
+		/// Creates a Timespan.
+	
+	Timespan(long seconds, long microseconds);
+		/// Creates a Timespan. Useful for creating
+		/// a Timespan from a struct timeval.
+	
+	Timespan(int days, int hours, int minutes, int seconds, int microSeconds);
+		/// Creates a Timespan.
+
+	Timespan(const Timespan& timespan);
+		/// Creates a Timespan from another one.
+
+	~Timespan();
+		/// Destroys the Timespan.
+
+	Timespan& operator = (const Timespan& timespan);
+		/// Assignment operator.
+
+	Timespan& operator = (TimeDiff microseconds);
+		/// Assignment operator.
+		
+	Timespan& assign(int days, int hours, int minutes, int seconds, int microSeconds);
+		/// Assigns a new span.
+		
+	Timespan& assign(long seconds, long microseconds);
+		/// Assigns a new span. Useful for assigning
+		/// from a struct timeval.
+
+	void swap(Timespan& timespan);
+		/// Swaps the Timespan with another one.
+
+	bool operator == (const Timespan& ts) const;
+	bool operator != (const Timespan& ts) const;
+	bool operator >  (const Timespan& ts) const;
+	bool operator >= (const Timespan& ts) const;
+	bool operator <  (const Timespan& ts) const;
+	bool operator <= (const Timespan& ts) const;
+
+	bool operator == (TimeDiff microSeconds) const;
+	bool operator != (TimeDiff microSeconds) const;
+	bool operator >  (TimeDiff microSeconds) const;
+	bool operator >= (TimeDiff microSeconds) const;
+	bool operator <  (TimeDiff microSeconds) const;
+	bool operator <= (TimeDiff microSeconds) const;
+	
+	Timespan operator + (const Timespan& d) const;
+	Timespan operator - (const Timespan& d) const;
+	Timespan& operator += (const Timespan& d);
+	Timespan& operator -= (const Timespan& d);
+
+	Timespan operator + (TimeDiff microSeconds) const;
+	Timespan operator - (TimeDiff microSeconds) const;
+	Timespan& operator += (TimeDiff microSeconds);
+	Timespan& operator -= (TimeDiff microSeconds);
+
+	int days() const;
+		/// Returns the number of days.
+		
+	int hours() const;
+		/// Returns the number of hours (0 to 23).
+		
+	int totalHours() const;
+		/// Returns the total number of hours.
+		
+	int minutes() const;
+		/// Returns the number of minutes (0 to 59).
+		
+	int totalMinutes() const;
+		/// Returns the total number of minutes.
+		
+	int seconds() const;
+		/// Returns the number of seconds (0 to 59).
+		
+	int totalSeconds() const;
+		/// Returns the total number of seconds.
+		
+	int milliseconds() const;
+		/// Returns the number of milliseconds (0 to 999).
+		
+	TimeDiff totalMilliseconds() const;
+		/// Returns the total number of milliseconds.
+		
+	int microseconds() const;
+		/// Returns the fractions of a millisecond
+		/// in microseconds (0 to 999).
+		
+	int useconds() const;
+		/// Returns the fractions of a second
+		/// in microseconds (0 to 999999).
+		
+	TimeDiff totalMicroseconds() const;
+		/// Returns the total number of microseconds.
+
+	static const TimeDiff MILLISECONDS; /// The number of microseconds in a millisecond.
+	static const TimeDiff SECONDS;      /// The number of microseconds in a second.
+	static const TimeDiff MINUTES;      /// The number of microseconds in a minute.
+	static const TimeDiff HOURS;        /// The number of microseconds in a hour.
+	static const TimeDiff DAYS;         /// The number of microseconds in a day.
+
+private:
+	TimeDiff _span;
+};
+
+
+//
+// inlines
+//
+inline int Timespan::days() const
+{
+	return int(_span/DAYS);
+}
+
+
+inline int Timespan::hours() const
+{
+	return int((_span/HOURS) % 24);
+}
+
+	
+inline int Timespan::totalHours() const
+{
+	return int(_span/HOURS);
+}
+
+	
+inline int Timespan::minutes() const
+{
+	return int((_span/MINUTES) % 60);
+}
+
+	
+inline int Timespan::totalMinutes() const
+{
+	return int(_span/MINUTES);
+}
+
+	
+inline int Timespan::seconds() const
+{
+	return int((_span/SECONDS) % 60);
+}
+
+	
+inline int Timespan::totalSeconds() const
+{
+	return int(_span/SECONDS);
+}
+
+	
+inline int Timespan::milliseconds() const
+{
+	return int((_span/MILLISECONDS) % 1000);
+}
+
+	
+inline Timespan::TimeDiff Timespan::totalMilliseconds() const
+{
+	return _span/MILLISECONDS;
+}
+
+	
+inline int Timespan::microseconds() const
+{
+	return int(_span % 1000);
+}
+
+
+inline int Timespan::useconds() const
+{
+	return int(_span % 1000000);
+}
+
+	
+inline Timespan::TimeDiff Timespan::totalMicroseconds() const
+{
+	return _span;
+}
+
+
+inline bool Timespan::operator == (const Timespan& ts) const
+{
+	return _span == ts._span;
+}
+
+
+inline bool Timespan::operator != (const Timespan& ts) const
+{
+	return _span != ts._span;
+}
+
+
+inline bool Timespan::operator >  (const Timespan& ts) const
+{
+	return _span > ts._span;
+}
+
+
+inline bool Timespan::operator >= (const Timespan& ts) const
+{
+	return _span >= ts._span;
+}
+
+
+inline bool Timespan::operator <  (const Timespan& ts) const
+{
+	return _span < ts._span;
+}
+
+
+inline bool Timespan::operator <= (const Timespan& ts) const
+{
+	return _span <= ts._span;
+}
+
+
+inline bool Timespan::operator == (TimeDiff microSeconds) const
+{
+	return _span == microSeconds;
+}
+
+
+inline bool Timespan::operator != (TimeDiff microSeconds) const
+{
+	return _span != microSeconds;
+}
+
+
+inline bool Timespan::operator >  (TimeDiff microSeconds) const
+{
+	return _span > microSeconds;
+}
+
+
+inline bool Timespan::operator >= (TimeDiff microSeconds) const
+{
+	return _span >= microSeconds;
+}
+
+
+inline bool Timespan::operator <  (TimeDiff microSeconds) const
+{
+	return _span < microSeconds;
+}
+
+
+inline bool Timespan::operator <= (TimeDiff microSeconds) const
+{
+	return _span <= microSeconds;
+}
+
+
+inline void swap(Timespan& s1, Timespan& s2)
+{
+	s1.swap(s2);
+}
+
+
+inline Timespan::~Timespan()
+{
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Timespan_INCLUDED
diff --git a/Poco/Timestamp.h b/Poco/Timestamp.h
new file mode 100644
index 0000000..3fd5d97
--- /dev/null
+++ b/Poco/Timestamp.h
@@ -0,0 +1,277 @@
+//
+// Timestamp.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  Timestamp
+//
+// Definition of the Timestamp class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Timestamp_INCLUDED
+#define Foundation_Timestamp_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <ctime>
+
+
+namespace Poco {
+
+class Timespan;
+
+
+class Foundation_API Timestamp
+	/// A Timestamp stores a monotonic* time value
+	/// with (theoretical) microseconds resolution.
+	/// Timestamps can be compared with each other
+	/// and simple arithmetics are supported.
+	///
+	/// [*] Note that Timestamp values are only monotonic as
+	/// long as the systems's clock is monotonic as well
+	/// (and not, e.g. set back due to time synchronization
+	/// or other reasons).
+	///
+	/// Timestamps are UTC (Coordinated Universal Time)
+	/// based and thus independent of the timezone
+	/// in effect on the system.
+	///
+	/// The internal reference time is the Unix epoch, 
+	/// midnight, January 1, 1970.
+{
+public:
+	typedef Int64 TimeVal; 
+		/// Monotonic UTC time value in microsecond resolution,
+		/// with base time midnight, January 1, 1970.
+		
+	typedef Int64 UtcTimeVal; 
+		/// Monotonic UTC time value in 100 nanosecond resolution,
+		/// with base time midnight, October 15, 1582.
+		
+	typedef Int64 TimeDiff;
+		/// Difference between two TimeVal values in microseconds.
+
+	static const TimeVal TIMEVAL_MIN; /// Minimum timestamp value.
+	static const TimeVal TIMEVAL_MAX; /// Maximum timestamp value.
+
+	Timestamp();
+		/// Creates a timestamp with the current time.
+		
+	Timestamp(TimeVal tv);
+		/// Creates a timestamp from the given time value
+		/// (microseconds since midnight, January 1, 1970).
+		
+	Timestamp(const Timestamp& other);
+		/// Copy constructor.
+		
+	~Timestamp();
+		/// Destroys the timestamp
+		
+	Timestamp& operator = (const Timestamp& other);
+	Timestamp& operator = (TimeVal tv);
+	
+	void swap(Timestamp& timestamp);
+		/// Swaps the Timestamp with another one.
+	
+	void update();
+		/// Updates the Timestamp with the current time.
+
+	bool operator == (const Timestamp& ts) const;
+	bool operator != (const Timestamp& ts) const;
+	bool operator >  (const Timestamp& ts) const;
+	bool operator >= (const Timestamp& ts) const;
+	bool operator <  (const Timestamp& ts) const;
+	bool operator <= (const Timestamp& ts) const;
+	
+	Timestamp  operator +  (TimeDiff d) const;
+	Timestamp  operator +  (const Timespan& span) const;
+	Timestamp  operator -  (TimeDiff d) const;
+	Timestamp  operator -  (const Timespan& span) const;
+	TimeDiff   operator -  (const Timestamp& ts) const;
+	Timestamp& operator += (TimeDiff d);
+	Timestamp& operator += (const Timespan& span);
+	Timestamp& operator -= (TimeDiff d);
+	Timestamp& operator -= (const Timespan& span);
+	
+	std::time_t epochTime() const;
+		/// Returns the timestamp expressed in time_t.
+		/// time_t base time is midnight, January 1, 1970.
+		/// Resolution is one second.
+		
+	UtcTimeVal utcTime() const;
+		/// Returns the timestamp expressed in UTC-based
+		/// time. UTC base time is midnight, October 15, 1582.
+		/// Resolution is 100 nanoseconds.
+	
+	TimeVal epochMicroseconds() const;
+		/// Returns the timestamp expressed in microseconds
+		/// since the Unix epoch, midnight, January 1, 1970.
+	
+	TimeDiff elapsed() const;
+		/// Returns the time elapsed since the time denoted by
+		/// the timestamp. Equivalent to Timestamp() - *this.
+	
+	bool isElapsed(TimeDiff interval) const;
+		/// Returns true iff the given interval has passed
+		/// since the time denoted by the timestamp.
+
+	TimeVal raw() const;
+		/// Returns the raw time value.
+		///
+		/// Same as epochMicroseconds().
+	
+	static Timestamp fromEpochTime(std::time_t t);
+		/// Creates a timestamp from a std::time_t.
+		
+	static Timestamp fromUtcTime(UtcTimeVal val);
+		/// Creates a timestamp from a UTC time value
+		/// (100 nanosecond intervals since midnight,
+		/// October 15, 1582).
+		
+	static TimeDiff resolution();
+		/// Returns the resolution in units per second.
+		/// Since the timestamp has microsecond resolution,
+		/// the returned value is always 1000000.
+
+#if defined(_WIN32)
+	static Timestamp fromFileTimeNP(UInt32 fileTimeLow, UInt32 fileTimeHigh);
+	void toFileTimeNP(UInt32& fileTimeLow, UInt32& fileTimeHigh) const;
+#endif
+
+private:
+	TimeVal _ts;
+};
+
+
+//
+// inlines
+//
+inline bool Timestamp::operator == (const Timestamp& ts) const
+{
+	return _ts == ts._ts;
+}
+
+
+inline bool Timestamp::operator != (const Timestamp& ts) const
+{
+	return _ts != ts._ts;
+}
+
+
+inline bool Timestamp::operator >  (const Timestamp& ts) const
+{
+	return _ts > ts._ts;
+}
+
+
+inline bool Timestamp::operator >= (const Timestamp& ts) const
+{
+	return _ts >= ts._ts;
+}
+
+
+inline bool Timestamp::operator <  (const Timestamp& ts) const
+{
+	return _ts < ts._ts;
+}
+
+
+inline bool Timestamp::operator <= (const Timestamp& ts) const
+{
+	return _ts <= ts._ts;
+}
+
+
+inline Timestamp Timestamp::operator + (Timestamp::TimeDiff d) const
+{
+	return Timestamp(_ts + d);
+}
+
+
+inline Timestamp Timestamp::operator - (Timestamp::TimeDiff d) const
+{
+	return Timestamp(_ts - d);
+}
+
+
+inline Timestamp::TimeDiff Timestamp::operator - (const Timestamp& ts) const
+{
+	return _ts - ts._ts;
+}
+
+
+inline Timestamp& Timestamp::operator += (Timestamp::TimeDiff d)
+{
+	_ts += d;
+	return *this;
+}
+
+
+inline Timestamp& Timestamp::operator -= (Timestamp::TimeDiff d)
+{
+	_ts -= d;
+	return *this;
+}
+
+
+inline std::time_t Timestamp::epochTime() const
+{
+	return std::time_t(_ts/resolution());
+}
+
+
+inline Timestamp::UtcTimeVal Timestamp::utcTime() const
+{
+	return _ts*10 + (TimeDiff(0x01b21dd2) << 32) + 0x13814000;
+}
+
+
+inline Timestamp::TimeVal Timestamp::epochMicroseconds() const
+{
+	return _ts;
+}
+
+
+inline Timestamp::TimeDiff Timestamp::elapsed() const
+{
+	Timestamp now;
+	return now - *this;
+}
+
+
+inline bool Timestamp::isElapsed(Timestamp::TimeDiff interval) const
+{
+	Timestamp now;
+	Timestamp::TimeDiff diff = now - *this;
+	return diff >= interval;
+}
+
+
+inline Timestamp::TimeDiff Timestamp::resolution()
+{
+	return 1000000;
+}
+
+
+inline void swap(Timestamp& s1, Timestamp& s2)
+{
+	s1.swap(s2);
+}
+
+
+inline Timestamp::TimeVal Timestamp::raw() const
+{
+	return _ts;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Timestamp_INCLUDED
diff --git a/Poco/Timezone.h b/Poco/Timezone.h
new file mode 100644
index 0000000..c273f32
--- /dev/null
+++ b/Poco/Timezone.h
@@ -0,0 +1,67 @@
+//
+// Timezone.h
+//
+// Library: Foundation
+// Package: DateTime
+// Module:  Timezone
+//
+// Definition of the Timezone class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Timezone_INCLUDED
+#define Foundation_Timezone_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Timezone
+	/// This class provides information about the current timezone.
+{
+public:
+	static int utcOffset();
+		/// Returns the offset of local time to UTC, in seconds.
+		///     local time = UTC + utcOffset() + dst().
+		
+	static int dst();
+		/// Returns the daylight saving time offset in seconds if
+		/// daylight saving time is in use.
+		///     local time = UTC + utcOffset() + dst().
+	
+	static bool isDst(const Timestamp& timestamp);
+		/// Returns true if daylight saving time is in effect
+		/// for the given time. Depending on the operating system
+		/// platform this might only work reliably for certain
+		/// date ranges, as the C library's localtime() function
+		/// is used.
+		
+	static int tzd();
+		/// Returns the time zone differential for the current timezone.
+		/// The timezone differential is computed as utcOffset() + dst()
+		/// and is expressed in seconds.
+	
+	static std::string name();
+		/// Returns the timezone name currently in effect.
+		
+	static std::string standardName();
+		/// Returns the timezone name if not daylight saving time is in effect.
+		
+	static std::string dstName();
+		/// Returns the timezone name if daylight saving time is in effect.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Timezone_INCLUDED
diff --git a/Poco/Token.h b/Poco/Token.h
new file mode 100644
index 0000000..13540af
--- /dev/null
+++ b/Poco/Token.h
@@ -0,0 +1,172 @@
+//
+// Token.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamTokenizer
+//
+// Definition of the Token class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Token_INCLUDED
+#define Foundation_Token_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class Foundation_API Token
+	/// The base class for all token classes that can be
+	/// registered with the StreamTokenizer.
+{
+public:
+	enum Class
+	{
+		IDENTIFIER_TOKEN,
+		KEYWORD_TOKEN,
+		SEPARATOR_TOKEN,
+		OPERATOR_TOKEN,
+		STRING_LITERAL_TOKEN,
+		CHAR_LITERAL_TOKEN,
+		INTEGER_LITERAL_TOKEN,
+		LONG_INTEGER_LITERAL_TOKEN,
+		FLOAT_LITERAL_TOKEN,
+		DOUBLE_LITERAL_TOKEN,
+		COMMENT_TOKEN,
+		SPECIAL_COMMENT_TOKEN,
+		PREPROCESSOR_TOKEN,
+		WHITESPACE_TOKEN,
+		EOF_TOKEN,
+		INVALID_TOKEN,
+		USER_TOKEN
+	};
+	
+	Token();
+		/// Creates the Token.
+
+	virtual ~Token();
+		/// Destroys the Token.
+		
+	virtual bool start(char c, std::istream& istr);
+		/// Checks if the given character (and, optionally,
+		/// the next character in the input stream) start
+		/// a valid token. Returns true if so, false
+		/// otherwise.
+		///
+		/// The current read position in istr must not be
+		/// changed. In other words, only the peek() method
+		/// of istream may be used.
+		///
+		/// If the character starts the token, it should
+		/// be set as the token's value.
+
+	virtual void finish(std::istream& istr);
+		/// Builds the token by reading and appending 
+		/// the remaining characters from istr.
+		
+	virtual Class tokenClass() const;
+		/// Returns the kind of the token.
+	
+	const std::string& tokenString() const;
+		/// Returns the token's raw string.
+	
+	virtual std::string asString() const;
+		/// Returns a string representation of the token.
+	
+#if defined(POCO_HAVE_INT64)
+	virtual Int64 asInteger64() const;
+        /// Returns a 64-bit integer representation of the token.
+
+	virtual UInt64 asUnsignedInteger64() const;
+        /// Returns an unsigned 64-bit integer representation of the token.
+#endif
+
+	virtual int asInteger() const;
+		/// Returns an integer representation of the token.
+
+	virtual unsigned asUnsignedInteger() const;
+		/// Returns an unsigned integer representation of the token.
+
+	virtual double asFloat() const;
+		/// Returns a floating-point representation of the token.
+
+	virtual char asChar() const;
+		/// Returns a char representation of the token.
+
+	bool is(Class tokenClass) const;
+		/// Returns true iff the token has the given class.
+
+protected:
+	std::string _value;
+	
+private:
+	Token(const Token&);
+	Token& operator = (const Token&);
+};
+
+
+class Foundation_API InvalidToken: public Token
+	/// This token class is used for signalling that
+	/// an invalid character sequence has been encountered
+	/// in the input stream.
+{
+public:
+	InvalidToken();
+	~InvalidToken();
+	Class tokenClass() const;
+};
+
+
+class Foundation_API EOFToken: public Token
+	/// This token class is used to signal the
+	/// end of the input stream.
+{
+public:
+	EOFToken();
+	~EOFToken();
+	Class tokenClass() const;
+};
+
+
+class Foundation_API WhitespaceToken: public Token
+	/// This pseudo token class is used to eat
+	/// up whitespace in between real tokens.
+{
+public:
+	WhitespaceToken();
+	~WhitespaceToken();
+	Class tokenClass() const;
+	bool start(char c, std::istream& istr);
+	void finish(std::istream& istr);
+};
+
+
+//
+// inlines
+//
+inline const std::string& Token::tokenString() const
+{
+	return _value;
+}
+
+
+inline bool Token::is(Token::Class cls) const
+{
+	return tokenClass() == cls;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Token_INCLUDED
diff --git a/Poco/Tuple.h b/Poco/Tuple.h
new file mode 100644
index 0000000..2111bf8
--- /dev/null
+++ b/Poco/Tuple.h
@@ -0,0 +1,1747 @@
+//
+// Tuple.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Tuple
+//
+// Definition of the Tuple class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Tuple_INCLUDED
+#define Foundation_Tuple_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TypeList.h"
+
+
+namespace Poco {
+
+
+#if defined(_MSC_VER) 
+#define POCO_TYPEWRAPPER_DEFAULTVALUE(T) TypeWrapper<T>::TYPE()
+#else
+#define POCO_TYPEWRAPPER_DEFAULTVALUE(T) typename TypeWrapper<T>::TYPE()
+#endif
+
+
+template <class T0,
+	class T1 = NullTypeList,
+	class T2 = NullTypeList,
+	class T3 = NullTypeList,
+	class T4 = NullTypeList,
+	class T5 = NullTypeList,
+	class T6 = NullTypeList,
+	class T7 = NullTypeList,
+	class T8 = NullTypeList,
+	class T9 = NullTypeList,
+	class T10 = NullTypeList,
+	class T11 = NullTypeList,
+	class T12 = NullTypeList,
+	class T13 = NullTypeList,
+	class T14 = NullTypeList,
+	class T15 = NullTypeList,
+	class T16 = NullTypeList,
+	class T17 = NullTypeList,
+	class T18 = NullTypeList,
+	class T19 = NullTypeList>
+struct Tuple
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0,
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16),
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17),
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18),
+		typename TypeWrapper<T19>::CONSTTYPE& t19 = POCO_TYPEWRAPPER_DEFAULTVALUE(T19)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t10, typename TypeListType<T11,T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t11, typename TypeListType<T12,T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t12, typename TypeListType<T13,T14,T15,T16,T17,T18,T19>::HeadType
+			(t13, typename TypeListType<T14,T15,T16,T17,T18,T19>::HeadType
+			(t14, typename TypeListType<T15,T16,T17,T18,T19>::HeadType
+			(t15, typename TypeListType<T16,T17,T18,T19>::HeadType
+			(t16, typename TypeListType<T17,T18,T19>::HeadType
+			(t17, typename TypeListType<T18,T19>::HeadType
+			(t18, typename TypeListType<T19>::HeadType
+			(t19, NullTypeList()))))))))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15,
+	class T16,
+	class T17,
+	class T18>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16),
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17),
+		typename TypeWrapper<T18>::CONSTTYPE& t18 = POCO_TYPEWRAPPER_DEFAULTVALUE(T18)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t10, typename TypeListType<T11,T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t11, typename TypeListType<T12,T13,T14,T15,T16,T17,T18>::HeadType
+			(t12, typename TypeListType<T13,T14,T15,T16,T17,T18>::HeadType
+			(t13, typename TypeListType<T14,T15,T16,T17,T18>::HeadType
+			(t14, typename TypeListType<T15,T16,T17,T18>::HeadType
+			(t15, typename TypeListType<T16,T17,T18>::HeadType
+			(t16, typename TypeListType<T17,T18>::HeadType
+			(t17, typename TypeListType<T18>::HeadType
+			(t18, NullTypeList())))))))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15,
+	class T16,
+	class T17>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16),
+		typename TypeWrapper<T17>::CONSTTYPE& t17 = POCO_TYPEWRAPPER_DEFAULTVALUE(T17)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t10, typename TypeListType<T11,T12,T13,T14,T15,T16,T17>::HeadType
+			(t11, typename TypeListType<T12,T13,T14,T15,T16,T17>::HeadType
+			(t12, typename TypeListType<T13,T14,T15,T16,T17>::HeadType
+			(t13, typename TypeListType<T14,T15,T16,T17>::HeadType
+			(t14, typename TypeListType<T15,T16,T17>::HeadType
+			(t15, typename TypeListType<T16,T17>::HeadType
+			(t16, typename TypeListType<T17>::HeadType
+			(t17, NullTypeList()))))))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15,
+	class T16>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15),
+		typename TypeWrapper<T16>::CONSTTYPE& t16 = POCO_TYPEWRAPPER_DEFAULTVALUE(T16)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13,T14,T15,T16>::HeadType
+			(t10, typename TypeListType<T11,T12,T13,T14,T15,T16>::HeadType
+			(t11, typename TypeListType<T12,T13,T14,T15,T16>::HeadType
+			(t12, typename TypeListType<T13,T14,T15,T16>::HeadType
+			(t13, typename TypeListType<T14,T15,T16>::HeadType
+			(t14, typename TypeListType<T15,T16>::HeadType
+			(t15, typename TypeListType<T16>::HeadType
+			(t16, NullTypeList())))))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14,
+	class T15>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14),
+		typename TypeWrapper<T15>::CONSTTYPE& t15 = POCO_TYPEWRAPPER_DEFAULTVALUE(T15)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13,T14,T15>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13,T14,T15>::HeadType
+			(t10, typename TypeListType<T11,T12,T13,T14,T15>::HeadType
+			(t11, typename TypeListType<T12,T13,T14,T15>::HeadType
+			(t12, typename TypeListType<T13,T14,T15>::HeadType
+			(t13, typename TypeListType<T14,T15>::HeadType
+			(t14, typename TypeListType<T15>::HeadType
+			(t15, NullTypeList()))))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13,
+	class T14>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13),
+		typename TypeWrapper<T14>::CONSTTYPE& t14 = POCO_TYPEWRAPPER_DEFAULTVALUE(T14)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13,T14>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13,T14>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13,T14>::HeadType
+			(t10, typename TypeListType<T11,T12,T13,T14>::HeadType
+			(t11, typename TypeListType<T12,T13,T14>::HeadType
+			(t12, typename TypeListType<T13,T14>::HeadType
+			(t13, typename TypeListType<T14>::HeadType
+			(t14, NullTypeList())))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12,
+	class T13>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12),
+		typename TypeWrapper<T13>::CONSTTYPE& t13 = POCO_TYPEWRAPPER_DEFAULTVALUE(T13)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12,T13>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12,T13>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12,T13>::HeadType
+			(t9, typename TypeListType<T10,T11,T12,T13>::HeadType
+			(t10, typename TypeListType<T11,T12,T13>::HeadType
+			(t11, typename TypeListType<T12,T13>::HeadType
+			(t12, typename TypeListType<T13>::HeadType
+			(t13, NullTypeList()))))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11,
+	class T12>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11),
+		typename TypeWrapper<T12>::CONSTTYPE& t12 = POCO_TYPEWRAPPER_DEFAULTVALUE(T12)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11,T12>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11,T12>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11,T12>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11,T12>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11,T12>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11,T12>::HeadType
+			(t8, typename TypeListType<T9,T10,T11,T12>::HeadType
+			(t9, typename TypeListType<T10,T11,T12>::HeadType
+			(t10, typename TypeListType<T11,T12>::HeadType
+			(t11, typename TypeListType<T12>::HeadType
+			(t12, NullTypeList())))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10,
+	class T11>
+struct Tuple<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10),
+		typename TypeWrapper<T11>::CONSTTYPE& t11 = POCO_TYPEWRAPPER_DEFAULTVALUE(T11)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10,T11>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10,T11>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10,T11>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10,T11>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10,T11>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10,T11>::HeadType
+			(t7, typename TypeListType<T8,T9,T10,T11>::HeadType
+			(t8, typename TypeListType<T9,T10,T11>::HeadType
+			(t9, typename TypeListType<T10,T11>::HeadType
+			(t10, typename TypeListType<T11>::HeadType
+			(t11, NullTypeList()))))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9,
+	class T10>
+struct Tuple<T0, T1,T2,T3,T4,T5,T6,T7,T8,T9,T10, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9),
+		typename TypeWrapper<T10>::CONSTTYPE& t10 = POCO_TYPEWRAPPER_DEFAULTVALUE(T10)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9,T10>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9,T10>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9,T10>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9,T10>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9,T10>::HeadType
+			(t6, typename TypeListType<T7,T8,T9,T10>::HeadType
+			(t7, typename TypeListType<T8,T9,T10>::HeadType
+			(t8, typename TypeListType<T9,T10>::HeadType
+			(t9, typename TypeListType<T10>::HeadType
+			(t10, NullTypeList())))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8,
+	class T9>
+struct Tuple<T0, T1,T2,T3,T4,T5,T6,T7,T8,T9, NullTypeList>
+{
+	typedef typename TypeListType<T0, T1,T2,T3,T4,T5,T6,T7,T8,T9>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8),
+		typename TypeWrapper<T9>::CONSTTYPE& t9 = POCO_TYPEWRAPPER_DEFAULTVALUE(T9)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8,T9>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8,T9>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8,T9>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8,T9>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8,T9>::HeadType
+			(t5, typename TypeListType<T6,T7,T8,T9>::HeadType
+			(t6, typename TypeListType<T7,T8,T9>::HeadType
+			(t7, typename TypeListType<T8,T9>::HeadType
+			(t8, typename TypeListType<T9>::HeadType
+			(t9, NullTypeList()))))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7,
+	class T8>
+struct Tuple<T0, T1,T2,T3,T4,T5,T6,T7,T8, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7,T8>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7),
+		typename TypeWrapper<T8>::CONSTTYPE& t8 = POCO_TYPEWRAPPER_DEFAULTVALUE(T8)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7,T8>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7,T8>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7,T8>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7,T8>::HeadType
+			(t4, typename TypeListType<T5,T6,T7,T8>::HeadType
+			(t5, typename TypeListType<T6,T7,T8>::HeadType
+			(t6, typename TypeListType<T7,T8>::HeadType
+			(t7, typename TypeListType<T8>::HeadType
+			(t8, NullTypeList())))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6,
+	class T7>
+struct Tuple<T0, T1,T2,T3,T4,T5,T6,T7, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6,T7>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6),
+		typename TypeWrapper<T7>::CONSTTYPE& t7 = POCO_TYPEWRAPPER_DEFAULTVALUE(T7)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6,T7>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6,T7>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6,T7>::HeadType
+			(t3, typename TypeListType<T4,T5,T6,T7>::HeadType
+			(t4, typename TypeListType<T5,T6,T7>::HeadType
+			(t5, typename TypeListType<T6,T7>::HeadType
+			(t6, typename TypeListType<T7>::HeadType
+			(t7, NullTypeList()))))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5,
+	class T6>
+struct Tuple<T0, T1,T2,T3,T4,T5,T6, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5,T6>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5),
+		typename TypeWrapper<T6>::CONSTTYPE& t6 = POCO_TYPEWRAPPER_DEFAULTVALUE(T6)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5,T6>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5,T6>::HeadType
+			(t2, typename TypeListType<T3,T4,T5,T6>::HeadType
+			(t3, typename TypeListType<T4,T5,T6>::HeadType
+			(t4, typename TypeListType<T5,T6>::HeadType
+			(t5, typename TypeListType<T6>::HeadType
+			(t6, NullTypeList())))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4,
+	class T5>
+struct Tuple<T0, T1,T2,T3,T4,T5, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4,T5>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4),
+		typename TypeWrapper<T5>::CONSTTYPE& t5 = POCO_TYPEWRAPPER_DEFAULTVALUE(T5)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4,T5>::HeadType
+			(t1, typename TypeListType<T2,T3,T4,T5>::HeadType
+			(t2, typename TypeListType<T3,T4,T5>::HeadType
+			(t3, typename TypeListType<T4,T5>::HeadType
+			(t4, typename TypeListType<T5>::HeadType
+			(t5, NullTypeList()))))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3,
+	class T4>
+struct Tuple<T0, T1,T2,T3,T4, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3,T4>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3),
+		typename TypeWrapper<T4>::CONSTTYPE& t4 = POCO_TYPEWRAPPER_DEFAULTVALUE(T4)):
+		_data(t0, typename TypeListType<T1,T2,T3,T4>::HeadType
+			(t1, typename TypeListType<T2,T3,T4>::HeadType
+			(t2, typename TypeListType<T3,T4>::HeadType
+			(t3, typename TypeListType<T4>::HeadType
+			(t4, NullTypeList())))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2,
+	class T3>
+struct Tuple<T0, T1,T2,T3, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2,T3>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2),
+		typename TypeWrapper<T3>::CONSTTYPE& t3 = POCO_TYPEWRAPPER_DEFAULTVALUE(T3)):
+		_data(t0, typename TypeListType<T1,T2,T3>::HeadType
+			(t1, typename TypeListType<T2,T3>::HeadType
+			(t2, typename TypeListType<T3>::HeadType
+			(t3, NullTypeList()))))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1,
+	class T2>
+struct Tuple<T0, T1,T2, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1,T2>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1),
+		typename TypeWrapper<T2>::CONSTTYPE& t2 = POCO_TYPEWRAPPER_DEFAULTVALUE(T2)):
+		_data(t0, typename TypeListType<T1,T2>::HeadType
+			(t1, typename TypeListType<T2>::HeadType
+			(t2, NullTypeList())))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0,
+	class T1>
+struct Tuple<T0, T1, NullTypeList>
+{
+	typedef typename TypeListType<T0,T1>::HeadType Type;
+
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0, 
+		typename TypeWrapper<T1>::CONSTTYPE& t1 = POCO_TYPEWRAPPER_DEFAULTVALUE(T1)):
+		_data(t0, typename TypeListType<T1>::HeadType(t1, NullTypeList()))
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+template <class T0>
+struct Tuple<T0, NullTypeList>
+{
+	typedef TypeList<T0, NullTypeList> Type;
+	
+	enum TupleLengthType
+	{
+		length = Type::length
+	};
+
+	Tuple():_data()
+	{
+	}
+
+	Tuple(typename TypeWrapper<T0>::CONSTTYPE& t0):
+		_data(t0, NullTypeList())
+	{
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::ConstHeadType& get() const
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	typename TypeGetter<N, Type>::HeadType& get()
+	{
+		return Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data);
+	}
+
+	template <int N>
+	void set(typename TypeGetter<N, Type>::ConstHeadType& val)
+	{
+		Getter<N>::template get<typename TypeGetter<N, Type>::HeadType, typename Type::HeadType, typename Type::TailType>(_data) = val;
+	}
+
+	bool operator == (const Tuple& other) const
+	{
+		return _data == other._data;
+	}
+
+	bool operator != (const Tuple& other) const
+	{
+		return !(_data == other._data);
+	}
+
+	bool operator < (const Tuple& other) const
+	{
+		return _data < other._data;
+	}
+
+private:
+	Type _data;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Tuple_INCLUDED
diff --git a/Poco/TypeList.h b/Poco/TypeList.h
new file mode 100644
index 0000000..352696f
--- /dev/null
+++ b/Poco/TypeList.h
@@ -0,0 +1,483 @@
+//
+// TypeList.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  TypeList
+//
+// Implementation of the TypeList template.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Portions extracted and adapted from
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_TypeList_INCLUDED
+#define Foundation_TypeList_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/MetaProgramming.h"
+
+
+namespace Poco {
+
+
+template <class Head, class Tail> 
+struct TypeList;
+
+
+struct NullTypeList
+{
+	enum
+	{
+		length = 0
+	};
+
+	bool operator == (const NullTypeList&) const
+	{
+		return true;
+	}
+
+	bool operator != (const NullTypeList&) const
+	{
+		return false;
+	}
+
+	bool operator < (const NullTypeList&) const
+	{
+		return false;
+	}
+};
+
+
+template <class Head, class Tail> 
+struct TypeList
+	/// Compile Time List of Types
+{
+	typedef Head HeadType;
+	typedef Tail TailType;
+	typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType;
+	typedef typename TypeWrapper<TailType>::CONSTTYPE ConstTailType;
+	enum
+	{
+		length = TailType::length+1
+	};
+
+	TypeList():head(), tail()
+	{
+	}
+
+	TypeList(ConstHeadType& h, ConstTailType& t):head(h), tail(t)
+	{
+	}
+
+	TypeList(const TypeList& tl): head(tl.head), tail(tl.tail)
+	{
+	}
+
+	TypeList& operator = (const TypeList& tl)
+	{
+		if (this != &tl)
+		{
+			head = tl.head;
+			tail = tl.tail;
+		}
+		return *this;
+	}
+
+	bool operator == (const TypeList& tl) const
+	{
+		return tl.head == head && tl.tail == tail;
+	}
+
+	bool operator != (const TypeList& tl) const
+	{
+		return !(*this == tl);
+	}
+
+	bool operator < (const TypeList& tl) const
+	{
+		if (head < tl.head)
+			return true;
+		else if (head == tl.head)
+			return tail < tl.tail;
+		return false;
+	}
+	
+	HeadType head;
+	TailType tail;
+};
+
+
+template <typename T0  = NullTypeList,
+	typename T1  = NullTypeList,
+	typename T2  = NullTypeList,
+	typename T3  = NullTypeList,
+	typename T4  = NullTypeList,
+	typename T5  = NullTypeList,
+	typename T6  = NullTypeList,
+	typename T7  = NullTypeList,
+	typename T8  = NullTypeList,
+	typename T9  = NullTypeList,
+	typename T10 = NullTypeList,
+	typename T11 = NullTypeList,
+	typename T12 = NullTypeList,
+	typename T13 = NullTypeList,
+	typename T14 = NullTypeList,
+	typename T15 = NullTypeList,
+	typename T16 = NullTypeList,
+	typename T17 = NullTypeList,
+	typename T18 = NullTypeList,
+	typename T19 = NullTypeList,
+	typename T20 = NullTypeList,
+	typename T21 = NullTypeList,
+	typename T22 = NullTypeList,
+	typename T23 = NullTypeList,
+	typename T24 = NullTypeList,
+	typename T25 = NullTypeList,
+	typename T26 = NullTypeList,
+	typename T27 = NullTypeList,
+	typename T28 = NullTypeList,
+	typename T29 = NullTypeList,
+	typename T30 = NullTypeList,
+	typename T31 = NullTypeList,
+	typename T32 = NullTypeList,
+	typename T33 = NullTypeList,
+	typename T34 = NullTypeList,
+	typename T35 = NullTypeList,
+	typename T36 = NullTypeList,
+	typename T37 = NullTypeList,
+	typename T38 = NullTypeList,
+	typename T39 = NullTypeList>
+struct TypeListType
+	/// TypeListType takes 1 - 40 typename arguments.
+	/// Usage:
+	///
+	/// TypeListType<T0, T1, ... , Tn>::HeadType typeList;
+	///
+	/// typeList is a TypeList of T0, T1, ... , Tn
+{
+private:
+	typedef typename
+		TypeListType<T1,T2, T3, T4, T5, T6, T7, T8, T9, T10,
+					T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,
+					T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,
+					T31,T32,T33,T34,T35,T36,T37,T38,T39>::HeadType TailType;
+
+public:
+	typedef TypeList<T0, TailType> HeadType;
+};
+
+
+template <>
+struct TypeListType<>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <int n> 
+struct Getter
+{
+	template <class Ret, class Head, class Tail>
+	inline static Ret& get(TypeList<Head, Tail>& val)
+	{
+		return Getter<n-1>::template get<Ret, typename Tail::HeadType, typename Tail::TailType>(val.tail);
+	}
+
+	template <class Ret, class Head, class Tail>
+	inline static const Ret& get(const TypeList<Head, Tail>& val)
+	{
+		return Getter<n-1>::template get<Ret, typename Tail::HeadType, typename Tail::TailType>(val.tail);
+	}
+};
+
+
+template <> 
+struct Getter<0>
+{
+	template <class Ret, class Head, class Tail>
+	inline static Ret& get(TypeList<Head, Tail>& val)
+	{
+		return val.head;
+	}
+
+	template <class Ret, class Head, class Tail>
+	inline static const Ret& get(const TypeList<Head, Tail>& val)
+	{
+		return val.head;
+	}
+};
+
+
+template <int N, class Head> 
+struct TypeGetter;
+
+
+template <int N, class Head, class Tail> 
+struct TypeGetter<N, TypeList<Head, Tail> >
+{
+	typedef typename TypeGetter<N-1, Tail>::HeadType HeadType;
+	typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType;
+};
+
+
+template <class Head, class Tail> 
+struct TypeGetter<0, TypeList<Head, Tail> >
+{
+	typedef typename TypeList<Head, Tail>::HeadType HeadType;
+	typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType;
+};
+
+
+template <class Head, class T>
+struct TypeLocator;
+	/// TypeLocator returns the first occurrence of the type T in Head
+	/// or -1 if the type is not found.
+	///
+	/// Usage example:
+	///
+	/// TypeLocator<Head, int>::HeadType TypeLoc;
+	///
+	/// if (2 == TypeLoc.value) ...
+	///
+	
+
+template <class T>
+struct TypeLocator<NullTypeList, T>
+{
+	enum { value = -1 };
+};
+
+
+template <class T, class Tail>
+struct TypeLocator<TypeList<T, Tail>, T>
+{
+	enum { value = 0 };
+};
+
+
+template <class Head, class Tail, class T>
+struct TypeLocator<TypeList<Head, Tail>, T>
+{
+private:
+	enum { tmp = TypeLocator<Tail, T>::value };
+public:
+	enum { value = tmp == -1 ? -1 : 1 + tmp };
+};
+
+
+template <class Head, class T> 
+struct TypeAppender;
+	/// TypeAppender appends T (type or a TypeList) to Head.
+	///
+	/// Usage:
+	///
+	/// typedef TypeListType<char>::HeadType Type1;
+	/// typedef TypeAppender<Type1, int>::HeadType Type2;
+	/// (Type2 is a TypeList of char,int)
+	///
+	///	typedef TypeListType<float, double>::HeadType Type3;
+	/// typedef TypeAppender<Type2, Type3>::HeadType Type4;
+	/// (Type4 is a TypeList of char,int,float,double)
+	///
+
+
+template <>
+struct TypeAppender<NullTypeList, NullTypeList>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <class T>
+struct TypeAppender<NullTypeList, T>
+{
+	typedef TypeList<T, NullTypeList> HeadType;
+};
+
+
+template <class Head, class Tail>
+struct TypeAppender<NullTypeList, TypeList<Head, Tail> >
+{
+	typedef TypeList<Head, Tail> HeadType;
+};
+
+
+template <class Head, class Tail, class T>
+struct TypeAppender<TypeList<Head, Tail>, T>
+{
+	typedef TypeList<Head, typename TypeAppender<Tail, T>::HeadType> HeadType;
+};
+
+
+template <class Head, class T> 
+struct TypeOneEraser;
+	/// TypeOneEraser erases the first occurence of the type T in Head.
+	/// Usage:
+	///
+	/// typedef TypeListType<char, int, float>::HeadType Type3;
+	/// typedef TypeOneEraser<Type3, int>::HeadType Type2;
+	/// (Type2 is a TypeList of char,float)
+	///
+
+
+template <class T>
+struct TypeOneEraser<NullTypeList, T>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <class T, class Tail>
+struct TypeOneEraser<TypeList<T, Tail>, T>
+{
+	typedef Tail HeadType;
+};
+
+
+template <class Head, class Tail, class T>
+struct TypeOneEraser<TypeList<Head, Tail>, T>
+{
+	typedef TypeList <Head, typename TypeOneEraser<Tail, T>::HeadType> HeadType;
+};
+
+
+template <class Head, class T> 
+struct TypeAllEraser;
+	/// TypeAllEraser erases all the occurences of the type T in Head.
+	/// Usage:
+	///
+	/// typedef TypeListType<char, int, float, int>::HeadType Type4;
+	/// typedef TypeAllEraser<Type4, int>::HeadType Type2;
+	/// (Type2 is a TypeList of char,float)
+	///
+
+
+template <class T>
+struct TypeAllEraser<NullTypeList, T>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <class T, class Tail>
+struct TypeAllEraser<TypeList<T, Tail>, T>
+{
+	typedef typename TypeAllEraser<Tail, T>::HeadType HeadType;
+};
+
+
+template <class Head, class Tail, class T>
+struct TypeAllEraser<TypeList<Head, Tail>, T>
+{
+	typedef TypeList <Head, typename TypeAllEraser<Tail, T>::HeadType> HeadType;
+};
+
+
+template <class Head> 
+struct TypeDuplicateEraser;
+	/// TypeDuplicateEraser erases all but the first occurence of the type T in Head.
+	/// Usage:
+	///
+	/// typedef TypeListType<char, int, float, int>::HeadType Type4;
+	/// typedef TypeDuplicateEraser<Type4, int>::HeadType Type3;
+	/// (Type3 is a TypeList of char,int,float)
+	///
+
+
+template <> 
+struct TypeDuplicateEraser<NullTypeList>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <class Head, class Tail>
+struct TypeDuplicateEraser<TypeList<Head, Tail> >
+{
+private:
+	typedef typename TypeDuplicateEraser<Tail>::HeadType L1;
+	typedef typename TypeOneEraser<L1, Head>::HeadType L2;
+public:
+	typedef TypeList<Head, L2> HeadType;
+};
+
+
+template <class Head, class T, class R>
+struct TypeOneReplacer;
+	/// TypeOneReplacer replaces the first occurence 
+	/// of the type T in Head with type R.
+	/// Usage:
+	///
+	/// typedef TypeListType<char, int, float, int>::HeadType Type4;
+	/// typedef TypeOneReplacer<Type4, int, double>::HeadType TypeR;
+	/// (TypeR is a TypeList of char,double,float,int)
+	///
+
+
+template <class T, class R>
+struct TypeOneReplacer<NullTypeList, T, R>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <class T, class Tail, class R>
+struct TypeOneReplacer<TypeList<T, Tail>, T, R>
+{
+	typedef TypeList<R, Tail> HeadType;
+};
+
+
+template <class Head, class Tail, class T, class R>
+struct TypeOneReplacer<TypeList<Head, Tail>, T, R>
+{
+	typedef TypeList<Head, typename TypeOneReplacer<Tail, T, R>::HeadType> HeadType;
+};
+
+
+template <class Head, class T, class R>
+struct TypeAllReplacer;
+	/// TypeAllReplacer replaces all the occurences 
+	/// of the type T in Head with type R.
+	/// Usage:
+	///
+	/// typedef TypeListType<char, int, float, int>::HeadType Type4;
+	/// typedef TypeAllReplacer<Type4, int, double>::HeadType TypeR;
+	/// (TypeR is a TypeList of char,double,float,double)
+	///
+
+
+template <class T, class R>
+struct TypeAllReplacer<NullTypeList, T, R>
+{
+	typedef NullTypeList HeadType;
+};
+
+
+template <class T, class Tail, class R>
+struct TypeAllReplacer<TypeList<T, Tail>, T, R>
+{
+	typedef TypeList<R, typename TypeAllReplacer<Tail, T, R>::HeadType> HeadType;
+};
+
+
+template <class Head, class Tail, class T, class R>
+struct TypeAllReplacer<TypeList<Head, Tail>, T, R>
+{
+	typedef TypeList<Head, typename TypeAllReplacer<Tail, T, R>::HeadType> HeadType;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_TypeList_INCLUDED
diff --git a/Poco/Types.h b/Poco/Types.h
new file mode 100644
index 0000000..f3d2ebc
--- /dev/null
+++ b/Poco/Types.h
@@ -0,0 +1,201 @@
+//
+// Types.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Types
+//
+// Definitions of fixed-size integer types for various platforms
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Types_INCLUDED
+#define Foundation_Types_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+#if defined(_MSC_VER)
+	//
+	// Windows/Visual C++
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	typedef signed __int64         Int64;
+	typedef unsigned __int64       UInt64;
+	#if defined(_WIN64)
+		#define POCO_PTR_IS_64_BIT 1
+		typedef signed __int64     IntPtr;
+		typedef unsigned __int64   UIntPtr;
+	#else
+		typedef signed long        IntPtr;
+		typedef unsigned long      UIntPtr;
+	#endif
+	#define POCO_HAVE_INT64 1
+#elif defined(__GNUC__) || defined(__clang__)
+	//
+	// Unix/GCC/Clang
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	#if defined(_WIN64)
+		#define POCO_PTR_IS_64_BIT 1
+		typedef signed long long   IntPtr;
+		typedef unsigned long long UIntPtr;
+		typedef signed long long   Int64;
+		typedef unsigned long long UInt64;
+	#else
+		typedef signed long        IntPtr;
+		typedef unsigned long      UIntPtr;
+		#if defined(__LP64__)
+			#define POCO_PTR_IS_64_BIT 1
+			#define POCO_LONG_IS_64_BIT 1
+			typedef signed long        Int64;
+			typedef unsigned long      UInt64;
+		#else
+			typedef signed long long   Int64;
+			typedef unsigned long long UInt64;
+		#endif
+	#endif
+	#define POCO_HAVE_INT64 1
+#elif defined(__DECCXX)
+	//
+	// Compaq C++
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	typedef signed __int64         Int64;
+	typedef unsigned __int64       UInt64;
+	typedef signed long        IntPtr;
+	typedef unsigned long      UIntPtr;
+	#define POCO_PTR_IS_64_BIT 1
+	#define POCO_LONG_IS_64_BIT 1
+	#define POCO_HAVE_INT64 1
+#elif defined(__HP_aCC)
+	//
+	// HP Ansi C++
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	typedef signed long            IntPtr;
+	typedef unsigned long          UIntPtr;
+	#if defined(__LP64__)
+		#define POCO_PTR_IS_64_BIT 1
+		#define POCO_LONG_IS_64_BIT 1
+		typedef signed long        Int64;
+		typedef unsigned long      UInt64;
+	#else
+		typedef signed long long   Int64;
+		typedef unsigned long long UInt64;
+	#endif
+	#define POCO_HAVE_INT64 1
+#elif defined(__SUNPRO_CC)
+	//
+	// SUN Forte C++
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	typedef signed long            IntPtr;
+	typedef unsigned long          UIntPtr;
+	#if defined(__sparcv9)
+		#define POCO_PTR_IS_64_BIT 1
+		#define POCO_LONG_IS_64_BIT 1
+		typedef signed long        Int64;
+		typedef unsigned long      UInt64;
+	#else
+		typedef signed long long   Int64;
+		typedef unsigned long long UInt64;
+	#endif
+	#define POCO_HAVE_INT64 1
+#elif defined(__IBMCPP__)
+	//
+	// IBM XL C++
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	typedef signed long            IntPtr;
+	typedef unsigned long          UIntPtr;
+	#if defined(__64BIT__)
+		#define POCO_PTR_IS_64_BIT 1
+		#define POCO_LONG_IS_64_BIT 1
+		typedef signed long        Int64;
+		typedef unsigned long      UInt64;
+	#else
+		typedef signed long long   Int64;
+		typedef unsigned long long UInt64;
+	#endif
+	#define POCO_HAVE_INT64 1
+#elif defined(__sgi)
+	//
+	// MIPSpro C++
+	//
+	typedef signed char            Int8;
+	typedef unsigned char          UInt8;
+	typedef signed short           Int16;
+	typedef unsigned short         UInt16;
+	typedef signed int             Int32;
+	typedef unsigned int           UInt32;
+	typedef signed long            IntPtr;
+	typedef unsigned long          UIntPtr;
+	#if _MIPS_SZLONG == 64
+		#define POCO_PTR_IS_64_BIT 1
+		#define POCO_LONG_IS_64_BIT 1
+		typedef signed long        Int64;
+		typedef unsigned long      UInt64;
+	#else
+		typedef signed long long   Int64;
+		typedef unsigned long long UInt64;
+	#endif
+	#define POCO_HAVE_INT64 1
+#elif defined(_DIAB_TOOL)
+	typedef signed char        Int8;
+	typedef unsigned char      UInt8;
+	typedef signed short       Int16;
+	typedef unsigned short     UInt16;
+	typedef signed int         Int32;
+	typedef unsigned int       UInt32;
+	typedef signed long        IntPtr;
+	typedef unsigned long      UIntPtr;
+	typedef signed long long   Int64;
+	typedef unsigned long long UInt64;
+	#define POCO_HAVE_INT64 1
+#endif
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Types_INCLUDED
diff --git a/Poco/URI.h b/Poco/URI.h
new file mode 100644
index 0000000..b6d41de
--- /dev/null
+++ b/Poco/URI.h
@@ -0,0 +1,406 @@
+//
+// URI.h
+//
+// Library: Foundation
+// Package: URI
+// Module:  URI
+//
+// Definition of the URI class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_URI_INCLUDED
+#define Foundation_URI_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <vector>
+#include <utility>
+
+
+namespace Poco {
+
+
+class Path;
+
+
+class Foundation_API URI
+	/// A Uniform Resource Identifier, as specified in RFC 3986.
+	/// 
+	/// The URI class provides methods for building URIs from their
+	/// parts, as well as for splitting URIs into their parts.
+	/// Furthermore, the class provides methods for resolving
+	/// relative URIs against base URIs.
+	///
+	/// The class automatically performs a few normalizations on
+	/// all URIs and URI parts passed to it:
+	///   * scheme identifiers are converted to lower case
+	///   * percent-encoded characters are decoded (except for the query string)
+	///   * optionally, dot segments are removed from paths (see normalize())
+	///
+	/// Note that dealing with query strings requires some precautions, as, internally,
+	/// query strings are stored in percent-encoded form, while all other parts of the URI
+	/// are stored in decoded form. While parsing query strings from properly encoded URLs
+	/// generally works, explicitly setting query strings with setQuery() or extracting
+	/// query strings with getQuery() may lead to ambiguities. See the descriptions of
+	/// setQuery(), setRawQuery(), getQuery() and getRawQuery() for more information.
+{
+public:
+	typedef std::vector<std::pair<std::string, std::string> > QueryParameters;
+
+	URI();
+		/// Creates an empty URI.
+
+	explicit URI(const std::string& uri);
+		/// Parses an URI from the given string. Throws a
+		/// SyntaxException if the uri is not valid.
+		
+	explicit URI(const char* uri);
+		/// Parses an URI from the given string. Throws a
+		/// SyntaxException if the uri is not valid.
+		
+	URI(const std::string& scheme, const std::string& pathEtc);
+		/// Creates an URI from its parts.
+		
+	URI(const std::string& scheme, const std::string& authority, const std::string& pathEtc);
+		/// Creates an URI from its parts.
+
+	URI(const std::string& scheme, const std::string& authority, const std::string& path, const std::string& query);
+		/// Creates an URI from its parts.
+
+	URI(const std::string& scheme, const std::string& authority, const std::string& path, const std::string& query, const std::string& fragment);
+		/// Creates an URI from its parts.
+
+	URI(const URI& uri);
+		/// Copy constructor. Creates an URI from another one.
+		
+	URI(const URI& baseURI, const std::string& relativeURI);
+		/// Creates an URI from a base URI and a relative URI, according to
+		/// the algorithm in section 5.2 of RFC 3986.
+
+	explicit URI(const Path& path);
+		/// Creates a URI from a path.
+		///
+		/// The path will be made absolute, and a file:// URI
+		/// will be built from it.
+
+	~URI();
+		/// Destroys the URI.
+	
+	URI& operator = (const URI& uri);
+		/// Assignment operator.
+		
+	URI& operator = (const std::string& uri);
+		/// Parses and assigns an URI from the given string. Throws a
+		/// SyntaxException if the uri is not valid.
+
+	URI& operator = (const char* uri);
+		/// Parses and assigns an URI from the given string. Throws a
+		/// SyntaxException if the uri is not valid.
+		
+	void swap(URI& uri);
+		/// Swaps the URI with another one.	
+		
+	void clear();
+		/// Clears all parts of the URI.
+	
+	std::string toString() const;
+		/// Returns a string representation of the URI.
+		///
+		/// Characters in the path, query and fragment parts will be 
+		/// percent-encoded as necessary.
+	
+	const std::string& getScheme() const;
+		/// Returns the scheme part of the URI.
+		
+	void setScheme(const std::string& scheme);
+		/// Sets the scheme part of the URI. The given scheme
+		/// is converted to lower-case.
+		///
+		/// A list of registered URI schemes can be found
+		/// at <http://www.iana.org/assignments/uri-schemes>.
+		
+	const std::string& getUserInfo() const;
+		/// Returns the user-info part of the URI.
+		
+	void setUserInfo(const std::string& userInfo);
+		/// Sets the user-info part of the URI.
+		
+	const std::string& getHost() const;
+		/// Returns the host part of the URI.
+		
+	void setHost(const std::string& host);
+		/// Sets the host part of the URI.
+		
+	unsigned short getPort() const;
+		/// Returns the port number part of the URI.
+		///
+		/// If no port number (0) has been specified, the
+		/// well-known port number (e.g., 80 for http) for
+		/// the given scheme is returned if it is known.
+		/// Otherwise, 0 is returned.
+		
+	void setPort(unsigned short port);
+		/// Sets the port number part of the URI.
+		
+	std::string getAuthority() const;
+		/// Returns the authority part (userInfo, host and port)
+		/// of the URI. 
+		///
+		/// If the port number is a well-known port
+		/// number for the given scheme (e.g., 80 for http), it
+		/// is not included in the authority.
+		
+	void setAuthority(const std::string& authority);
+		/// Parses the given authority part for the URI and sets
+		/// the user-info, host, port components accordingly.
+		
+	const std::string& getPath() const;
+		/// Returns the decoded path part of the URI.
+		
+	void setPath(const std::string& path);
+		/// Sets the path part of the URI.
+	
+	std::string getQuery() const;
+		/// Returns the decoded query part of the URI.
+		///
+		/// Note that encoded ampersand characters ('&', "%26") 
+		/// will be decoded, which could cause ambiguities if the query 
+		/// string contains multiple parameters and a parameter name
+		/// or value contains an ampersand as well.
+		/// In such a case it's better to use getRawQuery() or
+		/// getQueryParameters().
+		
+	void setQuery(const std::string& query);	
+		/// Sets the query part of the URI.
+		///
+		/// The query string will be percent-encoded. If the query
+		/// already contains percent-encoded characters, these
+		/// will be double-encoded, which is probably not what's
+		/// intended by the caller. Furthermore, ampersand ('&')
+		/// characters in the query will not be encoded. This could
+		/// lead to ambiguity issues if the query string contains multiple
+		/// name-value parameters separated by ampersand, and if any
+		/// name or value also contains an ampersand. In such a 
+		/// case, it's better to use setRawQuery() with a properly
+		/// percent-encoded query string, or use addQueryParameter()
+		/// or setQueryParameters(), which take care of appropriate 
+		/// percent encoding of parameter names and values.
+
+	void addQueryParameter(const std::string& param, const std::string& val = "");
+		/// Adds "param=val" to the query; "param" may not be empty.
+		/// If val is empty, only '=' is appended to the parameter.
+		/// 
+		/// In addition to regular encoding, function also encodes '&' and '=',
+		/// if found in param or val.
+
+	const std::string& getRawQuery() const;
+		/// Returns the query string in raw form, which usually
+		/// means percent encoded.
+		
+	void setRawQuery(const std::string& query);	
+		/// Sets the query part of the URI.
+		///
+		/// The given query string must be properly percent-encoded.
+	
+	QueryParameters getQueryParameters() const;
+		/// Returns the decoded query string parameters as a vector
+		/// of name-value pairs.
+
+	void setQueryParameters(const QueryParameters& params);
+		/// Sets the query part of the URI from a vector
+		/// of query parameters.
+		///
+		/// Calls addQueryParameter() for each parameter name and value.
+
+	const std::string& getFragment() const;
+		/// Returns the fragment part of the URI.
+		
+	void setFragment(const std::string& fragment);
+		/// Sets the fragment part of the URI.
+		
+	void setPathEtc(const std::string& pathEtc);
+		/// Sets the path, query and fragment parts of the URI.
+		
+	std::string getPathEtc() const;
+		/// Returns the encoded path, query and fragment parts of the URI.
+		
+	std::string getPathAndQuery() const;
+		/// Returns the encoded path and query parts of the URI.	
+		
+	void resolve(const std::string& relativeURI);
+		/// Resolves the given relative URI against the base URI.
+		/// See section 5.2 of RFC 3986 for the algorithm used.
+
+	void resolve(const URI& relativeURI);
+		/// Resolves the given relative URI against the base URI.
+		/// See section 5.2 of RFC 3986 for the algorithm used.
+
+	bool isRelative() const;
+		/// Returns true if the URI is a relative reference, false otherwise.
+		///
+		/// A relative reference does not contain a scheme identifier.
+		/// Relative references are usually resolved against an absolute
+		/// base reference.
+	
+	bool empty() const;
+		/// Returns true if the URI is empty, false otherwise.
+		
+	bool operator == (const URI& uri) const;
+		/// Returns true if both URIs are identical, false otherwise.
+		///
+		/// Two URIs are identical if their scheme, authority,
+		/// path, query and fragment part are identical.
+
+	bool operator == (const std::string& uri) const;
+		/// Parses the given URI and returns true if both URIs are identical,
+		/// false otherwise.
+
+	bool operator != (const URI& uri) const;
+		/// Returns true if both URIs are identical, false otherwise.
+
+	bool operator != (const std::string& uri) const;
+		/// Parses the given URI and returns true if both URIs are identical,
+		/// false otherwise.
+		
+	void normalize();
+		/// Normalizes the URI by removing all but leading . and .. segments from the path.
+		///
+		/// If the first path segment in a relative path contains a colon (:), 
+		/// such as in a Windows path containing a drive letter, a dot segment (./) 
+		/// is prepended in accordance with section 3.3 of RFC 3986.
+	
+	void getPathSegments(std::vector<std::string>& segments);
+		/// Places the single path segments (delimited by slashes) into the
+		/// given vector.
+	
+	static void encode(const std::string& str, const std::string& reserved, std::string& encodedStr);
+		/// URI-encodes the given string by escaping reserved and non-ASCII
+		/// characters. The encoded string is appended to encodedStr.
+		
+	static void decode(const std::string& str, std::string& decodedStr, bool plusAsSpace = false);
+		/// URI-decodes the given string by replacing percent-encoded
+		/// characters with the actual character. The decoded string
+		/// is appended to decodedStr.
+		///
+		/// When plusAsSpace is true, non-encoded plus signs in the query are decoded as spaces.
+		/// (http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1)
+
+protected:
+	bool equals(const URI& uri) const;
+		/// Returns true if both uri's are equivalent.
+	
+	bool isWellKnownPort() const;
+		/// Returns true if the URI's port number is a well-known one
+		/// (for example, 80, if the scheme is http).
+		
+	unsigned short getWellKnownPort() const;
+		/// Returns the well-known port number for the URI's scheme,
+		/// or 0 if the port number is not known.
+		
+	void parse(const std::string& uri);
+		/// Parses and assigns an URI from the given string. Throws a
+		/// SyntaxException if the uri is not valid.
+
+	void parseAuthority(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Parses and sets the user-info, host and port from the given data.
+
+	void parseHostAndPort(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Parses and sets the host and port from the given data.
+
+	void parsePath(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Parses and sets the path from the given data.
+
+	void parsePathEtc(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Parses and sets the path, query and fragment from the given data.
+
+	void parseQuery(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Parses and sets the query from the given data.
+
+	void parseFragment(std::string::const_iterator& it, const std::string::const_iterator& end);
+		/// Parses and sets the fragment from the given data.
+
+	void mergePath(const std::string& path);
+		/// Appends a path to the URI's path.
+
+	void removeDotSegments(bool removeLeading = true);
+		/// Removes all dot segments from the path.
+
+	static void getPathSegments(const std::string& path, std::vector<std::string>& segments);
+		/// Places the single path segments (delimited by slashes) into the
+		/// given vector.
+
+	void buildPath(const std::vector<std::string>& segments, bool leadingSlash, bool trailingSlash);
+		/// Builds the path from the given segments.
+
+	static const std::string RESERVED_PATH;
+	static const std::string RESERVED_QUERY;
+	static const std::string RESERVED_QUERY_PARAM;
+	static const std::string RESERVED_FRAGMENT;
+	static const std::string ILLEGAL;
+	
+private:
+	std::string    _scheme;
+	std::string    _userInfo;
+	std::string    _host;
+	unsigned short _port;
+	std::string    _path;
+	std::string    _query;
+	std::string    _fragment;
+};
+
+
+//
+// inlines
+//
+inline const std::string& URI::getScheme() const
+{
+	return _scheme;
+}
+	
+
+inline const std::string& URI::getUserInfo() const
+{
+	return _userInfo;
+}
+
+	
+inline const std::string& URI::getHost() const
+{
+	return _host;
+}
+
+	
+inline const std::string& URI::getPath() const
+{
+	return _path;
+}
+
+	
+inline const std::string& URI::getRawQuery() const
+{
+	return _query;
+}
+
+	
+inline const std::string& URI::getFragment() const
+{
+	return _fragment;
+}
+
+
+inline void swap(URI& u1, URI& u2)
+{
+	u1.swap(u2);
+}
+
+	
+} // namespace Poco
+
+
+#endif // Foundation_URI_INCLUDED
diff --git a/Poco/URIStreamFactory.h b/Poco/URIStreamFactory.h
new file mode 100644
index 0000000..c5efa22
--- /dev/null
+++ b/Poco/URIStreamFactory.h
@@ -0,0 +1,97 @@
+//
+// URIStreamFactory.h
+//
+// Library: Foundation
+// Package: URI
+// Module:  URIStreamFactory
+//
+// Definition of the URIStreamFactory class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_URIStreamFactory_INCLUDED
+#define Foundation_URIStreamFactory_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include <istream>
+
+
+namespace Poco {
+
+
+class URI;
+
+
+class Foundation_API URIStreamFactory
+	/// This class defines the interface that all
+	/// URI stream factories must implement.
+	///
+	/// Subclasses must implement the open() method.
+{
+public:
+	URIStreamFactory();
+		/// Creates the URIStreamFactory.
+
+	virtual std::istream* open(const URI& uri) = 0;
+		/// Tries to create and open an input stream for the
+		/// resource specified by the given URI.
+		///
+		/// If the stream cannot be opened for whatever reason,
+		/// an appropriate IOException must be thrown.
+		///
+		/// If opening the stream results in a redirect, a
+		/// URIRedirection exception should be thrown.
+
+protected:
+	virtual ~URIStreamFactory();
+		/// Destroys the URIStreamFactory.
+
+private:
+	URIStreamFactory(const URIStreamFactory&);
+	URIStreamFactory& operator = (const URIStreamFactory&);
+	
+	friend class URIStreamOpener;
+};
+
+
+class Foundation_API URIRedirection
+	/// An instance of URIRedirection is thrown by a URIStreamFactory::open()
+	/// if opening the original URI resulted in a redirection response
+	/// (such as a MOVED PERMANENTLY in HTTP).
+{
+public:
+	URIRedirection(const std::string& uri);
+	URIRedirection(const URIRedirection& redir);
+	
+	URIRedirection& operator = (const URIRedirection& redir);
+	void swap(URIRedirection& redir);
+	
+	const std::string& uri() const;
+		/// Returns the new URI.
+	
+private:
+	URIRedirection();
+	
+	std::string _uri;
+};
+
+
+//
+// inlines
+//
+inline const std::string& URIRedirection::uri() const
+{
+	return _uri;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_URIStreamFactory_INCLUDED
diff --git a/Poco/URIStreamOpener.h b/Poco/URIStreamOpener.h
new file mode 100644
index 0000000..85de22b
--- /dev/null
+++ b/Poco/URIStreamOpener.h
@@ -0,0 +1,135 @@
+//
+// URIStreamOpener.h
+//
+// Library: Foundation
+// Package: URI
+// Module:  URIStreamOpener
+//
+// Definition of the URIStreamOpener class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_URIStreamOpener_INCLUDED
+#define Foundation_URIStreamOpener_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Mutex.h"
+#include <istream>
+#include <map>
+
+
+namespace Poco {
+
+
+class URI;
+class URIStreamFactory;
+class Path;
+
+
+class Foundation_API URIStreamOpener
+	/// The URIStreamOpener class is used to create and open input streams
+	/// for resourced identified by Uniform Resource Identifiers.
+	///
+	/// For every URI scheme used, a URIStreamFactory must be registered.
+	/// A FileStreamFactory is automatically registered for file URIs.
+{
+public:
+	enum
+	{
+		MAX_REDIRECTS = 10
+	};
+	
+	URIStreamOpener();
+		/// Creates the URIStreamOpener and registers a FileStreamFactory
+		/// for file URIs.
+
+	~URIStreamOpener();
+		/// Destroys the URIStreamOpener and deletes all registered
+		/// URI stream factories.
+
+	std::istream* open(const URI& uri) const;
+		/// Tries to create and open an input stream for the resource specified
+		/// by the given uniform resource identifier.
+		///
+		/// If no URIStreamFactory has been registered for the URI's
+		/// scheme, a UnknownURIScheme exception is thrown.
+		/// If the stream cannot be opened for any reason, an
+		/// IOException is thrown.
+		///
+		/// The given URI must be a valid one. This excludes file system paths.
+		///
+		/// Whoever calls the method is responsible for deleting
+		/// the returned stream.
+
+	std::istream* open(const std::string& pathOrURI) const;
+		/// Tries to create and open an input stream for the resource specified
+		/// by the given path or uniform resource identifier.
+		///
+		/// If the stream cannot be opened for any reason, an
+		/// Exception is thrown.
+		///
+		/// The method first tries to interpret the given pathOrURI as an URI.
+		/// If this fails, the pathOrURI is treated as local filesystem path.
+		/// If this also fails, an exception is thrown.
+		///
+		/// Whoever calls the method is responsible for deleting
+		/// the returned stream.
+
+	std::istream* open(const std::string& basePathOrURI, const std::string& pathOrURI) const;
+		/// Tries to create and open an input stream for the resource specified
+		/// by the given path or uniform resource identifier.
+		///
+		/// pathOrURI is resolved against basePathOrURI (see URI::resolve() and
+		/// Path::resolve() for more information).
+		///
+		/// If the stream cannot be opened for any reason, an
+		/// Exception is thrown.
+		///
+		/// Whoever calls the method is responsible for deleting
+		/// the returned stream.
+		
+	void registerStreamFactory(const std::string& scheme, URIStreamFactory* pFactory);
+		/// Registers a URIStreamFactory for the given scheme. If another factory
+		/// has already been registered for the scheme, an ExistsException is thrown.
+		///
+		/// The URIStreamOpener takes ownership of the factory and deletes it when it is
+		/// no longer needed (in other words, when the URIStreamOpener is deleted).
+
+	void unregisterStreamFactory(const std::string& scheme);
+		/// Unregisters and deletes the URIStreamFactory for the given scheme.
+		///
+		/// Throws a NotFoundException if no URIStreamFactory has been registered
+		/// for the given scheme.
+		
+	bool supportsScheme(const std::string& scheme);
+		/// Returns true iff a URIStreamFactory for the given scheme
+		/// has been registered.
+
+	static URIStreamOpener& defaultOpener();
+		/// Returns a reference to the default URIStreamOpener.
+
+protected:
+	std::istream* openFile(const Path& path) const;
+	std::istream* openURI(const std::string& scheme, const URI& uri) const;
+
+private:
+	URIStreamOpener(const URIStreamOpener&);
+	URIStreamOpener& operator = (const URIStreamOpener&);
+
+	typedef std::map<std::string, URIStreamFactory*> FactoryMap;
+	
+	FactoryMap        _map;
+	mutable FastMutex _mutex;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_URIStreamOpener_INCLUDED
diff --git a/Poco/UTF16Encoding.h b/Poco/UTF16Encoding.h
new file mode 100644
index 0000000..0d38a71
--- /dev/null
+++ b/Poco/UTF16Encoding.h
@@ -0,0 +1,85 @@
+//
+// UTF16Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  UTF16Encoding
+//
+// Definition of the UTF16Encoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UTF16Encoding_INCLUDED
+#define Foundation_UTF16Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API UTF16Encoding: public TextEncoding
+	/// UTF-16 text encoding, as defined in RFC 2781.
+	///
+	/// When converting from UTF-16 to Unicode, surrogates are
+	/// reported as they are - in other words, surrogate pairs
+	/// are not combined into one Unicode character. 
+	/// When converting from Unicode to UTF-16, however, characters
+	/// outside the 16-bit range are converted into a low and
+	/// high surrogate.
+{
+public:
+	enum ByteOrderType
+	{
+		BIG_ENDIAN_BYTE_ORDER,
+		LITTLE_ENDIAN_BYTE_ORDER,
+		NATIVE_BYTE_ORDER
+	};
+	
+	UTF16Encoding(ByteOrderType byteOrder = NATIVE_BYTE_ORDER);
+		/// Creates and initializes the encoding for the given byte order.
+		
+	UTF16Encoding(int byteOrderMark);
+		/// Creates and initializes the encoding for the byte-order
+		/// indicated by the given byte-order mark, which is the Unicode
+		/// character 0xFEFF.
+		
+	~UTF16Encoding();
+	
+	ByteOrderType getByteOrder() const;
+		/// Returns the byte-order currently in use.
+		
+	void setByteOrder(ByteOrderType byteOrder);
+		/// Sets the byte order.
+		
+	void setByteOrder(int byteOrderMark);
+		/// Sets the byte order according to the given
+		/// byte order mark, which is the Unicode
+		/// character 0xFEFF.
+	
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	bool _flipBytes;
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UTF16Encoding_INCLUDED
diff --git a/Poco/UTF32Encoding.h b/Poco/UTF32Encoding.h
new file mode 100644
index 0000000..6f8af52
--- /dev/null
+++ b/Poco/UTF32Encoding.h
@@ -0,0 +1,82 @@
+//
+// UTF32Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  UTF32Encoding
+//
+// Definition of the UTF32Encoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UTF32Encoding_INCLUDED
+#define Foundation_UTF32Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API UTF32Encoding: public TextEncoding
+	/// UTF-32 text encoding, as defined in RFC 2781.
+	///
+	/// When converting from UTF-32 to Unicode, surrogates are
+	/// reported as they are - in other words, surrogate pairs
+	/// are not combined into one Unicode character. 
+{
+public:
+	enum ByteOrderType
+	{
+		BIG_ENDIAN_BYTE_ORDER,
+		LITTLE_ENDIAN_BYTE_ORDER,
+		NATIVE_BYTE_ORDER
+	};
+	
+	UTF32Encoding(ByteOrderType byteOrder = NATIVE_BYTE_ORDER);
+		/// Creates and initializes the encoding for the given byte order.
+		
+	UTF32Encoding(int byteOrderMark);
+		/// Creates and initializes the encoding for the byte-order
+		/// indicated by the given byte-order mark, which is the Unicode
+		/// character 0xFEFF.
+		
+	~UTF32Encoding();
+	
+	ByteOrderType getByteOrder() const;
+		/// Returns the byte-order currently in use.
+		
+	void setByteOrder(ByteOrderType byteOrder);
+		/// Sets the byte order.
+		
+	void setByteOrder(int byteOrderMark);
+		/// Sets the byte order according to the given
+		/// byte order mark, which is the Unicode
+		/// character 0xFEFF.
+	
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	bool _flipBytes;
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UTF32Encoding_INCLUDED
diff --git a/Poco/UTF8Encoding.h b/Poco/UTF8Encoding.h
new file mode 100644
index 0000000..66e29d2
--- /dev/null
+++ b/Poco/UTF8Encoding.h
@@ -0,0 +1,61 @@
+//
+// UTF8Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  UTF8Encoding
+//
+// Definition of the UTF8Encoding class.
+//
+// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UTF8Encoding_INCLUDED
+#define Foundation_UTF8Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API UTF8Encoding: public TextEncoding
+	/// UTF-8 text encoding, as defined in RFC 2279.
+{
+public:
+	UTF8Encoding();
+	~UTF8Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+
+	static bool isLegal(const unsigned char *bytes, int length);
+		/// Utility routine to tell whether a sequence of bytes is legal UTF-8.
+		/// This must be called with the length pre-determined by the first byte.
+		/// The sequence is illegal right away if there aren't enough bytes 
+		/// available. If presented with a length > 4, this function returns false.
+		/// The Unicode definition of UTF-8 goes up to 4-byte sequences.
+		/// 
+		/// Adapted from ftp://ftp.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
+		/// Copyright 2001-2004 Unicode, Inc.
+
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UTF8Encoding_INCLUDED
diff --git a/Poco/UTF8String.h b/Poco/UTF8String.h
new file mode 100644
index 0000000..73898c6
--- /dev/null
+++ b/Poco/UTF8String.h
@@ -0,0 +1,83 @@
+//
+// UTF8String.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  UTF8String
+//
+// Definition of the UTF8 string functions.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UTF8String_INCLUDED
+#define Foundation_UTF8String_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+struct Foundation_API UTF8
+	/// This class provides static methods that are UTF-8 capable variants
+	/// of the same functions in Poco/String.h.
+	///
+	/// The various variants of icompare() provide case insensitive comparison
+	/// for UTF-8 encoded strings.
+	///
+	/// toUpper(), toUpperInPlace(), toLower() and toLowerInPlace() provide
+	/// Unicode-based character case transformation for UTF-8 encoded strings.
+	///
+	/// removeBOM() removes the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF)
+	/// from the beginning of the given string, if it's there.
+{
+	static int icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, std::string::const_iterator it2, std::string::const_iterator end2);
+	static int icompare(const std::string& str1, const std::string& str2);
+	static int icompare(const std::string& str1, std::string::size_type n1, const std::string& str2, std::string::size_type n2);
+	static int icompare(const std::string& str1, std::string::size_type n, const std::string& str2);
+	static int icompare(const std::string& str1, std::string::size_type pos, std::string::size_type n, const std::string& str2);
+	static int icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n1, const std::string& str2, std::string::size_type pos2, std::string::size_type n2);
+	static int icompare(const std::string& str1, std::string::size_type pos1, std::string::size_type n, const std::string& str2, std::string::size_type pos2);
+	static int icompare(const std::string& str, std::string::size_type pos, std::string::size_type n, const std::string::value_type* ptr);
+	static int icompare(const std::string& str, std::string::size_type pos, const std::string::value_type* ptr);
+	static int icompare(const std::string& str, const std::string::value_type* ptr);
+
+	static std::string toUpper(const std::string& str);
+	static std::string& toUpperInPlace(std::string& str);
+	static std::string toLower(const std::string& str);
+	static std::string& toLowerInPlace(std::string& str);
+	
+	static void removeBOM(std::string& str);
+		/// Remove the UTF-8 Byte Order Mark sequence (0xEF, 0xBB, 0xBF)
+		/// from the beginning of the string, if it's there.
+
+	static std::string escape(const std::string& s, bool strictJSON = false);
+		/// Escapes a string. Special characters like tab, backslash, ... are
+		/// escaped. Unicode characters are escaped to \uxxxx.
+		/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B
+		/// instead of \\a and \\v for strict JSON conformance.
+
+	static std::string escape(const std::string::const_iterator& begin, const std::string::const_iterator& end, bool strictJSON = false);
+		/// Escapes a string. Special characters like tab, backslash, ... are
+		/// escaped. Unicode characters are escaped to \uxxxx.
+		/// If strictJSON is true, \a and \v will be escaped to \\u0007 and \\u000B
+		/// instead of \\a and \\v for strict JSON conformance.
+
+	static std::string unescape(const std::string& s);
+		/// Creates an UTF8 string from a string that contains escaped characters.
+
+	static std::string unescape(const std::string::const_iterator& begin, const std::string::const_iterator& end);
+		/// Creates an UTF8 string from a string that contains escaped characters.
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UTF8String_INCLUDED
diff --git a/Poco/UTFString.h b/Poco/UTFString.h
new file mode 100644
index 0000000..7364583
--- /dev/null
+++ b/Poco/UTFString.h
@@ -0,0 +1,305 @@
+//
+// UTFString.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  UTFString
+//
+// Definitions of strings for UTF encodings.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UTFString_INCLUDED
+#define Foundation_UTFString_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Types.h"
+#include <string>
+
+
+namespace Poco {
+
+
+struct UTF16CharTraits
+{
+	typedef std::fpos<std::mbstate_t> u16streampos;
+	typedef UInt16                    char_type;
+	typedef int                       int_type;
+	typedef std::streamoff            off_type;
+	typedef u16streampos              pos_type;
+	typedef std::mbstate_t            state_type;
+
+	static void assign(char_type& c1, const char_type& c2)
+	{
+		c1 = c2;
+	}
+	
+	static bool eq(char_type c1, char_type c2)
+	{
+		return c1 == c2;
+	}
+	
+	static bool lt(char_type c1, char_type c2)
+	{
+		return c1 < c2;
+	}
+
+	static int compare(const char_type* s1, const char_type* s2, std::size_t n)
+	{
+		for (; n; --n, ++s1, ++s2)
+		{
+			if (lt(*s1, *s2))
+				return -1;
+			if (lt(*s2, *s1))
+				return 1;
+		}
+		return 0;
+	}
+
+	static std::size_t length(const char_type* s)
+	{
+		std::size_t len = 0;
+		for (; !eq(*s, char_type(0)); ++s)
+			++len;
+		return len;
+	}
+
+	static const char_type* find(const char_type* s, std::size_t n, const char_type& a)
+	{
+		for (; n; --n)
+		{
+			if (eq(*s, a))
+				return s;
+			++s;
+		}
+		return 0;
+	}
+
+	static char_type* move(char_type* s1, const char_type* s2, std::size_t n)
+	{
+		char_type* r = s1;
+		if (s1 < s2)
+		{
+			for (; n; --n, ++s1, ++s2)
+				assign(*s1, *s2);
+		}
+		else if (s2 < s1)
+		{
+			s1 += n;
+			s2 += n;
+			for (; n; --n)
+				assign(*--s1, *--s2);
+		}
+		return r;
+	}
+
+	static char_type* copy(char_type* s1, const char_type* s2, std::size_t n)
+	{
+		poco_assert(s2 < s1 || s2 >= s1 + n);
+		char_type* r = s1;
+		for (; n; --n, ++s1, ++s2)
+			assign(*s1, *s2);
+		return r;
+	}
+
+	static char_type* assign(char_type* s, std::size_t n, char_type a)
+	{
+		char_type* r = s;
+		for (; n; --n, ++s)
+			assign(*s, a);
+		return r;
+	}
+
+	static int_type  not_eof(int_type c)
+	{
+		return eq_int_type(c, eof()) ? ~eof() : c;
+	}
+	
+	static char_type to_char_type(int_type c)
+	{
+		return char_type(c);
+	}
+	
+	static int_type to_int_type(char_type c)
+	{
+		return int_type(c);
+	}
+	
+	static bool eq_int_type(int_type c1, int_type c2)
+	{
+		return c1 == c2;
+	}
+	
+	static int_type eof()
+	{
+		return int_type(0xDFFF);
+	}
+};
+
+
+struct UTF32CharTraits
+{
+	typedef std::fpos<std::mbstate_t> u32streampos;
+	typedef UInt32                    char_type;
+	typedef int                       int_type;
+	typedef std::streamoff            off_type;
+	typedef u32streampos              pos_type;
+	typedef std::mbstate_t            state_type;
+
+	static void assign(char_type& c1, const char_type& c2)
+	{
+		c1 = c2;
+	}
+	
+	static bool eq(char_type c1, char_type c2)
+	{
+		return c1 == c2;
+	}
+	
+	static bool lt(char_type c1, char_type c2)
+	{
+		return c1 < c2;
+	}
+
+	static int compare(const char_type* s1, const char_type* s2, std::size_t n)
+	{
+		for (; n; --n, ++s1, ++s2)
+		{
+			if (lt(*s1, *s2))
+				return -1;
+			if (lt(*s2, *s1))
+				return 1;
+		}
+		return 0;
+	}
+
+	static std::size_t length(const char_type* s)
+	{
+		std::size_t len = 0;
+		for (; !eq(*s, char_type(0)); ++s)
+			++len;
+		return len;
+	}
+
+	static const char_type* find(const char_type* s, std::size_t n, const char_type& a)
+	{
+		for (; n; --n)
+		{
+			if (eq(*s, a))
+				return s;
+			++s;
+		}
+		return 0;
+	}
+
+	static char_type* move(char_type* s1, const char_type* s2, std::size_t n)
+	{
+		char_type* r = s1;
+		if (s1 < s2)
+		{
+			for (; n; --n, ++s1, ++s2)
+				assign(*s1, *s2);
+		}
+		else if (s2 < s1)
+		{
+			s1 += n;
+			s2 += n;
+			for (; n; --n)
+				assign(*--s1, *--s2);
+		}
+		return r;
+	}
+
+	static char_type* copy(char_type* s1, const char_type* s2, std::size_t n)
+	{
+		poco_assert(s2 < s1 || s2 >= s1 + n);
+		char_type* r = s1;
+		for (; n; --n, ++s1, ++s2)
+			assign(*s1, *s2);
+		return r;
+	}
+
+	static char_type* assign(char_type* s, std::size_t n, char_type a)
+	{
+		char_type* r = s;
+		for (; n; --n, ++s)
+			assign(*s, a);
+		return r;
+	}
+
+	static int_type  not_eof(int_type c)
+	{
+		return eq_int_type(c, eof()) ? ~eof() : c;
+	}
+	
+	static char_type to_char_type(int_type c)
+	{
+		return char_type(c);
+	}
+	
+	static int_type to_int_type(char_type c)
+	{
+		return int_type(c);
+	}
+	
+	static bool eq_int_type(int_type c1, int_type c2)
+	{
+		return c1 == c2;
+	}
+	
+	static int_type eof()
+	{
+		return int_type(0xDFFF);
+	}
+};
+
+
+//#if defined(POCO_ENABLE_CPP11) //TODO
+	//	typedef char16_t       UTF16Char;
+	//	typedef std::u16string UTF16String;
+	//	typedef char32_t       UTF32Char;
+	//	typedef std::u32string UTF32String;
+//#else
+	#ifdef POCO_NO_WSTRING
+		typedef Poco::UInt16                                  UTF16Char;
+		typedef std::basic_string<UTF16Char, UTF16CharTraits> UTF16String;
+		typedef UInt32                                        UTF32Char;
+		typedef std::basic_string<UTF32Char, UTF32CharTraits> UTF32String;
+	#else // POCO_NO_WSTRING
+		#if defined(POCO_OS_FAMILY_WINDOWS)
+			typedef wchar_t                                       UTF16Char;
+			typedef std::wstring                                  UTF16String;
+			typedef UInt32                                        UTF32Char;
+			typedef std::basic_string<UTF32Char, UTF32CharTraits> UTF32String;
+		#elif defined(__SIZEOF_WCHAR_T__) //gcc
+			#if (__SIZEOF_WCHAR_T__ == 2)
+				typedef wchar_t                                       UTF16Char;
+				typedef std::wstring                                  UTF16String;
+				typedef UInt32                                        UTF32Char;
+				typedef std::basic_string<UTF32Char, UTF32CharTraits> UTF32String;
+			#elif (__SIZEOF_WCHAR_T__ == 4)
+				typedef Poco::UInt16                                  UTF16Char;
+				typedef std::basic_string<UTF16Char, UTF16CharTraits> UTF16String;
+				typedef wchar_t                                       UTF32Char;
+				typedef std::wstring                                  UTF32String;
+			#endif
+		#else // default to 32-bit wchar_t
+			typedef Poco::UInt16                                  UTF16Char;
+			typedef std::basic_string<UTF16Char, UTF16CharTraits> UTF16String;
+			typedef wchar_t                                       UTF32Char;
+			typedef std::wstring                                  UTF32String;
+		#endif //POCO_OS_FAMILY_WINDOWS
+	#endif //POCO_NO_WSTRING
+//#endif // POCO_ENABLE_CPP11
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UTFString_INCLUDED
diff --git a/Poco/UUID.h b/Poco/UUID.h
new file mode 100644
index 0000000..2708a00
--- /dev/null
+++ b/Poco/UUID.h
@@ -0,0 +1,219 @@
+//
+// UUID.h
+//
+// Library: Foundation
+// Package: UUID
+// Module:  UUID
+//
+// Definition of the UUID class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UUID_INCLUDED
+#define Foundation_UUID_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API UUID
+	/// A UUID is an identifier that is unique across both space and time,
+	/// with respect to the space of all UUIDs. Since a UUID is a fixed
+	/// size and contains a time field, it is possible for values to
+	/// rollover (around A.D. 3400, depending on the specific algorithm
+	/// used). A UUID can be used for multiple purposes, from tagging
+	/// objects with an extremely short lifetime, to reliably identifying
+	/// very persistent objects across a network.
+	///
+	/// This class implements a Universal Unique Identifier,
+	/// as specified in Appendix A of the DCE 1.1 Remote Procedure
+	/// Call Specification (http://www.opengroup.org/onlinepubs/9629399/),
+	/// RFC 2518 (WebDAV), section 6.4.1 and the UUIDs and GUIDs internet
+	/// draft by Leach/Salz from February, 1998 
+	/// (http://www.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt)
+	/// and also http://tools.ietf.org/html/draft-mealling-uuid-urn-05
+{
+public:
+	enum Version
+	{
+		UUID_TIME_BASED      = 0x01,
+		UUID_DCE_UID         = 0x02,
+		UUID_NAME_BASED      = 0x03,
+		UUID_RANDOM          = 0x04,
+		UUID_NAME_BASED_SHA1 = 0x05
+		
+	};
+
+	UUID();
+		/// Creates a nil (all zero) UUID.
+		
+	UUID(const UUID& uuid);
+		/// Copy constructor.
+
+	explicit UUID(const std::string& uuid);
+		/// Parses the UUID from a string.
+		
+	explicit UUID(const char* uuid);
+		/// Parses the UUID from a string.
+
+	~UUID();
+		/// Destroys the UUID.
+
+	UUID& operator = (const UUID& uuid);
+		/// Assignment operator.
+		
+	void swap(UUID& uuid);
+		/// Swaps the UUID with another one.	
+		
+	void parse(const std::string& uuid);
+		/// Parses the UUID from its string representation.
+
+	bool tryParse(const std::string& uuid);
+		/// Tries to interpret the given string as an UUID.
+		/// If the UUID is syntactically valid, assigns the
+		/// members and returns true. Otherwise leaves the 
+		/// object unchanged and returns false.
+
+	std::string toString() const;
+		/// Returns a string representation of the UUID consisting
+		/// of groups of hexadecimal digits separated by hyphens.
+
+	void copyFrom(const char* buffer);
+		/// Copies the UUID (16 bytes) from a buffer or byte array.
+		/// The UUID fields are expected to be
+		/// stored in network byte order.
+		/// The buffer need not be aligned.
+
+	void copyTo(char* buffer) const;
+		/// Copies the UUID to the buffer. The fields
+		/// are in network byte order.
+		/// The buffer need not be aligned.
+		/// There must have room for at least 16 bytes.
+
+	Version version() const;
+		/// Returns the version of the UUID.
+		
+	int variant() const;
+		/// Returns the variant number of the UUID:
+		///   - 0 reserved for NCS backward compatibility
+		///   - 2 the Leach-Salz variant (used by this class)
+		///   - 6 reserved, Microsoft Corporation backward compatibility
+		///   - 7 reserved for future definition
+
+	bool operator == (const UUID& uuid) const;
+	bool operator != (const UUID& uuid) const;
+	bool operator <  (const UUID& uuid) const;
+	bool operator <= (const UUID& uuid) const;
+	bool operator >  (const UUID& uuid) const;
+	bool operator >= (const UUID& uuid) const;
+	
+	bool isNull() const;
+		/// Returns true iff the UUID is nil (in other words,
+		/// consists of all zeros).
+
+	static const UUID& null();
+		/// Returns a null/nil UUID.
+
+	static const UUID& dns();
+		/// Returns the namespace identifier for the DNS namespace.
+		
+	static const UUID& uri();
+		/// Returns the namespace identifier for the URI (former URL) namespace.
+
+	static const UUID& oid();
+		/// Returns the namespace identifier for the OID namespace.
+
+	static const UUID& x500();
+		/// Returns the namespace identifier for the X500 namespace.
+
+protected:
+	UUID(UInt32 timeLow, UInt32 timeMid, UInt32 timeHiAndVersion, UInt16 clockSeq, UInt8 node[]);
+	UUID(const char* bytes, Version version);
+	int compare(const UUID& uuid) const;
+	static void appendHex(std::string& str, UInt8 n);
+	static void appendHex(std::string& str, UInt16 n);
+	static void appendHex(std::string& str, UInt32 n);
+	static Int16 nibble(char hex);
+	void fromNetwork();
+	void toNetwork();
+
+private:
+	UInt32 _timeLow;
+	UInt16 _timeMid;
+	UInt16 _timeHiAndVersion;
+	UInt16 _clockSeq;
+	UInt8  _node[6];
+	
+	friend class UUIDGenerator;
+};
+
+
+//
+// inlines
+//
+inline bool UUID::operator == (const UUID& uuid) const
+{
+	return compare(uuid) == 0;
+}
+
+
+inline bool UUID::operator != (const UUID& uuid) const
+{
+	return compare(uuid) != 0;
+}
+
+
+inline bool UUID::operator < (const UUID& uuid) const
+{
+	return compare(uuid) < 0;
+}
+
+
+inline bool UUID::operator <= (const UUID& uuid) const
+{
+	return compare(uuid) <= 0;
+}
+
+
+inline bool UUID::operator > (const UUID& uuid) const
+{
+	return compare(uuid) > 0;
+}
+
+
+inline bool UUID::operator >= (const UUID& uuid) const
+{
+	return compare(uuid) >= 0;
+}
+
+
+inline UUID::Version UUID::version() const
+{
+	return Version(_timeHiAndVersion >> 12);
+}
+
+
+inline bool UUID::isNull() const
+{
+	return compare(null()) == 0;
+}
+
+
+inline void swap(UUID& u1, UUID& u2)
+{
+	u1.swap(u2);
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UUID_INCLUDED
diff --git a/Poco/UUIDGenerator.h b/Poco/UUIDGenerator.h
new file mode 100644
index 0000000..517417d
--- /dev/null
+++ b/Poco/UUIDGenerator.h
@@ -0,0 +1,104 @@
+//
+// UUIDGenerator.h
+//
+// Library: Foundation
+// Package: UUID
+// Module:  UUID
+//
+// Definition of the UUIDGenerator class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UUIDGenerator_INCLUDED
+#define Foundation_UUIDGenerator_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UUID.h"
+#include "Poco/Mutex.h"
+#include "Poco/Random.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Environment.h"
+
+
+namespace Poco {
+
+
+class DigestEngine;
+
+
+class Foundation_API UUIDGenerator
+	/// This class implements a generator for Universal Unique Identifiers,
+	/// as specified in Appendix A of the DCE 1.1 Remote Procedure
+	/// Call Specification (http://www.opengroup.org/onlinepubs/9629399/),
+	/// RFC 2518 (WebDAV), section 6.4.1 and the UUIDs and GUIDs internet
+	/// draft by Leach/Salz from February, 1998 
+	/// (http://ftp.ics.uci.edu/pub/ietf/webdav/uuid-guid/draft-leach-uuids-guids-01.txt)
+{
+public:
+	UUIDGenerator();
+		/// Creates the UUIDGenerator.
+
+	~UUIDGenerator();
+		/// Destroys the UUIDGenerator.
+
+	UUID create();
+		/// Creates a new time-based UUID, using the MAC address of
+		/// one of the system's ethernet adapters.
+		///
+		/// Throws a SystemException if no MAC address can be
+		/// obtained.
+	
+	UUID createFromName(const UUID& nsid, const std::string& name);
+		/// Creates a name-based UUID.
+
+	UUID createFromName(const UUID& nsid, const std::string& name, DigestEngine& de);
+		/// Creates a name-based UUID, using the given digest engine.
+		///
+		/// Note: in order to create a standard-compliant UUID, the given DigestEngine
+		/// must be either an instance of MD5Engine or SHA1Engine. The version field of
+		/// the UUID will be set accordingly.
+
+	UUID createFromName(const UUID& nsid, const std::string& name, DigestEngine& de, UUID::Version version);
+		/// Creates a name-based UUID, using the given digest engine and version.
+		
+	UUID createRandom();
+		/// Creates a random UUID.
+		
+	UUID createOne();
+		/// Tries to create and return a time-based UUID (see create()), and, 
+		/// if that does not work due to the unavailability of a MAC address,
+		/// creates and returns a random UUID (see createRandom()).
+		///
+		/// The UUID::version() method can be used to determine the actual kind of
+		/// the UUID generated.
+
+	static UUIDGenerator& defaultGenerator();
+		/// Returns a reference to the default UUIDGenerator.
+		
+protected:
+	Timestamp::UtcTimeVal timeStamp();
+	void getNode();
+
+private:
+	FastMutex           _mutex;
+	Random              _random;
+	Timestamp           _lastTime;
+	int                 _ticks;
+	Environment::NodeId _node;
+	bool                _haveNode;
+	
+	UUIDGenerator(const UUIDGenerator&);
+	UUIDGenerator& operator = (const UUIDGenerator&);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UUIDGenerator_INCLUDED
diff --git a/Poco/UnWindows.h b/Poco/UnWindows.h
new file mode 100644
index 0000000..0888c59
--- /dev/null
+++ b/Poco/UnWindows.h
@@ -0,0 +1,142 @@
+//
+// UnWindows.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  UnWindows
+//
+// A wrapper around the <windows.h> header file that #undef's some
+// of the macros for function names defined by <windows.h> that
+// are a frequent source of conflicts (e.g., GetUserName).
+//
+// Remember, that most of the WIN32 API functions come in two variants,
+// an Unicode variant (e.g., GetUserNameA) and an ASCII variant (GetUserNameW).
+// There is also a macro (GetUserName) that's either defined to be the Unicode
+// name or the ASCII name, depending on whether the UNICODE macro is #define'd
+// or not. POCO always calls the Unicode or ASCII functions directly (depending
+// on whether POCO_WIN32_UTF8 is #define'd or not), so the macros are not ignored.
+//
+// These macro definitions are a frequent case of problems and naming conflicts,
+// especially for C++ programmers. Say, you define a class with a member function named
+// GetUserName. Depending on whether "Poco/UnWindows.h" has been included by a particular
+// translation unit or not, this might be changed to GetUserNameA/GetUserNameW, or not.
+// While, due to naming conventions used, this is less of a problem in POCO, some
+// of the users of POCO might use a different naming convention where this can become
+// a problem.
+//
+// To disable the #undef's, compile POCO with the POCO_NO_UNWINDOWS macro #define'd.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UnWindows_INCLUDED
+#define Foundation_UnWindows_INCLUDED
+
+
+// Reduce bloat
+#if defined(_WIN32)
+	#if !defined(WIN32_LEAN_AND_MEAN) && !defined(POCO_BLOATED_WIN32)
+		#define WIN32_LEAN_AND_MEAN
+	#endif
+#endif
+
+
+// Microsoft Visual C++ includes copies of the Windows header files 
+// that were current at the time Visual C++ was released.
+// The Windows header files use macros to indicate which versions 
+// of Windows support many programming elements. Therefore, you must 
+// define these macros to use new functionality introduced in each 
+// major operating system release. (Individual header files may use 
+// different macros; therefore, if compilation problems occur, check 
+// the header file that contains the definition for conditional 
+// definitions.) For more information, see SdkDdkVer.h.
+
+
+#if !defined(_WIN32_WCE)
+#if defined(_WIN32_WINNT)
+	#if (_WIN32_WINNT < 0x0501)
+		#error Unsupported Windows version.
+	#endif
+#elif defined(NTDDI_VERSION)
+	#if (NTDDI_VERSION < 0x05010100)
+		#error Unsupported Windows version.
+	#endif
+#elif !defined(_WIN32_WINNT)
+	// Define minimum supported version.
+	// This can be changed, if needed.
+	// If allowed (see POCO_MIN_WINDOWS_OS_SUPPORT
+	// below), Platform_WIN32.h will do its
+	// best to determine the appropriate values
+	// and may redefine these. See Platform_WIN32.h
+	// for details.
+	#define _WIN32_WINNT 0x0501
+	#define NTDDI_VERSION 0x05010100
+#endif
+#endif
+
+
+// To prevent Platform_WIN32.h to modify version defines,
+// uncomment this, otherwise versions will be automatically
+// discovered in Platform_WIN32.h.
+// #define POCO_FORCE_MIN_WINDOWS_OS_SUPPORT
+
+
+#include <windows.h>
+
+
+#if !defined(POCO_NO_UNWINDOWS)
+// A list of annoying macros to #undef.
+// Extend as required.
+#undef GetBinaryType
+#undef GetShortPathName
+#undef GetLongPathName
+#undef GetEnvironmentStrings
+#undef SetEnvironmentStrings
+#undef FreeEnvironmentStrings
+#undef FormatMessage
+#undef EncryptFile
+#undef DecryptFile
+#undef CreateMutex
+#undef OpenMutex
+#undef CreateEvent
+#undef OpenEvent
+#undef CreateSemaphore
+#undef OpenSemaphore
+#undef LoadLibrary
+#undef GetModuleFileName
+#undef CreateProcess
+#undef GetCommandLine
+#undef GetEnvironmentVariable
+#undef SetEnvironmentVariable
+#undef ExpandEnvironmentStrings
+#undef OutputDebugString
+#undef FindResource
+#undef UpdateResource
+#undef FindAtom
+#undef AddAtom
+#undef GetSystemDirectory
+#undef GetTempPath
+#undef GetTempFileName
+#undef SetCurrentDirectory
+#undef GetCurrentDirectory
+#undef CreateDirectory
+#undef RemoveDirectory
+#undef CreateFile
+#undef DeleteFile
+#undef SearchPath
+#undef CopyFile
+#undef MoveFile
+#undef ReplaceFile
+#undef GetComputerName
+#undef SetComputerName
+#undef GetUserName
+#undef LogonUser
+#undef GetVersion
+#undef GetObject
+#endif // POCO_NO_UNWINDOWS
+
+#endif // Foundation_UnWindows_INCLUDED
diff --git a/Poco/UnbufferedStreamBuf.h b/Poco/UnbufferedStreamBuf.h
new file mode 100644
index 0000000..ed56cb8
--- /dev/null
+++ b/Poco/UnbufferedStreamBuf.h
@@ -0,0 +1,179 @@
+//
+// UnufferedStreamBuf.h
+//
+// Library: Foundation
+// Package: Streams
+// Module:  StreamBuf
+//
+// Definition of template BasicUnbufferedStreamBuf and class UnbufferedStreamBuf.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UnbufferedStreamBuf_INCLUDED
+#define Foundation_UnbufferedStreamBuf_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/StreamUtil.h"
+#include <streambuf>
+#include <iosfwd>
+#include <ios>
+
+
+namespace Poco {
+
+
+template <typename ch, typename tr> 
+class BasicUnbufferedStreamBuf: public std::basic_streambuf<ch, tr>
+	/// This is an implementation of an unbuffered streambuf
+	/// that greatly simplifies the implementation of
+	/// custom streambufs of various kinds.
+	/// Derived classes only have to override the methods
+	/// readFromDevice() or writeToDevice().
+{
+protected:
+	typedef std::basic_streambuf<ch, tr> Base;
+	typedef std::basic_ios<ch, tr> IOS;
+	typedef ch char_type;
+	typedef tr char_traits;
+	typedef typename Base::int_type int_type;
+	typedef typename Base::pos_type pos_type;
+	typedef typename Base::off_type off_type;
+	typedef typename IOS::openmode openmode;
+
+public:
+	BasicUnbufferedStreamBuf():
+		_pb(char_traits::eof()),
+		_ispb(false)
+	{
+		this->setg(0, 0, 0);
+		this->setp(0, 0);
+	}
+
+	~BasicUnbufferedStreamBuf()
+	{
+	}
+
+	virtual int_type overflow(int_type c)
+	{
+		if (c != char_traits::eof()) 
+			return writeToDevice(char_traits::to_char_type(c));
+		else
+			return c;
+	}
+
+	virtual int_type underflow()
+	{
+		if (_ispb)
+		{
+			return _pb;
+		}
+		else
+		{
+			int_type c = readFromDevice();
+			if (c != char_traits::eof())
+			{
+				_ispb = true;
+				_pb   = c;
+			}
+			return c;
+		}
+	}
+
+	virtual int_type uflow()
+	{
+		if (_ispb)
+		{
+			_ispb = false;
+			return _pb;
+		}
+		else
+		{
+			int_type c = readFromDevice();
+			if (c != char_traits::eof())
+			{
+				_pb = c;
+			}
+			return c;
+		}
+	}
+
+	virtual int_type pbackfail(int_type c)
+	{
+		if (_ispb)
+		{
+			return char_traits::eof();
+		}
+		else
+		{
+			_ispb = true;
+			_pb   = c;
+			return c;
+		}
+	}
+	
+	virtual std::streamsize xsgetn(char_type* p, std::streamsize count)
+		/// Some platforms (for example, Compaq C++) have buggy implementations of 
+		/// xsgetn that handle null buffers incorrectly.
+		/// Anyway, it does not hurt to provide an optimized implementation
+		/// of xsgetn for this streambuf implementation.
+	{
+		std::streamsize copied = 0;
+		while (count > 0)
+		{
+			int_type c = uflow();
+			if (c == char_traits::eof()) break;
+			*p++ = char_traits::to_char_type(c);
+			++copied;
+			--count;
+		}
+		return copied;
+	}
+
+protected:
+	static int_type charToInt(char_type c)
+	{
+		return char_traits::to_int_type(c);
+	}
+
+private:
+	virtual int_type readFromDevice()
+	{
+		return char_traits::eof();
+	}
+	
+	virtual int_type writeToDevice(char_type)
+	{
+		return char_traits::eof();
+	}
+
+	int_type _pb;
+	bool     _ispb;
+	
+	BasicUnbufferedStreamBuf(const BasicUnbufferedStreamBuf&);
+	BasicUnbufferedStreamBuf& operator = (const BasicUnbufferedStreamBuf&);
+};
+
+
+//
+// We provide an instantiation for char.
+//
+// Visual C++ needs a workaround - explicitly importing the template
+// instantiation - to avoid duplicate symbols due to multiple
+// instantiations in different libraries.
+//
+#if defined(_MSC_VER) && defined(POCO_DLL) && !defined(Foundation_EXPORTS)
+template class Foundation_API BasicUnbufferedStreamBuf<char, std::char_traits<char> >;
+#endif
+typedef BasicUnbufferedStreamBuf<char, std::char_traits<char> > UnbufferedStreamBuf;
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UnbufferedStreamBuf_INCLUDED
diff --git a/Poco/Unicode.h b/Poco/Unicode.h
new file mode 100644
index 0000000..b6d0276
--- /dev/null
+++ b/Poco/Unicode.h
@@ -0,0 +1,327 @@
+//
+// Unicode.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Unicode
+//
+// Definition of the Unicode class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Unicode_INCLUDED
+#define Foundation_Unicode_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Unicode
+	/// This class contains enumerations and static
+	/// utility functions for dealing with Unicode characters
+	/// and their properties.
+	///
+	/// For more information on Unicode, see <http://www.unicode.org>.
+	///
+	/// The implementation is based on the Unicode support
+	/// functions in PCRE.
+{
+public:
+	// Implementation note: the following definitions must be kept
+	// in sync with those from ucp.h (PCRE).
+	enum CharacterCategory
+		/// Unicode character categories.
+	{
+		UCP_OTHER,
+		UCP_LETTER,
+		UCP_MARK,
+		UCP_NUMBER,
+		UCP_PUNCTUATION,
+		UCP_SYMBOL,
+		UCP_SEPARATOR
+	};
+
+	enum CharacterType
+		/// Unicode character types.
+	{
+		UCP_CONTROL,
+		UCP_FORMAT,
+		UCP_UNASSIGNED,
+		UCP_PRIVATE_USE,
+		UCP_SURROGATE,
+		UCP_LOWER_CASE_LETTER,
+		UCP_MODIFIER_LETTER,
+		UCP_OTHER_LETTER,
+		UCP_TITLE_CASE_LETTER,
+		UCP_UPPER_CASE_LETTER,
+		UCP_SPACING_MARK,
+		UCP_ENCLOSING_MARK,
+		UCP_NON_SPACING_MARK,
+		UCP_DECIMAL_NUMBER,
+		UCP_LETTER_NUMBER,
+		UCP_OTHER_NUMBER,
+		UCP_CONNECTOR_PUNCTUATION,
+		UCP_DASH_PUNCTUATION,
+		UCP_CLOSE_PUNCTUATION,
+		UCP_FINAL_PUNCTUATION,
+		UCP_INITIAL_PUNCTUATION,
+		UCP_OTHER_PUNCTUATION,
+		UCP_OPEN_PUNCTUATION,
+		UCP_CURRENCY_SYMBOL,
+		UCP_MODIFIER_SYMBOL,
+		UCP_MATHEMATICAL_SYMBOL,
+		UCP_OTHER_SYMBOL,
+		UCP_LINE_SEPARATOR,
+		UCP_PARAGRAPH_SEPARATOR,
+		UCP_SPACE_SEPARATOR
+	};
+	
+	enum Script
+		/// Unicode 7.0 script identifiers.
+	{
+		UCP_ARABIC,
+		UCP_ARMENIAN,
+		UCP_BENGALI,
+		UCP_BOPOMOFO,
+		UCP_BRAILLE,
+		UCP_BUGINESE,
+		UCP_BUHID,
+		UCP_CANADIAN_ABORIGINAL,
+		UCP_CHEROKEE,
+		UCP_COMMON,
+		UCP_COPTIC,
+		UCP_CYPRIOT,
+		UCP_CYRILLIC,
+		UCP_DESERET,
+		UCP_DEVANAGARI,
+		UCP_ETHIOPIC,
+		UCP_GEORGIAN,
+		UCP_GLAGOLITIC,
+		UCP_GOTHIC,
+		UCP_GREEK,
+		UCP_GUJARATI,
+		UCP_GURMUKHI,
+		UCP_HAN,
+		UCP_HANGUL,
+		UCP_HANUNOO,
+		UCP_HEBREW,
+		UCP_HIRAGANA,
+		UCP_INHERITED,
+		UCP_KANNADA,
+		UCP_KATAKANA,
+		UCP_KHAROSHTHI,
+		UCP_KHMER,
+		UCP_LAO,
+		UCP_LATIN,
+		UCP_LIMBU,
+		UCP_LINEAR_B,
+		UCP_MALAYALAM,
+		UCP_MONGOLIAN,
+		UCP_MYANMAR,
+		UCP_NEW_TAI_LUE,
+		UCP_OGHAM,
+		UCP_OLD_ITALIC,
+		UCP_OLD_PERSIAN,
+		UCP_ORIYA,
+		UCP_OSMANYA,
+		UCP_RUNIC,
+		UCP_SHAVIAN,
+		UCP_SINHALA,
+		UCP_SYLOTI_NAGRI,
+		UCP_SYRIAC,
+		UCP_TAGALOG,
+		UCP_TAGBANWA,
+		UCP_TAI_LE,
+		UCP_TAMIL,
+		UCP_TELUGU,
+		UCP_THAANA,
+		UCP_THAI,
+		UCP_TIBETAN,
+		UCP_TIFINAGH,
+		UCP_UGARITIC,
+		UCP_YI,
+		// Unicode 5.0
+		UCP_BALINESE,
+		UCP_CUNEIFORM,
+		UCP_NKO,
+		UCP_PHAGS_PA,
+		UCP_PHOENICIAN,
+		// Unicode 5.1
+		UCP_CARIAN,
+		UCP_CHAM,
+		UCP_KAYAH_LI,
+		UCP_LEPCHA,
+		UCP_LYCIAN,
+		UCP_LYDIAN,
+		UCP_OL_CHIKI,
+		UCP_REJANG,
+		UCP_SAURASHTRA,
+		UCP_SUNDANESE,
+		UCP_VAI,
+		// Unicode 5.2
+		UCP_AVESTAN,
+		UCP_BAMUM,
+		UCP_EGYPTIAN_HIEROGLYPHS,
+		UCP_IMPERIAL_ARAMAIC,
+		UCP_INSCRIPTIONAL_PAHLAVI,
+		UCP_INSCRIPTIONAL_PARTHIAN,
+		UCP_JAVANESE,
+		UCP_KAITHI,
+		UCP_LISU,
+		UCP_MEETEI_MAYEK,
+		UCP_OLD_SOUTH_ARABIAN,
+		UCP_OLD_TURKIC,
+		UCP_SAMARITAN,
+		UCP_TAI_THAM,
+		UCP_TAI_VIET,
+		// Unicode 6.0
+		UCP_BATAK,
+		UCP_BRAHMI,
+		UCP_MANDAIC,
+		// Unicode 6.1
+		UCP_CHAKMA,
+		UCP_MEROITIC_CURSIVE,
+		UCP_MEROITIC_HIEROGLYPHS,
+		UCP_MIAO,
+		UCP_SHARADA,
+		UCP_SORA_SOMPENG,
+		UCP_TAKRI,
+		// Unicode 7.0
+		UCP_BASSA_VAH,
+		UCP_CAUCASIAN_ALBANIAN,
+		UCP_DUPLOYAN,
+		UCP_ELBASAN,
+		UCP_GRANTHA,
+		UCP_KHOJKI,
+		UCP_KHUDAWADI,
+		UCP_LINEAR_A,
+		UCP_MAHAJANI,
+		UCP_MANICHAEAN,
+		UCP_MENDE_KIKAKUI,
+		UCP_MODI,
+		UCP_MRO,
+		UCP_NABATAEAN,
+		UCP_OLD_NORTH_ARABIAN,
+		UCP_OLD_PERMIC,
+		UCP_PAHAWH_HMONG,
+		UCP_PALMYRENE,
+		UCP_PSALTER_PAHLAVI,
+		UCP_PAU_CIN_HAU,
+		UCP_SIDDHAM,
+		UCP_TIRHUTA,
+		UCP_WARANG_CITI
+	};
+	
+	enum
+	{
+		UCP_MAX_CODEPOINT = 0x10FFFF
+	};
+	
+	struct CharacterProperties
+		/// This structure holds the character properties
+		/// of an Unicode character.
+	{
+		CharacterCategory category;
+		CharacterType     type;
+		Script            script;
+	};
+
+	static void properties(int ch, CharacterProperties& props);
+		/// Return the Unicode character properties for the
+		/// character with the given Unicode value.
+		
+	static bool isSpace(int ch);
+		/// Returns true iff the given character is a separator.
+		
+	static bool isDigit(int ch);
+		/// Returns true iff the given character is a numeric character.
+		
+	static bool isPunct(int ch);
+		/// Returns true iff the given character is a punctuation character.
+		
+	static bool isAlpha(int ch);
+		/// Returns true iff the given character is a letter.	
+		
+	static bool isLower(int ch);
+		/// Returns true iff the given character is a lowercase
+		/// character.
+		
+	static bool isUpper(int ch);
+		/// Returns true iff the given character is an uppercase
+		/// character.
+		
+	static int toLower(int ch);
+		/// If the given character is an uppercase character,
+		/// return its lowercase counterpart, otherwise return
+		/// the character.
+
+	static int toUpper(int ch);
+		/// If the given character is a lowercase character,
+		/// return its uppercase counterpart, otherwise return
+		/// the character.
+};
+
+
+//
+// inlines
+//
+inline bool Unicode::isSpace(int ch)
+{
+	CharacterProperties props;
+	properties(ch, props);
+	return props.category == UCP_SEPARATOR;
+}
+
+
+inline bool Unicode::isDigit(int ch)
+{
+	CharacterProperties props;
+	properties(ch, props);
+	return props.category == UCP_NUMBER;
+}
+
+
+inline bool Unicode::isPunct(int ch)
+{
+	CharacterProperties props;
+	properties(ch, props);
+	return props.category == UCP_PUNCTUATION;
+}
+
+
+inline bool Unicode::isAlpha(int ch)
+{
+	CharacterProperties props;
+	properties(ch, props);
+	return props.category == UCP_LETTER;
+}
+
+
+inline bool Unicode::isLower(int ch)
+{
+	CharacterProperties props;
+	properties(ch, props);
+	return props.category == UCP_LETTER && props.type == UCP_LOWER_CASE_LETTER;
+}
+
+	
+inline bool Unicode::isUpper(int ch)
+{
+	CharacterProperties props;
+	properties(ch, props);
+	return props.category == UCP_LETTER && props.type == UCP_UPPER_CASE_LETTER;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Unicode_INCLUDED
diff --git a/Poco/UnicodeConverter.h b/Poco/UnicodeConverter.h
new file mode 100644
index 0000000..0733b67
--- /dev/null
+++ b/Poco/UnicodeConverter.h
@@ -0,0 +1,141 @@
+//
+// UnicodeConverter.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  UnicodeConverter
+//
+// Definition of the UnicodeConverter class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UnicodeConverter_INCLUDED
+#define Foundation_UnicodeConverter_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/UTFString.h"
+
+
+namespace Poco {
+
+
+class Foundation_API UnicodeConverter
+	/// A convenience class that converts strings from
+	/// UTF-8 encoded std::strings to UTF-16 or UTF-32 encoded std::wstrings
+	/// and vice-versa.
+	///
+	/// This class is mainly used for working with the Unicode Windows APIs
+	/// and probably won't be of much use anywhere else ???
+{
+public:
+	static void convert(const std::string& utf8String, UTF32String& utf32String);
+		/// Converts the given UTF-8 encoded string into an UTF-32 encoded wide string.
+
+	static void convert(const char* utf8String,  std::size_t length, UTF32String& utf32String);
+		/// Converts the given UTF-8 encoded character sequence into an UTF-32 encoded wide string.
+
+	static void convert(const char* utf8String, UTF32String& utf32String);
+		/// Converts the given zero-terminated UTF-8 encoded character sequence into an UTF-32 encoded wide string.
+
+	static void convert(const std::string& utf8String, UTF16String& utf16String);
+		/// Converts the given UTF-8 encoded string into an UTF-16 encoded wide string.
+
+	static void convert(const char* utf8String,  std::size_t length, UTF16String& utf16String);	
+		/// Converts the given UTF-8 encoded character sequence into an UTF-16 encoded wide string.
+
+	static void convert(const char* utf8String, UTF16String& utf16String);	
+		/// Converts the given zero-terminated UTF-8 encoded character sequence into an UTF-16 encoded wide string.
+
+	static void convert(const UTF16String& utf16String, std::string& utf8String);
+		/// Converts the given UTF-16 encoded wide string into an UTF-8 encoded string.
+
+	static void convert(const UTF32String& utf32String, std::string& utf8String);
+		/// Converts the given UTF-32 encoded wide string into an UTF-8 encoded string.
+
+	static void convert(const UTF16Char* utf16String,  std::size_t length, std::string& utf8String);
+		/// Converts the given zero-terminated UTF-16 encoded wide character sequence into an UTF-8 encoded string.
+
+	static void convert(const UTF32Char* utf16String, std::size_t length, std::string& utf8String);
+		/// Converts the given zero-terminated UTF-32 encoded wide character sequence into an UTF-8 encoded string.
+
+	static void convert(const UTF16Char* utf16String, std::string& utf8String);
+		/// Converts the given UTF-16 encoded zero terminated character sequence into an UTF-8 encoded string.
+
+	static void convert(const UTF32Char* utf32String, std::string& utf8String);
+		/// Converts the given UTF-32 encoded zero terminated character sequence into an UTF-8 encoded string.
+
+	template <typename F, typename T>
+	static void toUTF32(const F& f, T& t)
+	{
+		convert(f, t);
+	}
+
+	template <typename F, typename T>
+	static void toUTF32(const F& f, std::size_t l, T& t)
+	{
+		convert(f, l, t);
+	}
+
+	template <typename F, typename T>
+	static void toUTF16(const F& f, T& t)
+	{
+		convert(f, t);
+	}
+
+	template <typename F, typename T>
+	static void toUTF16(const F& f, std::size_t l, T& t)
+	{
+		convert(f, l, t);
+	}
+
+	template <typename F, typename T>
+	static void toUTF8(const F& f, T& t)
+	{
+		convert(f, t);
+	}
+
+	template <typename F, typename T>
+	static void toUTF8(const F& f, std::size_t l, T& t)
+	{
+		convert(f, l, t);
+	}
+
+	template <typename T>
+	static T to(const char* pChar)
+	{
+		T utfStr;
+		Poco::UnicodeConverter::convert(pChar, utfStr);
+		return utfStr;
+	}
+
+
+	template <typename T>
+	static T to(const std::string& str)
+	{
+		T utfStr;
+		Poco::UnicodeConverter::convert(str, utfStr);
+		return utfStr;
+	}
+
+	template <typename T>
+	static std::size_t UTFStrlen(const T* ptr)
+		/// Returns the length (in characters) of a zero-terminated UTF string.
+	{
+		if (ptr == 0) return 0;
+		const T* p;
+		for (p = ptr; *p; ++p);
+		return p - ptr;
+	}
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UnicodeConverter_INCLUDED
diff --git a/Poco/UniqueAccessExpireCache.h b/Poco/UniqueAccessExpireCache.h
new file mode 100644
index 0000000..a2d58f6
--- /dev/null
+++ b/Poco/UniqueAccessExpireCache.h
@@ -0,0 +1,73 @@
+//
+// UniqueAccessExpireCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  UniqueAccessExpireCache
+//
+// Definition of the UniqueAccessExpireCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UniqueAccessExpireCache_INCLUDED
+#define Foundation_UniqueAccessExpireCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/UniqueAccessExpireStrategy.h"
+
+
+namespace Poco {
+
+
+template <
+	class TKey, 
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+> 
+class UniqueAccessExpireCache: public AbstractCache<TKey, TValue, UniqueAccessExpireStrategy<TKey, TValue>, TMutex, TEventMutex>
+	/// An UniqueAccessExpireCache caches entries for a given time span. In contrast
+	/// to ExpireCache which only allows to set a per cache expiration value, it allows to define 
+	/// expiration per CacheEntry.
+	/// Each TValue object must thus offer the following method:
+	///    
+	///    const Poco::Timespan& getTimeout() const;
+	///    
+	/// which returns the relative timespan for how long the entry should be valid without being accessed!
+	/// The absolute expire timepoint is calculated as now() + getTimeout().
+	/// Accessing an object will update this absolute expire timepoint.
+	/// You can use the Poco::AccessExpirationDecorator to add the getExpiration
+	/// method to values that do not have a getExpiration function.
+	///
+	/// Be careful when using an UniqueAccessExpireCache. A cache is often used
+	/// like cache.has(x) followed by cache.get x). Note that it could happen
+	/// that the "has" call works, then the current execution thread gets descheduled, time passes,
+	/// the entry gets invalid, thus leading to an empty SharedPtr being returned 
+	/// when "get" is invoked.
+{
+public:
+	UniqueAccessExpireCache():
+		AbstractCache<TKey, TValue, UniqueAccessExpireStrategy<TKey, TValue>, TMutex, TEventMutex>(UniqueAccessExpireStrategy<TKey, TValue>())
+	{
+	}
+
+	~UniqueAccessExpireCache()
+	{
+	}
+
+private:
+	UniqueAccessExpireCache(const UniqueAccessExpireCache& aCache);
+	UniqueAccessExpireCache& operator = (const UniqueAccessExpireCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UniqueAccessExpireCache_INCLUDED
diff --git a/Poco/UniqueAccessExpireLRUCache.h b/Poco/UniqueAccessExpireLRUCache.h
new file mode 100644
index 0000000..6e7a366
--- /dev/null
+++ b/Poco/UniqueAccessExpireLRUCache.h
@@ -0,0 +1,71 @@
+//
+// UniqueAccessExpireLRUCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  UniqueAccessExpireLRUCache
+//
+// Definition of the UniqueAccessExpireLRUCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UniqueAccessExpireLRUCache_INCLUDED
+#define Foundation_UniqueAccessExpireLRUCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/StrategyCollection.h"
+#include "Poco/UniqueAccessExpireStrategy.h"
+#include "Poco/LRUStrategy.h"
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+>
+class UniqueAccessExpireLRUCache: public AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>
+	/// A UniqueAccessExpireLRUCache combines LRU caching and time based per entry expire caching.
+	/// One can define for each cache entry a seperate timepoint
+	/// but also limit the size of the cache (per default: 1024).
+	/// Each TValue object must thus offer the following method:
+	///    
+	///    const Poco::Timespan& getTimeout() const;
+	///    
+	/// which returns the relative timespan for how long the entry should be valid without being accessed!
+	/// The absolute expire timepoint is calculated as now() + getTimeout().
+	/// Accessing an object will update this absolute expire timepoint.
+	/// You can use the Poco::AccessExpirationDecorator to add the getExpiration
+	/// method to values that do not have a getExpiration function.
+{
+public:
+	UniqueAccessExpireLRUCache(long cacheSize = 1024): 
+		AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>(StrategyCollection<TKey, TValue>())
+	{
+		this->_strategy.pushBack(new LRUStrategy<TKey, TValue>(cacheSize));
+		this->_strategy.pushBack(new UniqueAccessExpireStrategy<TKey, TValue>());
+	}
+
+	~UniqueAccessExpireLRUCache()
+	{
+	}
+
+private:
+	UniqueAccessExpireLRUCache(const UniqueAccessExpireLRUCache& aCache);
+	UniqueAccessExpireLRUCache& operator = (const UniqueAccessExpireLRUCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UniqueAccessExpireLRUCache_INCLUDED
diff --git a/Poco/UniqueAccessExpireStrategy.h b/Poco/UniqueAccessExpireStrategy.h
new file mode 100644
index 0000000..d20f218
--- /dev/null
+++ b/Poco/UniqueAccessExpireStrategy.h
@@ -0,0 +1,156 @@
+//
+// UniqueAccessExpireStrategy.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  UniqueAccessExpireStrategy
+//
+// Definition of the UniqueAccessExpireStrategy class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UniqueAccessExpireStrategy_INCLUDED
+#define Foundation_UniqueAccessExpireStrategy_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/AbstractStrategy.h"
+#include "Poco/Bugcheck.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Timespan.h"
+#include "Poco/EventArgs.h"
+#include "Poco/UniqueExpireStrategy.h"
+#include <set>
+#include <map>
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue
+>
+class UniqueAccessExpireStrategy: public AbstractStrategy<TKey, TValue>
+	/// An UniqueExpireStrategy implements time based expiration of cache entries. In contrast
+	/// to ExpireStrategy which only allows to set a per cache expiration value, it allows to define 
+	/// expiration per CacheEntry.
+	/// Each TValue object must thus offer the following method:
+	///    
+	///    const Poco::Timestamp& getTimeout() const;
+	///    
+	/// which returns the timespan for how long an object will be valid without being accessed.
+{
+public:
+	typedef std::pair<TKey, Timespan>           KeyExpire;
+	typedef std::multimap<Timestamp, KeyExpire> TimeIndex;
+	typedef typename TimeIndex::iterator        IndexIterator;
+	typedef typename TimeIndex::const_iterator  ConstIndexIterator;
+	typedef std::map<TKey, IndexIterator>       Keys;
+	typedef typename Keys::iterator             Iterator;
+
+public:
+	UniqueAccessExpireStrategy()
+		/// Create an unique expire strategy.
+	{
+	}
+
+	~UniqueAccessExpireStrategy()
+	{
+	}
+
+	void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
+	{
+		// the expire value defines how many millisecs in the future the
+		// value will expire, even insert negative values!
+		Timestamp expire;
+		expire += args.value().getTimeout().totalMicroseconds();
+		
+		IndexIterator it = _keyIndex.insert(std::make_pair(expire, std::make_pair(args.key(), args.value().getTimeout())));
+		std::pair<Iterator, bool> stat = _keys.insert(std::make_pair(args.key(), it));
+		if (!stat.second)
+		{
+			_keyIndex.erase(stat.first->second);
+			stat.first->second = it;
+		}
+	}
+
+	void onRemove(const void*, const TKey& key)
+	{
+		Iterator it = _keys.find(key);
+		if (it != _keys.end())
+		{
+			_keyIndex.erase(it->second);
+			_keys.erase(it);
+		}
+	}
+
+	void onGet(const void*, const TKey& key)
+	{
+		// get updates the expiration time stamp
+		Iterator it = _keys.find(key);
+		if (it != _keys.end())
+		{
+			KeyExpire ke = it->second->second;
+			// gen new absolute expire value
+			Timestamp expire;
+			expire += ke.second.totalMicroseconds();
+			// delete old index
+			_keyIndex.erase(it->second);
+			IndexIterator itt = _keyIndex.insert(std::make_pair(expire, ke));
+			// update iterator
+			it->second = itt;
+		}
+	}
+
+	void onClear(const void*, const EventArgs& args)
+	{
+		_keys.clear();
+		_keyIndex.clear();
+	}
+
+	void onIsValid(const void*, ValidArgs<TKey>& args)
+	{
+		Iterator it = _keys.find(args.key());
+		if (it != _keys.end())
+		{
+			Timestamp now;
+			if (it->second->first <= now)
+			{
+				args.invalidate();
+			}
+		}
+		else //not found: probably removed by onReplace
+			args.invalidate();
+	}
+
+	void onReplace(const void*, std::set<TKey>& elemsToRemove)
+	{
+		// Note: replace only informs the cache which elements
+		// it would like to remove!
+		// it does not remove them on its own!
+		IndexIterator it = _keyIndex.begin();
+		Timestamp now;
+		while (it != _keyIndex.end() && it->first < now)
+		{
+			elemsToRemove.insert(it->second.first);
+			++it;
+		}
+	}
+
+protected:
+	Keys      _keys;     /// For faster replacement of keys, the iterator points to the _keyIndex map
+	TimeIndex _keyIndex; /// Maps time to key value
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UniqueAccessExpireStrategy_INCLUDED
diff --git a/Poco/UniqueExpireCache.h b/Poco/UniqueExpireCache.h
new file mode 100644
index 0000000..613f9e2
--- /dev/null
+++ b/Poco/UniqueExpireCache.h
@@ -0,0 +1,72 @@
+//
+// UniqueExpireCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  UniqueExpireCache
+//
+// Definition of the UniqueExpireCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UniqueExpireCache_INCLUDED
+#define Foundation_UniqueExpireCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/UniqueExpireStrategy.h"
+
+
+namespace Poco {
+
+
+template <
+	class TKey, 
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+> 
+class UniqueExpireCache: public AbstractCache<TKey, TValue, UniqueExpireStrategy<TKey, TValue>, TMutex, TEventMutex>
+	/// An UniqueExpireCache caches entries for a given time amount. In contrast
+	/// to ExpireCache which only allows to set a per cache expiration value, it allows to define 
+	/// expiration per CacheEntry.
+	/// Each TValue object must thus offer the following method:
+	///    
+	///    const Poco::Timestamp& getExpiration() const;
+	///    
+	/// which returns the absolute timepoint when the entry will be invalidated.
+	/// Accessing an object will NOT update this absolute expire timepoint.
+	/// You can use the Poco::ExpirationDecorator to add the getExpiration
+	/// method to values that do not have a getExpiration function.
+	///
+	/// Be careful when using an UniqueExpireCache. A cache is often used
+	/// like cache.has(x) followed by cache.get x). Note that it could happen
+	/// that the "has" call works, then the current execution thread gets descheduled, time passes,
+	/// the entry gets invalid, thus leading to an empty SharedPtr being returned 
+	/// when "get" is invoked.
+{
+public:
+	UniqueExpireCache():
+		AbstractCache<TKey, TValue, UniqueExpireStrategy<TKey, TValue>, TMutex, TEventMutex>(UniqueExpireStrategy<TKey, TValue>())
+	{
+	}
+
+	~UniqueExpireCache()
+	{
+	}
+
+private:
+	UniqueExpireCache(const UniqueExpireCache& aCache);
+	UniqueExpireCache& operator = (const UniqueExpireCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UniqueExpireCache_INCLUDED
diff --git a/Poco/UniqueExpireLRUCache.h b/Poco/UniqueExpireLRUCache.h
new file mode 100644
index 0000000..c59bf0f
--- /dev/null
+++ b/Poco/UniqueExpireLRUCache.h
@@ -0,0 +1,70 @@
+//
+// UniqueExpireLRUCache.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  UniqueExpireLRUCache
+//
+// Definition of the UniqueExpireLRUCache class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UniqueExpireLRUCache_INCLUDED
+#define Foundation_UniqueExpireLRUCache_INCLUDED
+
+
+#include "Poco/AbstractCache.h"
+#include "Poco/StrategyCollection.h"
+#include "Poco/UniqueExpireStrategy.h"
+#include "Poco/LRUStrategy.h"
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue,
+	class TMutex = FastMutex, 
+	class TEventMutex = FastMutex
+>
+class UniqueExpireLRUCache: public AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>
+	/// A UniqueExpireLRUCache combines LRU caching and time based per entry expire caching.
+	/// One can define for each cache entry a seperate timepoint
+	/// but also limit the size of the cache (per default: 1024).
+	/// Each TValue object must thus offer the following method:
+	///    
+	///    const Poco::Timestamp& getExpiration() const;
+	///    
+	/// which returns the absolute timepoint when the entry will be invalidated.
+	/// Accessing an object will NOT update this absolute expire timepoint.
+	/// You can use the Poco::ExpirationDecorator to add the getExpiration
+	/// method to values that do not have a getExpiration function.
+{
+public:
+	UniqueExpireLRUCache(long cacheSize = 1024): 
+		AbstractCache<TKey, TValue, StrategyCollection<TKey, TValue>, TMutex, TEventMutex>(StrategyCollection<TKey, TValue>())
+	{
+		this->_strategy.pushBack(new LRUStrategy<TKey, TValue>(cacheSize));
+		this->_strategy.pushBack(new UniqueExpireStrategy<TKey, TValue>());
+	}
+
+	~UniqueExpireLRUCache()
+	{
+	}
+
+private:
+	UniqueExpireLRUCache(const UniqueExpireLRUCache& aCache);
+	UniqueExpireLRUCache& operator = (const UniqueExpireLRUCache& aCache);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UniqueExpireLRUCache_INCLUDED
diff --git a/Poco/UniqueExpireStrategy.h b/Poco/UniqueExpireStrategy.h
new file mode 100644
index 0000000..6ae7994
--- /dev/null
+++ b/Poco/UniqueExpireStrategy.h
@@ -0,0 +1,138 @@
+//
+// UniqueExpireStrategy.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  UniqueExpireStrategy
+//
+// Definition of the UniqueExpireStrategy class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_UniqueExpireStrategy_INCLUDED
+#define Foundation_UniqueExpireStrategy_INCLUDED
+
+
+#include "Poco/KeyValueArgs.h"
+#include "Poco/ValidArgs.h"
+#include "Poco/AbstractStrategy.h"
+#include "Poco/Bugcheck.h"
+#include "Poco/Timestamp.h"
+#include "Poco/EventArgs.h"
+#include <set>
+#include <map>
+
+
+namespace Poco {
+
+
+template < 
+	class TKey,
+	class TValue
+>
+class UniqueExpireStrategy: public AbstractStrategy<TKey, TValue>
+	/// An UniqueExpireStrategy implements time based expiration of cache entries. In contrast
+	/// to ExpireStrategy which only allows to set a per cache expiration value, it allows to define 
+	/// expiration per CacheEntry.
+	/// Each TValue object must thus offer the following method:
+	///    
+	///    const Poco::Timestamp& getExpiration() const;
+	///    
+	/// which returns the absolute timepoint when the entry will be invalidated.
+{
+public:
+	typedef std::multimap<Timestamp, TKey>     TimeIndex;
+	typedef typename TimeIndex::iterator       IndexIterator;
+	typedef typename TimeIndex::const_iterator ConstIndexIterator;
+	typedef std::map<TKey, IndexIterator>      Keys;
+	typedef typename Keys::iterator            Iterator;
+
+public:
+	UniqueExpireStrategy()
+		/// Create an unique expire strategy.
+	{
+	}
+
+	~UniqueExpireStrategy()
+	{
+	}
+
+	void onAdd(const void*, const KeyValueArgs <TKey, TValue>& args)
+	{
+		// note: we have to insert even if the expire timepoint is in the past (for StrategyCollection classes to avoid inconsistency with LRU)
+		// no problem: will be removed with next get
+		const Timestamp& expire = args.value().getExpiration();
+		IndexIterator it = _keyIndex.insert(std::make_pair(expire, args.key()));
+		std::pair<Iterator, bool> stat = _keys.insert(std::make_pair(args.key(), it));
+		if (!stat.second)
+		{
+			_keyIndex.erase(stat.first->second);
+			stat.first->second = it;
+		}
+	}
+
+	void onRemove(const void*, const TKey& key)
+	{
+		Iterator it = _keys.find(key);
+		if (it != _keys.end())
+		{
+			_keyIndex.erase(it->second);
+			_keys.erase(it);
+		}
+	}
+
+	void onGet(const void*, const TKey& key)
+	{
+		// get triggers no changes in an expire
+	}
+
+	void onClear(const void*, const EventArgs& args)
+	{
+		_keys.clear();
+		_keyIndex.clear();
+	}
+
+	void onIsValid(const void*, ValidArgs<TKey>& args)
+	{
+		Iterator it = _keys.find(args.key());
+		if (it != _keys.end())
+		{
+			Timestamp now;
+			if (it->second->first <= now)
+			{
+				args.invalidate();
+			}
+		}
+		else //not found: probably removed by onReplace
+			args.invalidate();
+	}
+
+	void onReplace(const void*, std::set<TKey>& elemsToRemove)
+	{
+		// Note: replace only informs the cache which elements
+		// it would like to remove!
+		// it does not remove them on its own!
+		IndexIterator it = _keyIndex.begin();
+		Timestamp now;
+		while (it != _keyIndex.end() && it->first < now)
+		{
+			elemsToRemove.insert(it->second);
+			++it;
+		}
+	}
+
+protected:
+	Keys      _keys;     /// For faster replacement of keys, the iterator points to the _keyIndex map
+	TimeIndex _keyIndex; /// Maps time to key value
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_UniqueExpireStrategy_INCLUDED
diff --git a/Poco/Util/AbstractConfiguration.h b/Poco/Util/AbstractConfiguration.h
new file mode 100644
index 0000000..277c6d7
--- /dev/null
+++ b/Poco/Util/AbstractConfiguration.h
@@ -0,0 +1,381 @@
+//
+// AbstractConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  AbstractConfiguration
+//
+// Definition of the AbstractConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_AbstractConfiguration_INCLUDED
+#define Util_AbstractConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Mutex.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/BasicEvent.h"
+#include <vector>
+#include <utility>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API AbstractConfiguration: public Poco::RefCountedObject
+	/// AbstractConfiguration is an abstract base class for different
+	/// kinds of configuration data, such as INI files, property files,
+	/// XML configuration files or the Windows Registry.
+	///
+	/// Configuration property keys have a hierarchical format, consisting
+	/// of names separated by periods. The exact interpretation of key names
+	/// is up to the actual subclass implementation of AbstractConfiguration.
+	/// Keys are case sensitive.
+	///
+	/// All public methods are synchronized, so the class is safe for multithreaded use.
+	/// AbstractConfiguration implements reference counting based garbage collection.
+	///
+	/// Subclasses must override the getRaw(), setRaw() and enumerate() methods.
+{
+public:
+	typedef std::vector<std::string> Keys;
+	
+	class KeyValue
+		/// A key-value pair, used as event argument.
+	{
+	public:
+		KeyValue(const std::string& key, std::string& value):
+			_key(key),
+			_value(value)
+		{
+		}
+		
+		const std::string& key() const
+		{
+			return _key;
+		}
+		
+		const std::string& value() const
+		{
+			return _value;
+		}
+		
+		std::string& value()
+		{
+			return _value;
+		}
+	
+	private:
+		const std::string& _key;
+		std::string& _value;
+	};
+	
+	Poco::BasicEvent<KeyValue> propertyChanging;
+		/// Fired before a property value is changed or
+		/// a new property is created.
+		///
+		/// Can be used to check or fix a property value,
+		/// or to cancel the change by throwing an exception.
+		///
+		/// The event delegate can use one of the get...() functions
+		/// to obtain the current property value.
+
+	Poco::BasicEvent<const KeyValue> propertyChanged;
+		/// Fired after a property value has been changed
+		/// or a property has been created.
+
+	Poco::BasicEvent<const std::string> propertyRemoving;
+		/// Fired before a property is removed by a
+		/// call to remove().
+		///
+		/// Note: This will even be fired if the key
+		/// does not exist and the remove operation will
+		/// fail with an exception.
+		
+	Poco::BasicEvent<const std::string> propertyRemoved;
+		/// Fired after a property has been removed by
+		/// a call to remove().
+
+	AbstractConfiguration();
+		/// Creates the AbstractConfiguration.
+
+	bool hasProperty(const std::string& key) const;
+		/// Returns true iff the property with the given key exists.
+
+	bool hasOption(const std::string& key) const;
+		/// Returns true iff the property with the given key exists.
+		///
+		/// Same as hasProperty().
+
+	bool has(const std::string& key) const;
+		/// Returns true iff the property with the given key exists.
+		///
+		/// Same as hasProperty().
+		
+	std::string getString(const std::string& key) const;
+		/// Returns the string value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	std::string getString(const std::string& key, const std::string& defaultValue) const;
+		/// If a property with the given key exists, returns the property's string value,
+		/// otherwise returns the given default value.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+	std::string getRawString(const std::string& key) const;
+		/// Returns the raw string value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// References to other properties are not expanded.
+		
+	std::string getRawString(const std::string& key, const std::string& defaultValue) const;
+		/// If a property with the given key exists, returns the property's raw string value,
+		/// otherwise returns the given default value.
+		/// References to other properties are not expanded.
+		
+	int getInt(const std::string& key) const;
+		/// Returns the int value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an int.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	unsigned int getUInt(const std::string& key) const;
+		/// Returns the unsigned int value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an unsigned int.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	int getInt(const std::string& key, int defaultValue) const;
+		/// If a property with the given key exists, returns the property's int value,
+		/// otherwise returns the given default value.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an int.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	unsigned int getUInt(const std::string& key, unsigned int defaultValue) const;
+		/// If a property with the given key exists, returns the property's unsigned int
+		/// value, otherwise returns the given default value.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an unsigned int.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+#if defined(POCO_HAVE_INT64)
+
+	Int64 getInt64(const std::string& key) const;
+		/// Returns the Int64 value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an Int64.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+	UInt64 getUInt64(const std::string& key) const;
+		/// Returns the UInt64 value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an UInt64.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+	Int64 getInt64(const std::string& key, Int64 defaultValue) const;
+		/// If a property with the given key exists, returns the property's Int64 value,
+		/// otherwise returns the given default value.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an Int64.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+	UInt64 getUInt64(const std::string& key, UInt64 defaultValue) const;
+		/// If a property with the given key exists, returns the property's UInt64
+		/// value, otherwise returns the given default value.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an UInt64.
+		/// Numbers starting with 0x are treated as hexadecimal.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+#endif // defined(POCO_HAVE_INT64)
+
+	double getDouble(const std::string& key) const;
+		/// Returns the double value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to a double.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	double getDouble(const std::string& key, double defaultValue) const;
+		/// If a property with the given key exists, returns the property's double value,
+		/// otherwise returns the given default value.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to an double.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+
+	bool getBool(const std::string& key) const;
+		/// Returns the boolean value of the property with the given name.
+		/// Throws a NotFoundException if the key does not exist.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to a boolean.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	bool getBool(const std::string& key, bool defaultValue) const;
+		/// If a property with the given key exists, returns the property's boolean value,
+		/// otherwise returns the given default value.
+		/// Throws a SyntaxException if the property can not be converted
+		/// to a boolean.
+		/// The following string values can be converted into a boolean:
+		///   - numerical values: non zero becomes true, zero becomes false
+		///   - strings: true, yes, on become true, false, no, off become false
+		/// Case does not matter.
+		/// If the value contains references to other properties (${<property>}), these
+		/// are expanded.
+		
+	virtual void setString(const std::string& key, const std::string& value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+		
+	virtual void setInt(const std::string& key, int value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+		
+	virtual void setUInt(const std::string& key, unsigned int value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+
+#if defined(POCO_HAVE_INT64)
+
+	virtual void setInt64(const std::string& key, Int64 value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+
+	virtual void setUInt64(const std::string& key, UInt64 value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+
+#endif // defined(POCO_HAVE_INT64)
+
+	virtual void setDouble(const std::string& key, double value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+
+	virtual void setBool(const std::string& key, bool value);
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+		
+	void keys(Keys& range) const;
+		/// Returns in range the names of all keys at root level.
+
+	void keys(const std::string& key, Keys& range) const;
+		/// Returns in range the names of all subkeys under the given key.
+		/// If an empty key is passed, all root level keys are returned.
+	
+	const AbstractConfiguration* createView(const std::string& prefix) const;
+		/// Creates a non-mutable view (see ConfigurationView) into the configuration.
+
+	AbstractConfiguration* createView(const std::string& prefix);
+		/// Creates a view (see ConfigurationView) into the configuration.
+	
+	std::string expand(const std::string& value) const;
+		/// Replaces all occurrences of ${<property>} in value with the
+		/// value of the <property>. If <property> does not exist,
+		/// nothing is changed.
+		///
+		/// If a circular property reference is detected, a
+		/// CircularReferenceException will be thrown.
+
+	void remove(const std::string& key);
+		/// Removes the property with the given key.
+		///
+		/// Does nothing if the key does not exist.
+		
+	void enableEvents(bool enable = true);
+		/// Enables (or disables) events.
+		
+	bool eventsEnabled() const;
+		/// Returns true iff events are enabled.
+	
+protected:
+	virtual bool getRaw(const std::string& key, std::string& value) const = 0;
+		/// If the property with the given key exists, stores the property's value
+		/// in value and returns true. Otherwise, returns false.
+		///
+		/// Must be overridden by subclasses.
+
+	virtual void setRaw(const std::string& key, const std::string& value) = 0;
+		/// Sets the property with the given key to the given value.
+		/// An already existing value for the key is overwritten.
+		///
+		/// Must be overridden by subclasses.
+		
+	virtual void enumerate(const std::string& key, Keys& range) const = 0;
+		/// Returns in range the names of all subkeys under the given key.
+		/// If an empty key is passed, all root level keys are returned.
+		
+	virtual void removeRaw(const std::string& key);
+		/// Removes the property with the given key.
+		///
+		/// Does nothing if the key does not exist.
+		///
+		/// Should be overridden by subclasses; the default
+		/// implementation throws a Poco::NotImplementedException.
+
+	static int parseInt(const std::string& value);
+	static unsigned parseUInt(const std::string& value);
+
+#if defined(POCO_HAVE_INT64)
+
+	static Int64 parseInt64(const std::string& value);
+	static UInt64 parseUInt64(const std::string& value);
+
+#endif // defined(POCO_HAVE_INT64)
+
+	static bool parseBool(const std::string& value);
+	void setRawWithEvent(const std::string& key, std::string value);
+	
+	virtual ~AbstractConfiguration();
+
+private:
+	std::string internalExpand(const std::string& value) const;
+	std::string uncheckedExpand(const std::string& value) const;
+
+	AbstractConfiguration(const AbstractConfiguration&);
+	AbstractConfiguration& operator = (const AbstractConfiguration&);
+
+	mutable int _depth;
+	bool        _eventsEnabled;
+	mutable Poco::Mutex _mutex;
+	
+	friend class LayeredConfiguration;
+	friend class ConfigurationView;
+	friend class ConfigurationMapper;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_AbstractConfiguration_INCLUDED
diff --git a/Poco/Util/Application.h b/Poco/Util/Application.h
new file mode 100644
index 0000000..da63ecf
--- /dev/null
+++ b/Poco/Util/Application.h
@@ -0,0 +1,545 @@
+//
+// Application.h
+//
+// Library: Util
+// Package: Application
+// Module:  Application
+//
+// Definition of the Application class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_Application_INCLUDED
+#define Util_Application_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/Subsystem.h"
+#include "Poco/Util/LayeredConfiguration.h"
+#include "Poco/Util/OptionSet.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Logger.h"
+#include "Poco/Path.h"
+#include "Poco/Timestamp.h"
+#include "Poco/Timespan.h"
+#include "Poco/AutoPtr.h"
+#if defined(POCO_VXWORKS)
+#include <cstdarg>
+#endif
+#include <vector>
+#include <typeinfo>
+
+
+namespace Poco {
+namespace Util {
+
+
+class OptionSet;
+
+
+class Util_API Application: public Subsystem
+	/// The Application class implements the main subsystem
+	/// in a process. The application class is responsible for
+	/// initializing all its subsystems.
+	///
+	/// Subclasses can and should override the following virtual methods:
+	///   - initialize() (the one-argument, protected variant)
+	///   - uninitialize()
+	///   - reinitialize()
+	///   - defineOptions()
+	///   - handleOption()
+	///   - main()
+	///
+	/// The application's main logic should be implemented in
+	/// the main() method.
+	///
+	/// There may be at most one instance of the Application class
+	/// in a process.
+	///
+	/// The Application class maintains a LayeredConfiguration (available
+	/// via the config() member function) consisting of:
+	///   - a MapConfiguration (priority -100) storing application-specific
+	///     properties, as well as properties from bound command line arguments.
+	///   - a SystemConfiguration (priority 100)
+	///   - the configurations loaded with loadConfiguration().
+	///
+	/// The Application class sets a few default properties in
+	/// its configuration. These are:
+	///   - application.path: the absolute path to application executable
+	///   - application.name: the file name of the application executable
+	///   - application.baseName: the file name (excluding extension) of the application executable
+	///   - application.dir: the path to the directory where the application executable resides
+	///   - application.configDir: the path to the directory where user specific configuration files of the application should be stored.
+	///   - application.cacheDir: the path to the directory where user specific non-essential data files of the application should be stored.
+	///   - application.dataDir: the path to the directory where user specific data files of the application should be stored.
+	///   - application.tempDir: the path to the directory where user specific temporary files and other file objects of the application should be stored.
+	///
+	/// If loadConfiguration() has never been called, application.configDir will be equal to application.dir.
+	///
+	/// The POCO_APP_MAIN macro can be used to implement main(argc, argv).
+	/// If POCO has been built with POCO_WIN32_UTF8, POCO_APP_MAIN supports
+	/// Unicode command line arguments.
+{
+public:
+	typedef std::vector<std::string> ArgVec;
+	typedef Poco::AutoPtr<Subsystem> SubsystemPtr;
+	typedef std::vector<SubsystemPtr> SubsystemVec;
+
+	enum ExitCode
+		/// Commonly used exit status codes.
+		/// Based on the definitions in the 4.3BSD <sysexits.h> header file.
+	{
+		EXIT_OK          = 0,  /// successful termination
+		EXIT_USAGE	     = 64, /// command line usage error
+		EXIT_DATAERR     = 65, /// data format error
+		EXIT_NOINPUT     = 66, /// cannot open input
+		EXIT_NOUSER      = 67, /// addressee unknown
+		EXIT_NOHOST      = 68, /// host name unknown
+		EXIT_UNAVAILABLE = 69, /// service unavailable
+		EXIT_SOFTWARE    = 70, /// internal software error
+		EXIT_OSERR	     = 71, /// system error (e.g., can't fork)
+		EXIT_OSFILE      = 72, /// critical OS file missing
+		EXIT_CANTCREAT   = 73, /// can't create (user) output file
+		EXIT_IOERR       = 74, /// input/output error
+		EXIT_TEMPFAIL    = 75, /// temp failure; user is invited to retry
+		EXIT_PROTOCOL    = 76, /// remote error in protocol
+		EXIT_NOPERM      = 77, /// permission denied
+		EXIT_CONFIG      = 78  /// configuration error
+	};
+
+	enum ConfigPriority
+	{
+		PRIO_APPLICATION = -100,
+		PRIO_DEFAULT     = 0,
+		PRIO_SYSTEM      = 100
+	};
+
+	Application();
+		/// Creates the Application.
+
+	Application(int argc, char* argv[]);
+		/// Creates the Application and calls init(argc, argv).
+
+	void addSubsystem(Subsystem* pSubsystem);
+		/// Adds a new subsystem to the application. The
+		/// application immediately takes ownership of it, so that a
+		/// call in the form
+		///     Application::instance().addSubsystem(new MySubsystem);
+		/// is okay.
+
+	void init(int argc, char* argv[]);
+		/// Processes the application's command line arguments
+		/// and sets the application's properties (e.g.,
+		/// "application.path", "application.name", etc.).
+		///
+		/// Note that as of release 1.3.7, init() no longer
+		/// calls initialize(). This is now called from run().
+
+#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
+	void init(int argc, wchar_t* argv[]);
+		/// Processes the application's command line arguments
+		/// and sets the application's properties (e.g.,
+		/// "application.path", "application.name", etc.).
+		///
+		/// Note that as of release 1.3.7, init() no longer
+		/// calls initialize(). This is now called from run().
+		///
+		/// This Windows-specific version of init is used for passing
+		/// Unicode command line arguments from wmain().
+#endif
+
+	void init(const ArgVec& args);
+		/// Processes the application's command line arguments
+		/// and sets the application's properties (e.g.,
+		/// "application.path", "application.name", etc.).
+		///
+		/// Note that as of release 1.3.7, init() no longer
+		/// calls initialize(). This is now called from run().
+
+	bool initialized() const;
+		/// Returns true iff the application is in initialized state
+		/// (that means, has been initialized but not yet uninitialized).
+
+	void setUnixOptions(bool flag);
+		/// Specify whether command line option handling is Unix-style
+		/// (flag == true; default) or Windows/OpenVMS-style (flag == false).
+		///
+		/// This member function should be called from the constructor of
+		/// a subclass to be effective.
+
+	int loadConfiguration(int priority = PRIO_DEFAULT);
+		/// Loads configuration information from a default location.
+		///
+		/// The configuration(s) will be added to the application's
+		/// LayeredConfiguration with the given priority.
+		///
+		/// The configuration file(s) must be located in the same directory
+		/// as the executable or a parent directory of it, and must have the
+		/// same base name as the executable, with one of the following extensions:
+		/// .properties, .ini or .xml.
+		///
+		/// The .properties file, if it exists, is loaded first, followed
+		/// by the .ini file and the .xml file.
+		///
+		/// If the application is built in debug mode (the _DEBUG preprocessor
+		/// macro is defined) and the base name of the appication executable
+		/// ends with a 'd', a config file without the 'd' ending its base name is
+		/// also found.
+		///
+		/// Example: Given the application "SampleAppd.exe", built in debug mode.
+		/// Then loadConfiguration() will automatically find a configuration file
+		/// named "SampleApp.properties" if it exists and if "SampleAppd.properties"
+		/// cannot be found.
+		///
+		/// Returns the number of configuration files loaded, which may be zero.
+		///
+		/// This method must not be called before init(argc, argv)
+		/// has been called.
+
+	void loadConfiguration(const std::string& path, int priority = PRIO_DEFAULT);
+		/// Loads configuration information from the file specified by
+		/// the given path. The file type is determined by the file
+		/// extension. The following extensions are supported:
+		///   - .properties - properties file (PropertyFileConfiguration)
+		///   - .ini        - initialization file (IniFileConfiguration)
+		///   - .xml        - XML file (XMLConfiguration)
+		///
+		/// Extensions are not case sensitive.
+		///
+		/// The configuration will be added to the application's
+		/// LayeredConfiguration with the given priority.
+
+	template <class C> C& getSubsystem() const;
+		/// Returns a reference to the subsystem of the class
+		/// given as template argument.
+		///
+		/// Throws a NotFoundException if such a subsystem has
+		/// not been registered.
+
+	SubsystemVec& subsystems();
+		/// Returns a reference to the subsystem list
+
+	virtual int run();
+		/// Runs the application by performing additional (un)initializations
+		/// and calling the main() method.
+		///
+		/// First calls initialize(), then calls main(), and
+		/// finally calls uninitialize(). The latter will be called
+		/// even if main() throws an exception. If initialize() throws
+		/// an exception, main() will not be called and the exception
+		/// will be propagated to the caller. If uninitialize() throws
+		/// an exception, the exception will be propagated to the caller.
+
+	std::string commandName() const;
+		/// Returns the command name used to invoke the application.
+
+	std::string commandPath() const;
+		/// Returns the full command path used to invoke the application.
+
+	LayeredConfiguration& config() const;
+		/// Returns the application's configuration.
+
+	Poco::Logger& logger() const;
+		/// Returns the application's logger.
+		///
+		/// Before the logging subsystem has been initialized, the
+		/// application's logger is "ApplicationStartup", which is
+		/// connected to a ConsoleChannel.
+		///
+		/// After the logging subsystem has been initialized, which
+		/// usually happens as the first action in Application::initialize(),
+		/// the application's logger is the one specified by the
+		/// "application.logger" configuration property. If that property
+		/// is not specified, the logger is "Application".
+
+	const ArgVec& argv() const;
+		/// Returns reference to vector of the application's arguments as
+		/// specified on the command line. If user overrides the
+		/// Application::main(const ArgVec&) function, it will receive
+		/// only the command line parameters that were not processed in
+		/// Application::processOptons(). This function returns the
+		/// full set of command line parameters as received in
+		/// main(argc, argv*).
+
+	const OptionSet& options() const;
+		/// Returns the application's option set.
+
+	static Application& instance();
+		/// Returns a reference to the Application singleton.
+		///
+		/// Throws a NullPointerException if no Application instance exists.
+
+	const Poco::Timestamp& startTime() const;
+		/// Returns the application start time (UTC).
+
+	Poco::Timespan uptime() const;
+		/// Returns the application uptime.
+
+	void stopOptionsProcessing();
+		/// If called from an option callback, stops all further
+		/// options processing.
+		///
+		/// If called, the following options on the command line
+		/// will not be processed, and required options will not
+		/// be checked.
+		///
+		/// This is useful, for example, if an option for displaying
+		/// help information has been encountered and no other things
+		/// besides displaying help shall be done.
+
+	const char* name() const;
+
+protected:
+	void initialize(Application& self);
+		/// Initializes the application and all registered subsystems.
+		/// Subsystems are always initialized in the exact same order
+		/// in which they have been registered.
+		///
+		/// Overriding implementations must call the base class implementation.
+
+	void uninitialize();
+		/// Uninitializes the application and all registered subsystems.
+		/// Subsystems are always uninitialized in reverse order in which
+		/// they have been initialized.
+		///
+		/// Overriding implementations must call the base class implementation.
+
+	void reinitialize(Application& self);
+		/// Re-nitializes the application and all registered subsystems.
+		/// Subsystems are always reinitialized in the exact same order
+		/// in which they have been registered.
+		///
+		/// Overriding implementations must call the base class implementation.
+
+	virtual void defineOptions(OptionSet& options);
+		/// Called before command line processing begins.
+		/// If a subclass wants to support command line arguments,
+		/// it must override this method.
+		/// The default implementation does not define any options itself,
+		/// but calls defineOptions() on all registered subsystems.
+		///
+		/// Overriding implementations should call the base class implementation.
+
+	virtual void handleOption(const std::string& name, const std::string& value);
+		/// Called when the option with the given name is encountered
+		/// during command line arguments processing.
+		///
+		/// The default implementation does option validation, bindings
+		/// and callback handling.
+		///
+		/// Overriding implementations must call the base class implementation.
+
+	void setLogger(Poco::Logger& logger);
+		/// Sets the logger used by the application.
+
+	virtual int main(const std::vector<std::string>& args);
+		/// The application's main logic.
+		///
+		/// Unprocessed command line arguments are passed in args.
+		/// Note that all original command line arguments are available
+		/// via the properties application.argc and application.argv[<n>].
+		///
+		/// Returns an exit code which should be one of the values
+		/// from the ExitCode enumeration.
+
+	bool findFile(Poco::Path& path) const;
+		/// Searches for the file in path in the application directory.
+		///
+		/// If path is absolute, the method immediately returns true and
+		/// leaves path unchanged.
+		///
+		/// If path is relative, searches for the file in the application
+		/// directory and in all subsequent parent directories.
+		/// Returns true and stores the absolute path to the file in
+		/// path if the file could be found. Returns false and leaves path
+		/// unchanged otherwise.
+
+	void init();
+		/// Common initialization code.
+
+	~Application();
+		/// Destroys the Application and deletes all registered subsystems.
+
+private:
+	void setup();
+	void setArgs(int argc, char* argv[]);
+	void setArgs(const ArgVec& args);
+	void getApplicationPath(Poco::Path& path) const;
+	void processOptions();
+	bool findAppConfigFile(const std::string& appName, const std::string& extension, Poco::Path& path) const;
+	bool findAppConfigFile(const Path& basePath, const std::string& appName, const std::string& extension, Poco::Path& path) const;
+
+	typedef Poco::AutoPtr<LayeredConfiguration> ConfigPtr;
+
+	ConfigPtr       _pConfig;
+	SubsystemVec    _subsystems;
+	bool            _initialized;
+	std::string     _command;
+	ArgVec          _argv;
+	ArgVec          _unprocessedArgs;
+	OptionSet       _options;
+	bool            _unixOptions;
+	Poco::Logger*   _pLogger;
+	Poco::Timestamp _startTime;
+	bool            _stopOptionsProcessing;
+
+#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
+	std::string _workingDirAtLaunch;
+#endif
+
+	static Application* _pInstance;
+
+	friend class LoggingSubsystem;
+
+	Application(const Application&);
+	Application& operator = (const Application&);
+};
+
+
+//
+// inlines
+//
+template <class C> C& Application::getSubsystem() const
+{
+	for (SubsystemVec::const_iterator it = _subsystems.begin(); it != _subsystems.end(); ++it)
+	{
+		const Subsystem* pSS(it->get());
+		const C* pC = dynamic_cast<const C*>(pSS);
+		if (pC) return *const_cast<C*>(pC);
+	}
+	throw Poco::NotFoundException("The subsystem has not been registered", typeid(C).name());
+}
+
+inline Application::SubsystemVec& Application::subsystems()
+{
+	return _subsystems;
+}
+
+
+inline bool Application::initialized() const
+{
+	return _initialized;
+}
+
+
+inline LayeredConfiguration& Application::config() const
+{
+	return *const_cast<LayeredConfiguration*>(_pConfig.get());
+}
+
+
+inline Poco::Logger& Application::logger() const
+{
+	poco_check_ptr (_pLogger);
+	return *_pLogger;
+}
+
+
+inline const Application::ArgVec& Application::argv() const
+{
+	return _argv;
+}
+
+
+inline const OptionSet& Application::options() const
+{
+	return _options;
+}
+
+
+inline Application& Application::instance()
+{
+	poco_check_ptr (_pInstance);
+	return *_pInstance;
+}
+
+
+inline const Poco::Timestamp& Application::startTime() const
+{
+	return _startTime;
+}
+
+
+inline Poco::Timespan Application::uptime() const
+{
+	Poco::Timestamp now;
+	Poco::Timespan uptime = now - _startTime;
+
+	return uptime;
+}
+
+
+} } // namespace Poco::Util
+
+
+//
+// Macro to implement main()
+//
+#if defined(_WIN32) && defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
+	#define POCO_APP_MAIN(App) \
+	int wmain(int argc, wchar_t** argv)		\
+	{										\
+		Poco::AutoPtr<App> pApp = new App;	\
+		try									\
+		{									\
+			pApp->init(argc, argv);			\
+		}									\
+		catch (Poco::Exception& exc)		\
+		{									\
+			pApp->logger().log(exc);		\
+			return Poco::Util::Application::EXIT_CONFIG;\
+		}									\
+		return pApp->run();					\
+	}
+#elif defined(POCO_VXWORKS)
+	#define POCO_APP_MAIN(App) \
+	int pocoAppMain(const char* appName, ...) \
+	{ \
+		std::vector<std::string> args; \
+		args.push_back(std::string(appName)); \
+		va_list vargs; \
+		va_start(vargs, appName); \
+		const char* arg = va_arg(vargs, const char*); \
+		while (arg) \
+		{ \
+			args.push_back(std::string(arg)); \
+			arg = va_arg(vargs, const char*); \
+		} \
+		va_end(vargs); \
+		Poco::AutoPtr<App> pApp = new App;	\
+		try									\
+		{									\
+			pApp->init(args);			\
+		}									\
+		catch (Poco::Exception& exc)		\
+		{									\
+			pApp->logger().log(exc);		\
+			return Poco::Util::Application::EXIT_CONFIG;\
+		}									\
+		return pApp->run();					\
+	}
+#else
+	#define POCO_APP_MAIN(App) \
+	int main(int argc, char** argv)			\
+	{										\
+		Poco::AutoPtr<App> pApp = new App;	\
+		try									\
+		{									\
+			pApp->init(argc, argv);			\
+		}									\
+		catch (Poco::Exception& exc)		\
+		{									\
+			pApp->logger().log(exc);		\
+			return Poco::Util::Application::EXIT_CONFIG;\
+		}									\
+		return pApp->run();					\
+	}
+#endif
+
+
+#endif // Util_Application_INCLUDED
diff --git a/Poco/Util/ConfigurationMapper.h b/Poco/Util/ConfigurationMapper.h
new file mode 100644
index 0000000..ef8e960
--- /dev/null
+++ b/Poco/Util/ConfigurationMapper.h
@@ -0,0 +1,94 @@
+//
+// ConfigurationMapper.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  ConfigurationMapper
+//
+// Definition of the ConfigurationMapper class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_ConfigurationMapper_INCLUDED
+#define Util_ConfigurationMapper_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API ConfigurationMapper: public AbstractConfiguration
+	/// This configuration maps a property hierarchy into another
+	/// hierarchy.
+	/// 
+	/// For example, given a configuration with the following properties:
+	///     config.value1
+	///     config.value2
+	///     config.sub.value1
+	///     config.sub.value2
+	/// and a ConfigurationView with fromPrefix == "config" and toPrefix == "root.conf", then
+	/// the above properties will be available via the mapper as
+	///     root.conf.value1
+	///     root.conf.value2
+	///     root.conf.sub.value1
+	///     root.conf.sub.value2
+	///
+	/// FromPrefix can be empty, in which case, and given toPrefix == "root",
+	/// the properties will be available as
+	///     root.config.value1
+	///     root.config.value2
+	///     root.config.sub.value1
+	///     root.config.sub.value2
+	///
+	/// This is equivalent to the functionality of the ConfigurationView class.
+	///
+	/// Similarly, toPrefix can also be empty. Given fromPrefix == "config" and
+	/// toPrefix == "", the properties will be available as
+	///     value1
+	///     value2
+	///     sub.value1
+	///     sub.value2
+	///
+	/// If both fromPrefix and toPrefix are empty, no mapping is performed.
+	///
+	/// A ConfigurationMapper is most useful in combination with a
+	/// LayeredConfiguration.
+{
+public:
+	ConfigurationMapper(const std::string& fromPrefix, const std::string& toPrefix, AbstractConfiguration* pConfig);
+		/// Creates the ConfigurationMapper. The ConfigurationMapper does not take
+		/// ownership of the passed configuration.
+
+protected:
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	
+	std::string translateKey(const std::string& key) const;
+	
+	~ConfigurationMapper();
+
+private:
+	ConfigurationMapper(const ConfigurationMapper&);
+	ConfigurationMapper& operator = (const ConfigurationMapper&);
+
+	std::string _fromPrefix;
+	std::string _toPrefix;
+	AbstractConfiguration* _pConfig;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_ConfigurationMapper_INCLUDED
diff --git a/Poco/Util/ConfigurationView.h b/Poco/Util/ConfigurationView.h
new file mode 100644
index 0000000..10f8948
--- /dev/null
+++ b/Poco/Util/ConfigurationView.h
@@ -0,0 +1,82 @@
+//
+// ConfigurationView.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  ConfigurationView
+//
+// Definition of the ConfigurationView class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_ConfigurationView_INCLUDED
+#define Util_ConfigurationView_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API ConfigurationView: public AbstractConfiguration
+	/// This configuration implements a "view" into a sub-hierarchy 
+	/// of another configuration.
+	/// 
+	/// For example, given a configuration with the following properties:
+	///     config.value1
+	///     config.value2
+	///     config.sub.value1
+	///     config.sub.value2
+	/// and a ConfigurationView with the prefix "config", then
+	/// the above properties will be available via the view as
+	///     value1
+	///     value2
+	///     sub.value1
+	///     sub.value2
+	///
+	/// A ConfigurationView is most useful in combination with a
+	/// LayeredConfiguration.
+	///
+	/// If a property is not found in the view, it is searched in
+	/// the original configuration. Given the above example configuration,
+	/// the property named "config.value1" will still be found in the view.
+	///
+	/// The main reason for this is that placeholder expansion (${property})
+	/// still works as expected given a ConfigurationView.
+{
+public:
+	ConfigurationView(const std::string& prefix, AbstractConfiguration* pConfig);
+		/// Creates the ConfigurationView. The ConfigurationView does not take
+		/// ownership of the passed configuration.
+
+protected:
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	
+	std::string translateKey(const std::string& key) const;
+	
+	~ConfigurationView();
+
+private:
+	ConfigurationView(const ConfigurationView&);
+	ConfigurationView& operator = (const ConfigurationView&);
+
+	std::string _prefix;
+	AbstractConfiguration* _pConfig;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_ConfigurationView_INCLUDED
diff --git a/Poco/Util/FilesystemConfiguration.h b/Poco/Util/FilesystemConfiguration.h
new file mode 100644
index 0000000..d0a1718
--- /dev/null
+++ b/Poco/Util/FilesystemConfiguration.h
@@ -0,0 +1,93 @@
+//
+// FilesystemConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  FilesystemConfiguration
+//
+// Definition of the FilesystemConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_FilesystemConfiguration_INCLUDED
+#define Util_FilesystemConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+#include "Poco/Path.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API FilesystemConfiguration: public AbstractConfiguration
+	/// An implementation of AbstractConfiguration that stores configuration data
+	/// in a directory hierarchy in the filesystem.
+	///
+	/// Every period-separated part of a property name is represented
+	/// as a directory in the filesystem, relative to the base directory.
+	/// Values are stored in files named "data".
+	///
+	/// All changes to properties are immediately persisted in the filesystem.
+	///
+	/// For example, a configuration consisting of the properties
+	/// 
+	///   logging.loggers.root.channel.class = ConsoleChannel
+	///   logging.loggers.app.name = Application
+	///   logging.loggers.app.channel = c1
+	///   logging.formatters.f1.class = PatternFormatter
+	///   logging.formatters.f1.pattern = [%p] %t
+	///
+	/// is stored in the filesystem as follows:
+	///
+	///   logging/
+	///           loggers/
+	///                   root/
+	///                        channel/
+	///                                class/
+	///                                      data ("ConsoleChannel")
+	///                   app/
+	///                       name/
+	///                            data ("Application")
+	///                       channel/
+	///                               data ("c1")
+	///           formatters/
+	///                      f1/
+	///                         class/
+	///                               data ("PatternFormatter")
+	///                         pattern/
+	///                                 data ("[%p] %t")                      
+{
+public:
+	FilesystemConfiguration(const std::string& path);
+		/// Creates a FilesystemConfiguration using the given path.
+		/// All directories are created as necessary.
+
+	void clear();
+		/// Clears the configuration by erasing the configuration
+		/// directory and all its subdirectories and files.
+
+protected:
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	Poco::Path keyToPath(const std::string& key) const;
+	~FilesystemConfiguration();
+
+private:
+	Poco::Path _path;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_FilesystemConfiguration_INCLUDED
diff --git a/Poco/Util/HelpFormatter.h b/Poco/Util/HelpFormatter.h
new file mode 100644
index 0000000..3d79ec0
--- /dev/null
+++ b/Poco/Util/HelpFormatter.h
@@ -0,0 +1,202 @@
+//
+// HelpFormatter.h
+//
+// Library: Util
+// Package: Options
+// Module:  HelpFormatter
+//
+// Definition of the HelpFormatter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_HelpFormatter_INCLUDED
+#define Util_HelpFormatter_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include <ostream>
+
+
+namespace Poco {
+namespace Util {
+
+
+class OptionSet;
+class Option;
+
+
+class Util_API HelpFormatter
+	/// This class formats a help message from an OptionSet.
+{
+public:
+	HelpFormatter(const OptionSet& options);
+		/// Creates the HelpFormatter, using the given
+		/// options. 
+		///
+		/// The HelpFormatter just stores a reference
+		/// to the given OptionSet, so the OptionSet must not
+		/// be destroyed during the lifetime of the HelpFormatter.
+
+	~HelpFormatter();
+		/// Destroys the HelpFormatter.
+
+	void setCommand(const std::string& command);
+		/// Sets the command name.
+		
+	const std::string& getCommand() const;
+		/// Returns the command name.
+		
+	void setUsage(const std::string& usage);
+		/// Sets the usage string.
+		
+	const std::string& getUsage() const;
+		/// Returns the usage string.
+		
+	void setHeader(const std::string& header);
+		/// Sets the header string.
+		
+	const std::string& getHeader() const;
+		/// Returns the header string.
+		
+	void setFooter(const std::string& footer);
+		/// Sets the footer string.
+		
+	const std::string& getFooter() const;
+		/// Returns the footer string.
+
+	void format(std::ostream& ostr) const;
+		/// Writes the formatted help text to the given stream.
+	
+	void setWidth(int width);
+		/// Sets the line width for the formatted help text.
+		
+	int getWidth() const;
+		/// Returns the line width for the formatted help text.
+		///
+		/// The default width is 72.
+
+	void setIndent(int indent);
+		/// Sets the indentation for description continuation lines.
+
+	int getIndent() const;
+		/// Returns the indentation for description continuation lines.
+		
+	void setAutoIndent();
+		/// Sets the indentation for description continuation lines so that
+		/// the description text is left-aligned. 
+
+	void setUnixStyle(bool flag);
+		/// Enables Unix-style options. Both short and long option names
+		/// are printed if Unix-style is set. Otherwise, only long option
+		/// names are printed.
+		///
+		/// After calling setUnixStyle(), setAutoIndent() should be called
+		/// as well to ensure proper help text formatting.
+		
+	bool isUnixStyle() const;
+		/// Returns if Unix-style options are set.
+
+	std::string shortPrefix() const;
+		/// Returns the platform-specific prefix for short options.
+		/// "-" on Unix, "/" on Windows and OpenVMS.
+	
+	std::string longPrefix() const;
+		/// Returns the platform-specific prefix for long options.
+		/// "--" on Unix, "/" on Windows and OpenVMS.
+
+protected:
+	int calcIndent() const;
+		/// Calculates the indentation for the option descriptions
+		/// from the given options.
+
+	void formatOptions(std::ostream& ostr) const;
+		/// Formats all options.
+
+	void formatOption(std::ostream& ostr, const Option& option, int width) const;
+		/// Formats an option, using the platform-specific
+		/// prefixes.
+
+	void formatText(std::ostream& ostr, const std::string& text, int indent) const;
+		/// Formats the given text.
+
+	void formatText(std::ostream& ostr, const std::string& text, int indent, int firstIndent) const;
+		/// Formats the given text.
+
+	void formatWord(std::ostream& ostr, int& pos, const std::string& word, int indent) const;
+		/// Formats the given word.
+	
+	void clearWord(std::ostream& ostr, int& pos, std::string& word, int indent) const;
+		/// Formats and then clears the given word.
+	
+private:
+	HelpFormatter(const HelpFormatter&);
+	HelpFormatter& operator = (const HelpFormatter&);
+
+	const OptionSet& _options;
+	int _width;
+	int _indent;
+	std::string _command;
+	std::string _usage;
+	std::string _header;
+	std::string _footer;
+	bool _unixStyle;
+	
+	static const int TAB_WIDTH;
+	static const int LINE_WIDTH;
+};
+
+
+//
+// inlines
+//
+inline int HelpFormatter::getWidth() const
+{
+	return _width;
+}
+
+
+inline int HelpFormatter::getIndent() const
+{
+	return _indent;
+}
+
+
+inline const std::string& HelpFormatter::getCommand() const
+{
+	return _command;
+}
+
+
+inline const std::string& HelpFormatter::getUsage() const
+{
+	return _usage;
+}
+
+
+inline const std::string& HelpFormatter::getHeader() const
+{
+	return _header;
+}
+
+
+inline const std::string& HelpFormatter::getFooter() const
+{
+	return _footer;
+}
+
+
+inline bool HelpFormatter::isUnixStyle() const
+{
+	return _unixStyle;
+}
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_HelpFormatter_INCLUDED
diff --git a/Poco/Util/IniFileConfiguration.h b/Poco/Util/IniFileConfiguration.h
new file mode 100644
index 0000000..94ea5da
--- /dev/null
+++ b/Poco/Util/IniFileConfiguration.h
@@ -0,0 +1,99 @@
+//
+// IniFileConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  IniFileConfiguration
+//
+// Definition of the IniFileConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_IniFileConfiguration_INCLUDED
+#define Util_IniFileConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+
+
+#ifndef POCO_UTIL_NO_INIFILECONFIGURATION
+
+
+#include "Poco/Util/AbstractConfiguration.h"
+#include <map>
+#include <istream>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API IniFileConfiguration: public AbstractConfiguration
+	/// This implementation of a Configuration reads properties
+	/// from a legacy Windows initialization (.ini) file.
+	///
+	/// The file syntax is implemented as follows.
+	///   - a line starting with a semicolon is treated as a comment and ignored
+	///   - a line starting with a square bracket denotes a section key [<key>]
+	///   - every other line denotes a property assignment in the form
+	///     <value key> = <value>
+	///
+	/// The name of a property is composed of the section key and the value key,
+	/// separated by a period (<section key>.<value key>).
+	///
+	/// Property names are not case sensitive. Leading and trailing whitespace is
+	/// removed from both keys and values.
+{
+public:
+	IniFileConfiguration();
+		/// Creates an empty IniFileConfiguration.
+
+	IniFileConfiguration(std::istream& istr);
+		/// Creates an IniFileConfiguration and loads the configuration data
+		/// from the given stream, which must be in initialization file format.
+		
+	IniFileConfiguration(const std::string& path);
+		/// Creates an IniFileConfiguration and loads the configuration data
+		/// from the given file, which must be in initialization file format.
+		
+	void load(std::istream& istr);
+		/// Loads the configuration data from the given stream, which 
+		/// must be in initialization file format.
+		
+	void load(const std::string& path);
+		/// Loads the configuration data from the given file, which 
+		/// must be in initialization file format.
+
+protected:
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	~IniFileConfiguration();
+
+private:
+	void parseLine(std::istream& istr);
+
+	struct ICompare
+	{
+		bool operator () (const std::string& s1, const std::string& s2) const;
+	};
+	typedef std::map<std::string, std::string, ICompare> IStringMap;
+	
+	IStringMap _map;
+	std::string _sectionKey;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // POCO_UTIL_NO_INIFILECONFIGURATION
+
+
+#endif // Util_IniFileConfiguration_INCLUDED
diff --git a/Poco/Util/IntValidator.h b/Poco/Util/IntValidator.h
new file mode 100644
index 0000000..10e15f8
--- /dev/null
+++ b/Poco/Util/IntValidator.h
@@ -0,0 +1,56 @@
+//
+// IntValidator.h
+//
+// Library: Util
+// Package: Options
+// Module:  IntValidator
+//
+// Definition of the IntValidator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_IntValidator_INCLUDED
+#define Util_IntValidator_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/Validator.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API IntValidator: public Validator
+	/// The IntValidator tests whether the option argument,
+	/// which must be an integer, lies within a given range.
+{
+public:
+	IntValidator(int min, int max);
+		/// Creates the IntValidator.
+
+	~IntValidator();
+		/// Destroys the IntValidator.
+
+	void validate(const Option& option, const std::string& value);
+		/// Validates the value for the given option by
+		/// testing whether it's an integer that lies within
+		/// a given range.
+
+private:
+	IntValidator();
+
+	int _min;
+	int _max;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_IntValidator_INCLUDED
diff --git a/Poco/Util/JSONConfiguration.h b/Poco/Util/JSONConfiguration.h
new file mode 100644
index 0000000..d1fa53e
--- /dev/null
+++ b/Poco/Util/JSONConfiguration.h
@@ -0,0 +1,150 @@
+//
+// JSONConfiguration.h
+//
+// Library: Util
+// Package: Util
+// Module:  JSONConfiguration
+//
+// Definition of the JSONConfiguration class.
+//
+// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_JSONConfiguration_INCLUDED
+#define Util_JSONConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+
+
+#ifndef POCO_UTIL_NO_JSONCONFIGURATION
+
+
+#include "Poco/Util/AbstractConfiguration.h"
+#include "Poco/JSON/Object.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API JSONConfiguration : public AbstractConfiguration
+	/// This configuration class extracts configuration properties
+	/// from a JSON object. An XPath-like syntax for property
+	/// names is supported to allow full access to the JSON object.
+	///
+	/// Given the following JSON object as an example:
+	/// {
+	///   "config" : {
+	///      "prop1" : "value1",
+	///      "prop2" : 10,
+	///      "prop3" : [
+	///        "element1",
+	///        "element2"
+	///      ],
+	///      "prop4" : {
+	///        "prop5" : false,
+	///        "prop6" : null
+	///      }
+	///   }
+	/// }
+	///	The following property names would be valid and would
+	/// yield the shown values:
+	///
+	/// config.prop1       --> "value1"
+	/// config.prop3[1]    --> "element2"
+	/// config.prop4.prop5 --> false
+{
+public:
+
+	JSONConfiguration();
+		/// Creates an empty configuration
+
+
+	JSONConfiguration(const std::string& path);
+		/// Creates a configuration and loads the JSON structure from the given file
+
+
+	JSONConfiguration(std::istream& istr);
+		/// Creates a configuration and loads the JSON structure from the given stream
+
+
+	JSONConfiguration(const JSON::Object::Ptr& object);
+		/// Creates a configuration from the given JSON object
+
+
+	virtual ~JSONConfiguration();
+		/// Destructor
+
+
+	void load(const std::string& path);
+		/// Loads the configuration from the given file
+
+
+	void load(std::istream& istr);
+		/// Loads the configuration from the given stream
+
+
+	void loadEmpty(const std::string& root);
+		/// Loads an empty object containing only a root object with the given name.
+
+
+	void save(std::ostream& ostr, unsigned int indent = 2) const;
+		/// Saves the configuration to the given stream
+
+
+	virtual void setInt(const std::string& key, int value);
+
+
+	virtual void setBool(const std::string& key, bool value);
+
+
+	virtual void setDouble(const std::string& key, double value);
+
+
+	virtual void setString(const std::string& key, const std::string& value);
+	
+
+	virtual void removeRaw(const std::string& key);	
+	
+
+protected:
+
+	bool getRaw(const std::string & key, std::string & value) const;
+
+
+	void setRaw(const std::string& key, const std::string& value);
+
+
+	void enumerate(const std::string& key, Keys& range) const;
+
+
+private:
+
+
+	JSON::Object::Ptr findStart(const std::string& key, std::string& lastPart);
+
+
+	void getIndexes(std::string& name, std::vector<int>& indexes);
+
+
+	void setValue(const std::string& key, const Poco::DynamicAny& value);
+
+
+ 	JSON::Object::Ptr _object;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // POCO_UTIL_NO_JSONCONFIGURATION
+
+
+#endif // Util_JSONConfiguration_INCLUDED
+
diff --git a/Poco/Util/LayeredConfiguration.h b/Poco/Util/LayeredConfiguration.h
new file mode 100644
index 0000000..59628b3
--- /dev/null
+++ b/Poco/Util/LayeredConfiguration.h
@@ -0,0 +1,184 @@
+//
+// LayeredConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  LayeredConfiguration
+//
+// Definition of the LayeredConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_LayeredConfiguration_INCLUDED
+#define Util_LayeredConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+#include "Poco/AutoPtr.h"
+#include <list>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API LayeredConfiguration: public AbstractConfiguration
+	/// A LayeredConfiguration consists of a number of AbstractConfigurations.
+	///
+	/// When reading a configuration property in a LayeredConfiguration,
+	/// all added configurations are searched, in order of their priority.
+	/// Configurations with lower priority values have precedence.
+	///
+	/// When setting a property, the property is always written to the first writeable 
+	/// configuration (see addWriteable()). 
+	/// If no writeable configuration has been added to the LayeredConfiguration, and an
+	/// attempt is made to set a property, a RuntimeException is thrown.
+	///
+	/// Every configuration added to the LayeredConfiguration has a priority value.
+	/// The priority determines the position where the configuration is inserted,
+	/// with lower priority values coming before higher priority values.
+	///
+	/// If no priority is specified, a priority of 0 is assumed.
+{
+public:
+	typedef Poco::AutoPtr<AbstractConfiguration> ConfigPtr;
+
+	LayeredConfiguration();
+		/// Creates the LayeredConfiguration.
+		
+	void add(AbstractConfiguration* pConfig);
+		/// Adds a read-only configuration to the back of the LayeredConfiguration.
+		/// The LayeredConfiguration does not take ownership of the given
+		/// configuration. In other words, the configuration's reference
+		/// count is incremented.
+
+	void add(AbstractConfiguration* pConfig, const std::string& label);
+		/// Adds a read-only configuration with the given label to the back of the LayeredConfiguration.
+		/// The LayeredConfiguration does not take ownership of the given
+		/// configuration. In other words, the configuration's reference
+		/// count is incremented.
+
+	void add(AbstractConfiguration* pConfig, bool shared);
+		/// Adds a read-only configuration to the back of the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+
+	void add(AbstractConfiguration* pConfig, const std::string& label, bool shared);
+		/// Adds a read-only configuration with the given label to the back of the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+
+	void add(AbstractConfiguration* pConfig, int priority);
+		/// Adds a read-only configuration to the LayeredConfiguration.
+		/// The LayeredConfiguration does not take ownership of the given
+		/// configuration. In other words, the configuration's reference
+		/// count is incremented.
+
+	void add(AbstractConfiguration* pConfig, const std::string& label, int priority);
+		/// Adds a read-only configuration with the given label to the LayeredConfiguration.
+		/// The LayeredConfiguration does not take ownership of the given
+		/// configuration. In other words, the configuration's reference
+		/// count is incremented.
+
+	void add(AbstractConfiguration* pConfig, int priority, bool shared);
+		/// Adds a read-only configuration the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+
+	void add(AbstractConfiguration* pConfig, const std::string& label, int priority, bool shared);
+		/// Adds a read-only configuration with the given label the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+
+	void add(AbstractConfiguration* pConfig, int priority, bool writeable, bool shared);
+		/// Adds a configuration to the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+
+	void add(AbstractConfiguration* pConfig, const std::string& label, int priority, bool writeable, bool shared);
+		/// Adds a configuration with the given label to the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+
+	void addWriteable(AbstractConfiguration* pConfig, int priority);
+		/// Adds a writeable configuration to the LayeredConfiguration.
+		/// The LayeredConfiguration does not take ownership of the given
+		/// configuration. In other words, the configuration's reference
+		/// count is incremented.
+
+	void addWriteable(AbstractConfiguration* pConfig, int priority, bool shared);
+		/// Adds a writeable configuration to the LayeredConfiguration.
+		/// If shared is false, the LayeredConfiguration takes ownership
+		/// of the given configuration (and the configuration's reference
+		/// count remains unchanged).
+		
+	ConfigPtr find(const std::string& label) const;
+		/// Finds and returns the configuration with the given label.
+		///
+		/// Returns null if no such configuration can be found.
+
+	//@ deprecated
+	void addFront(AbstractConfiguration* pConfig);
+		/// Adds a read-only configuration to the front of the LayeredConfiguration.
+		/// The LayeredConfiguration does not take ownership of the given
+		/// configuration. In other words, the configuration's reference
+		/// count is incremented.
+
+	//@ deprecated
+	void addFront(AbstractConfiguration* pConfig, bool shared);
+		/// Adds a read-only configuration to the front of the LayeredConfiguration.
+		/// If shared is true, the LayeredConfiguration takes ownership
+		/// of the given configuration.
+		
+	void removeConfiguration(AbstractConfiguration* pConfig);
+		/// Removes the given configuration from the LayeredConfiguration.
+		///
+		/// Does nothing if the given configuration is not part of the
+		/// LayeredConfiguration.
+		
+protected:	
+	struct ConfigItem
+	{
+		ConfigPtr   pConfig;
+		int         priority;
+		bool        writeable;
+		std::string label;
+	};
+
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	
+	int lowest() const;
+	int highest() const;
+	void insert(const ConfigItem& item);
+	
+	~LayeredConfiguration();
+
+private:
+	LayeredConfiguration(const LayeredConfiguration&);
+	LayeredConfiguration& operator = (const LayeredConfiguration&);
+
+	typedef std::list<ConfigItem> ConfigList;
+	
+	ConfigList _configs;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_LayeredConfiguration_INCLUDED
diff --git a/Poco/Util/LoggingConfigurator.h b/Poco/Util/LoggingConfigurator.h
new file mode 100644
index 0000000..e5ed99a
--- /dev/null
+++ b/Poco/Util/LoggingConfigurator.h
@@ -0,0 +1,139 @@
+//
+// LoggingConfigurator.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  LoggingConfigurator
+//
+// Definition of the LoggingConfigurator class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_LoggingConfigurator_INCLUDED
+#define Util_LoggingConfigurator_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Formatter.h"
+#include "Poco/Channel.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class AbstractConfiguration;
+
+
+class Util_API LoggingConfigurator
+	/// This utility class uses a configuration object to configure the
+	/// logging subsystem of an application.
+	///
+	/// The LoggingConfigurator sets up and connects formatters, channels 
+	/// and loggers. To accomplish its work, the LoggingConfigurator relies on the
+	/// functionality provided by the LoggingFactory and LoggingRegistry classes.
+	///
+	/// The LoggingConfigurator expects all configuration data to be under a root
+	/// property named "logging".
+	/// 
+	/// Configuring Formatters
+	///
+	/// A formatter is configured using the "logging.formatters" property. Every 
+	/// formatter has an internal name, which is only used for referring to it 
+	/// during configuration time. This name becomes part of the property name.
+	/// Every formatter has a mandatory "class" property, which specifies the actual
+	/// class implementing the formatter. Any other properties are passed on to
+	/// the formatter by calling its setProperty() method.
+	///
+	/// A typical formatter definition looks as follows:
+	///     logging.formatters.f1.class = PatternFormatter
+	///     logging.formatters.f1.pattern = %s: [%p] %t
+	///     logging.formatters.f1.times = UTC
+	///
+	/// Configuring Channels
+	///
+	/// A channel is configured using the "logging.channels" property. Like with
+	/// Formatters, every channel has an internal name, which is used during
+	/// configuration only. The name becomes part of the property name.
+	/// Every channel has a mandatory "class" property, which specifies the actual
+	/// class implementing the channel. Any other properties are passed on to
+	/// the formatter by calling its setProperty() method.
+	///
+	/// For convenience, the "formatter" property of a channel is treated
+	/// specifically. The "formatter" property can either be used to refer to
+	/// an already defined formatter, or it can be used to specify an "inline"
+	/// formatter definition. In either case, when a "formatter" property is
+	/// present, the channel is automatically "wrapped" in a FormattingChannel
+	/// object.
+	/// 
+	/// Similarly, a channel supports also a "pattern" property, which results
+	/// in the automatic instantiation of a FormattingChannel object with a
+	/// connected PatternFormatter.
+	/// 
+	/// Examples:
+	///     logging.channels.c1.class = ConsoleChannel
+	///     logging.channels.c1.formatter = f1
+	///     logging.channels.c2.class = FileChannel
+	///     logging.channels.c2.path = ${system.tempDir}/sample.log
+	///     logging.channels.c2.formatter.class = PatternFormatter
+	///     logging.channels.c2.formatter.pattern = %s: [%p] %t
+	///     logging.channels.c3.class = ConsoleChannel
+	///     logging.channels.c3.pattern = %s: [%p] %t
+	///
+	/// Configuring Loggers
+	///
+	/// A logger is configured using the "logging.loggers" property. Like with
+	/// channels and formatters, every logger has an internal name, which, however,
+	/// is only used to ensure the uniqueness of the property names. Note that this
+	/// name is different from the logger's full name, which is used to access
+	/// the logger at runtime.
+	/// Every logger except the root logger has a mandatory "name" property which
+	/// is used to specify the logger's full name.
+	/// Furthermore, a "channel" property is supported, which can either refer
+	/// to a named channel, or which can contain an inline channel definition.
+	///
+	/// Examples:
+	///     logging.loggers.root.channel = c1
+	///     logging.loggers.root.level = warning
+	///     logging.loggers.l1.name = logger1
+	///     logging.loggers.l1.channel.class = ConsoleChannel
+	///     logging.loggers.l1.channel.pattern = %s: [%p] %t
+	///     logging.loggers.l1.level = information
+{
+public:
+	LoggingConfigurator();
+		/// Creates the LoggingConfigurator.
+
+	~LoggingConfigurator();
+		/// Destroys the LoggingConfigurator.
+		
+	void configure(AbstractConfiguration* pConfig);
+		/// Configures the logging subsystem based on
+		/// the given configuration.
+		///
+		/// A ConfigurationView can be used to pass only
+		/// a part of a larger configuration.
+
+private:
+	void configureFormatters(AbstractConfiguration* pConfig);
+	void configureChannels(AbstractConfiguration* pConfig);
+	void configureLoggers(AbstractConfiguration* pConfig);
+	Poco::Formatter* createFormatter(AbstractConfiguration* pConfig);
+	Poco::Channel* createChannel(AbstractConfiguration* pConfig);
+	void configureChannel(Channel* pChannel, AbstractConfiguration* pConfig);
+	void configureLogger(AbstractConfiguration* pConfig);
+	
+	LoggingConfigurator(const LoggingConfigurator&);
+	LoggingConfigurator& operator = (const LoggingConfigurator&);
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_LoggingConfigurator_INCLUDED
diff --git a/Poco/Util/LoggingSubsystem.h b/Poco/Util/LoggingSubsystem.h
new file mode 100644
index 0000000..53e8c9a
--- /dev/null
+++ b/Poco/Util/LoggingSubsystem.h
@@ -0,0 +1,52 @@
+//
+// LoggingSubsystem.h
+//
+// Library: Util
+// Package: Application
+// Module:  LoggingSubsystem
+//
+// Definition of the LoggingSubsystem class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_LoggingSubsystem_INCLUDED
+#define Util_LoggingSubsystem_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/Subsystem.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API LoggingSubsystem: public Subsystem
+	/// The LoggingSubsystem class initializes the logging
+	/// framework using the LoggingConfigurator.
+	///
+	/// It also sets the Application's logger to
+	/// the logger specified by the "application.logger"
+	/// property, or to "Application" if the property
+	/// is not specified.
+{
+public:
+	LoggingSubsystem();
+	const char* name() const;
+	
+protected:
+	void initialize(Application& self);
+	void uninitialize();
+	~LoggingSubsystem();
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_LoggingSubsystem_INCLUDED
diff --git a/Poco/Util/MapConfiguration.h b/Poco/Util/MapConfiguration.h
new file mode 100644
index 0000000..ac725cd
--- /dev/null
+++ b/Poco/Util/MapConfiguration.h
@@ -0,0 +1,64 @@
+//
+// MapConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  MapConfiguration
+//
+// Definition of the MapConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_MapConfiguration_INCLUDED
+#define Util_MapConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+#include <map>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API MapConfiguration: public AbstractConfiguration
+	/// An implementation of AbstractConfiguration that stores configuration data in a map.
+{
+public:
+	MapConfiguration();
+		/// Creates an empty MapConfiguration.
+
+	void copyTo(AbstractConfiguration& config);
+		/// Copies all configuration properties to the given configuration.
+
+	void clear();
+		/// Clears the configuration.
+
+protected:
+	typedef std::map<std::string, std::string> StringMap;
+	typedef StringMap::const_iterator iterator;
+
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	~MapConfiguration();
+
+	iterator begin() const;
+	iterator end() const;
+
+private:	
+	StringMap _map;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_MapConfiguration_INCLUDED
diff --git a/Poco/Util/Option.h b/Poco/Util/Option.h
new file mode 100644
index 0000000..051f7c0
--- /dev/null
+++ b/Poco/Util/Option.h
@@ -0,0 +1,332 @@
+//
+// Option.h
+//
+// Library: Util
+// Package: Options
+// Module:  Option
+//
+// Definition of the Option class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_Option_INCLUDED
+#define Util_Option_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/OptionCallback.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Application;
+class Validator;
+class AbstractConfiguration;
+
+
+class Util_API Option
+	/// This class represents and stores the properties
+	/// of a command line option.
+	///
+	/// An option has a full name, an optional short name,
+	/// a description (used for printing a usage statement),
+	/// and an optional argument name.
+	/// An option can be optional or required.
+	/// An option can be repeatable, which means that it can
+	/// be given more than once on the command line.
+	///
+	/// An option can be part of an option group. At most one
+	/// option of each group may be specified on the command
+	/// line.
+	///
+	/// An option can be bound to a configuration property.
+	/// In this case, a configuration property will automatically
+	/// receive the option's argument value.
+	///
+	/// A callback method can be specified for options. This method
+	/// is called whenever an option is specified on the command line.
+	///
+	/// Option argument values can be automatically validated using a
+	/// Validator.
+	///
+	/// Option instances are value objects.
+	///
+	/// Typically, after construction, an Option object is immediately
+	/// passed to an Options object.
+	///
+	/// An Option object can be created by chaining the constructor
+	/// with any of the setter methods, as in the following example:
+	///
+	///     Option versionOpt("include", "I", "specify an include directory")
+	///        .required(false)
+	///        .repeatable(true)
+	///        .argument("directory");
+{
+public:
+	Option();
+		/// Creates an empty Option.
+
+	Option(const Option& option);
+		/// Creates an option from another one.
+
+	Option(const std::string& fullName, const std::string& shortName);
+		/// Creates an option with the given properties.
+
+	Option(const std::string& fullName, const std::string& shortName, const std::string& description, bool required = false);
+		/// Creates an option with the given properties.
+
+	Option(const std::string& fullName, const std::string& shortName, const std::string& description, bool required, const std::string& argName, bool argRequired = false);
+		/// Creates an option with the given properties.
+
+	~Option();
+		/// Destroys the Option.
+
+	Option& operator = (const Option& option);
+		/// Assignment operator.
+		
+	void swap(Option& option);
+		/// Swaps the option with another one.
+
+	Option& shortName(const std::string& name);
+		/// Sets the short name of the option.
+		
+	Option& fullName(const std::string& name);
+		/// Sets the full name of the option.
+		
+	Option& description(const std::string& text);
+		/// Sets the description of the option.
+		
+	Option& required(bool flag);
+		/// Sets whether the option is required (flag == true)
+		/// or optional (flag == false).
+
+	Option& repeatable(bool flag);
+		/// Sets whether the option can be specified more than once
+		/// (flag == true) or at most once (flag == false).
+		
+	Option& argument(const std::string& name, bool required = true);
+		/// Specifies that the option takes an (optional or required)
+		/// argument.
+		
+	Option& noArgument();
+		/// Specifies that the option does not take an argument (default).
+
+	Option& group(const std::string& group);
+		/// Specifies the option group the option is part of.
+		
+	Option& binding(const std::string& propertyName);
+		/// Binds the option to the configuration property with the given name.
+		///
+		/// The configuration will automatically receive the option's argument.
+
+	Option& binding(const std::string& propertyName, AbstractConfiguration* pConfig);
+		/// Binds the option to the configuration property with the given name, 
+		/// using the given AbstractConfiguration.
+		///
+		/// The configuration will automatically receive the option's argument.
+		
+	Option& callback(const AbstractOptionCallback& cb);
+		/// Binds the option to the given method.
+		///
+		/// The callback method will be called when the option
+		/// has been specified on the command line.
+		///
+		/// Usage:
+		///     callback(OptionCallback<MyApplication>(this, &MyApplication::myCallback));
+
+	Option& validator(Validator* pValidator);
+		/// Sets the validator for the given option.
+		///
+		/// The Option takes ownership of the Validator and
+		/// deletes it when it's no longer needed.
+
+	const std::string& shortName() const;
+		/// Returns the short name of the option.
+		
+	const std::string& fullName() const;
+		/// Returns the full name of the option.
+		
+	const std::string& description() const;
+		/// Returns the description of the option.
+		
+	bool required() const;
+		/// Returns true if the option is required, false if not.
+	
+	bool repeatable() const;
+		/// Returns true if the option can be specified more than
+		/// once, or false if at most once.
+	
+	bool takesArgument() const;
+		/// Returns true if the options takes an (optional) argument.
+		
+	bool argumentRequired() const;
+		/// Returns true if the argument is required.
+
+	const std::string& argumentName() const;
+		/// Returns the argument name, if specified.
+		
+	const std::string& group() const;
+		/// Returns the option group the option is part of,
+		/// or an empty string, if the option is not part of
+		/// a group.
+		
+	const std::string& binding() const;
+		/// Returns the property name the option is bound to,
+		/// or an empty string in case it is not bound.
+		
+	AbstractOptionCallback* callback() const;
+		/// Returns a pointer to the callback method for the option,
+		/// or NULL if no callback has been specified.
+		
+	Validator* validator() const;
+		/// Returns the option's Validator, if one has been specified,
+		/// or NULL otherwise.	
+		
+	AbstractConfiguration* config() const;
+		/// Returns the configuration, if specified, or NULL otherwise.
+		
+	bool matchesShort(const std::string& option) const;
+		/// Returns true if the given option string matches the
+		/// short name.
+		///
+		/// The first characters of the option string must match
+		/// the short name of the option (case sensitive),
+		/// or the option string must partially match the full
+		/// name (case insensitive).
+
+	bool matchesFull(const std::string& option) const;
+		/// Returns true if the given option string matches the
+		/// full name.
+		///
+		/// The option string must match the full
+		/// name (case insensitive).
+
+	bool matchesPartial(const std::string& option) const;
+		/// Returns true if the given option string partially matches the
+		/// full name.
+		///
+		/// The option string must partially match the full
+		/// name (case insensitive).
+		
+	void process(const std::string& option, std::string& arg) const;
+		/// Verifies that the given option string matches the
+		/// requirements of the option, and extracts the option argument,
+		/// if present.
+		///
+		/// If the option string is okay and carries an argument,
+		/// the argument is returned in arg.
+		///
+		/// Throws a MissingArgumentException if a required argument
+		/// is missing. Throws an UnexpectedArgumentException if an
+		/// argument has been found, but none is expected. 
+
+private:
+	std::string _shortName;
+	std::string _fullName;
+	std::string _description;
+	bool        _required;
+	bool        _repeatable;
+	std::string _argName;
+	bool        _argRequired;
+	std::string _group;
+	std::string _binding;
+	Validator*  _pValidator;
+	AbstractOptionCallback* _pCallback;
+	AbstractConfiguration*  _pConfig;
+};
+
+
+//
+// inlines
+//
+
+
+inline const std::string& Option::shortName() const
+{
+	return _shortName;
+}
+
+	
+inline const std::string& Option::fullName() const
+{
+	return _fullName;
+}
+
+	
+inline const std::string& Option::description() const
+{
+	return _description;
+}
+
+	
+inline bool Option::required() const
+{
+	return _required;
+}
+
+
+inline bool Option::repeatable() const
+{
+	return _repeatable;
+}
+
+	
+inline bool Option::takesArgument() const
+{
+	return !_argName.empty();
+}
+
+	
+inline bool Option::argumentRequired() const
+{
+	return _argRequired;
+}
+
+
+inline const std::string& Option::argumentName() const
+{
+	return _argName;
+}
+
+
+inline const std::string& Option::group() const
+{
+	return _group;
+}
+
+
+inline const std::string& Option::binding() const
+{
+	return _binding;
+}
+
+
+inline AbstractOptionCallback* Option::callback() const
+{
+	return _pCallback;
+}
+
+
+inline Validator* Option::validator() const
+{
+	return _pValidator;
+}
+
+
+inline AbstractConfiguration* Option::config() const
+{
+	return _pConfig;
+}
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_Option_INCLUDED
diff --git a/Poco/Util/OptionCallback.h b/Poco/Util/OptionCallback.h
new file mode 100644
index 0000000..63dd4a3
--- /dev/null
+++ b/Poco/Util/OptionCallback.h
@@ -0,0 +1,109 @@
+//
+// OptionCallback.h
+//
+// Library: Util
+// Package: Options
+// Module:  OptionCallback
+//
+// Definition of the OptionCallback class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_OptionCallback_INCLUDED
+#define Util_OptionCallback_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API AbstractOptionCallback
+	/// Base class for OptionCallback.
+{
+public:
+	virtual void invoke(const std::string& name, const std::string& value) const = 0;
+		/// Invokes the callback member function.
+		
+	virtual AbstractOptionCallback* clone() const = 0;
+		/// Creates and returns a copy of the object.
+
+	virtual ~AbstractOptionCallback();
+		/// Destroys the AbstractOptionCallback.
+
+protected:
+	AbstractOptionCallback();
+	AbstractOptionCallback(const AbstractOptionCallback&);
+};
+
+
+template <class C>
+class OptionCallback: public AbstractOptionCallback
+	/// This class is used as an argument to Option::callback().
+	///
+	/// It stores a pointer to an object and a pointer to a member
+	/// function of the object's class.
+{
+public:
+	typedef void (C::*Callback)(const std::string& name, const std::string& value);
+
+	OptionCallback(C* pObject, Callback method):
+		_pObject(pObject),
+		_method(method)
+		/// Creates the OptionCallback for the given object and member function.
+	{
+		poco_check_ptr (pObject);
+	}
+	
+	OptionCallback(const OptionCallback& cb):
+		AbstractOptionCallback(cb),
+		_pObject(cb._pObject),
+		_method(cb._method)
+		/// Creates an OptionCallback from another one.
+	{
+	}
+	
+	~OptionCallback()
+		/// Destroys the OptionCallback.
+	{
+	}
+	
+	OptionCallback& operator = (const OptionCallback& cb)
+	{
+		if (&cb != this)
+		{
+			this->_pObject = cb._pObject;
+			this->_method  = cb._method;
+		}
+		return *this;
+	}
+	
+	void invoke(const std::string& name, const std::string& value) const
+	{
+		(_pObject->*_method)(name, value);
+	}
+	
+	AbstractOptionCallback* clone() const
+	{
+		return new OptionCallback(_pObject, _method);
+	}
+	
+private:
+	OptionCallback();
+	
+	C* _pObject;
+	Callback _method;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_OptionCallback_INCLUDED
diff --git a/Poco/Util/OptionException.h b/Poco/Util/OptionException.h
new file mode 100644
index 0000000..35e7bff
--- /dev/null
+++ b/Poco/Util/OptionException.h
@@ -0,0 +1,44 @@
+//
+// OptionException.h
+//
+// Library: Util
+// Package: Options
+// Module:  OptionException
+//
+// Definition of the OptionException class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_OptionException_INCLUDED
+#define Util_OptionException_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+POCO_DECLARE_EXCEPTION(Util_API, OptionException, Poco::DataException)
+POCO_DECLARE_EXCEPTION(Util_API, UnknownOptionException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, AmbiguousOptionException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, MissingOptionException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, MissingArgumentException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, InvalidArgumentException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, UnexpectedArgumentException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, IncompatibleOptionsException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, DuplicateOptionException, OptionException)
+POCO_DECLARE_EXCEPTION(Util_API, EmptyOptionException, OptionException)
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_OptionException_INCLUDED
diff --git a/Poco/Util/OptionProcessor.h b/Poco/Util/OptionProcessor.h
new file mode 100644
index 0000000..47e5eb8
--- /dev/null
+++ b/Poco/Util/OptionProcessor.h
@@ -0,0 +1,137 @@
+//
+// OptionProcessor.h
+//
+// Library: Util
+// Package: Options
+// Module:  OptionProcessor
+//
+// Definition of the OptionProcessor class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_OptionProcessor_INCLUDED
+#define Util_OptionProcessor_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include <set>
+
+
+namespace Poco {
+namespace Util {
+
+
+class OptionSet;
+
+
+class Util_API OptionProcessor
+	/// An OptionProcessor is used to process the command line
+	/// arguments of an application.
+	///
+	/// The process() method takes an argument from the command line.
+	/// If that argument starts with an option prefix, the argument
+	/// is further processed. Otherwise, the argument is ignored and
+	/// false is returned. The argument must match one of the options
+	/// given in the OptionSet that is passed to the OptionProcessor
+	/// with the constructor. If an option is part of a group, at most
+	/// one option of the group can be passed to the OptionProcessor.
+	/// Otherwise an IncompatibleOptionsException is thrown.
+	/// If the same option is given multiple times, but the option
+	/// is not repeatable, a DuplicateOptionException is thrown.
+	/// If the option is not recognized, a UnexpectedArgumentException
+	/// is thrown.
+	/// If the option requires an argument, but none is given, an
+	/// MissingArgumentException is thrown.
+	/// If no argument is expected, but one is present, a
+	/// UnexpectedArgumentException is thrown.
+	/// If a partial option name is ambiguous, an AmbiguousOptionException
+	/// is thrown.
+	///
+	/// The OptionProcessor supports two modes: Unix mode and default mode.
+	/// In Unix mode, the option prefix is a dash '-'. A dash must be followed
+	/// by a short option name, or another dash, followed by a (partial)
+	/// long option name.
+	/// In default mode, the option prefix is a slash '/', followed by 
+	/// a (partial) long option name.
+	/// If the special option '--' is encountered in Unix mode, all following
+	/// options are ignored.
+	///
+	/// Option arguments can be specified in three ways. If a Unix short option
+	/// ("-o") is given, the argument directly follows the option name, without
+	/// any delimiting character or space ("-ovalue"). In default option mode, or if a
+	/// Unix long option ("--option") is given, the option argument is 
+	/// delimited from the option name with either an equal sign ('=') or
+	/// a colon (':'), as in "--option=value" or "/option:value". Finally,
+	/// a required option argument can be specified on the command line after the
+	/// option, delimited with a space, as in "--option value" or "-o value".
+	/// The latter only works for required option arguments, not optional ones.
+{
+public:
+	OptionProcessor(const OptionSet& options);
+		/// Creates the OptionProcessor, using the given OptionSet.
+
+	~OptionProcessor();
+		/// Destroys the OptionProcessor.
+
+	void setUnixStyle(bool flag);
+		/// Enables (flag == true) or disables (flag == false) Unix-style
+		/// option processing.
+		///
+		/// If Unix-style processing is enabled, options are expected to
+		/// begin with a single or a double dash ('-' or '--', respectively).
+		/// A single dash must be followed by a short option name. A double
+		/// dash must be followed by a (partial) full option name.
+		///
+		/// If Unix-style processing is disabled, options are expected to
+		/// begin with a slash ('/'), followed by a (partial) full option name.
+
+	bool isUnixStyle() const;
+		/// Returns true iff Unix-style option processing is enabled.
+
+	bool process(const std::string& argument, std::string& optionName, std::string& optionArg);
+		/// Examines and processes the given command line argument.
+		///
+		/// If the argument begins with an option prefix, the option is processed
+		/// and true is returned. The full option name is stored in optionName and the 
+		/// option argument, if present, is stored in optionArg.
+		///
+		/// If the option does not begin with an option prefix, false is returned.
+
+	void checkRequired() const;
+		/// Checks if all required options have been processed.
+		///
+		/// Does nothing if all required options have been processed.
+		/// Throws a MissingOptionException otherwise.
+
+private:
+	bool processUnix(const std::string& argument, std::string& optionName, std::string& optionArg);
+	bool processDefault(const std::string& argument, std::string& optionName, std::string& optionArg);
+	bool processCommon(const std::string& option, bool isShort, std::string& optionName, std::string& optionArg);
+	
+	const OptionSet& _options;
+	bool _unixStyle;
+	bool _ignore;
+	std::set<std::string> _groups;
+	std::set<std::string> _specifiedOptions;
+	std::string _deferredOption;
+};
+
+
+//
+// inlines
+//
+inline bool OptionProcessor::isUnixStyle() const
+{
+	return _unixStyle;
+}
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_OptionProcessor_INCLUDED
diff --git a/Poco/Util/OptionSet.h b/Poco/Util/OptionSet.h
new file mode 100644
index 0000000..31e36fe
--- /dev/null
+++ b/Poco/Util/OptionSet.h
@@ -0,0 +1,88 @@
+//
+// OptionSet.h
+//
+// Library: Util
+// Package: Options
+// Module:  OptionSet
+//
+// Definition of the OptionSet class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_OptionSet_INCLUDED
+#define Util_OptionSet_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/Option.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API OptionSet
+	/// A collection of Option objects.
+{
+public:
+	typedef std::vector<Option> OptionVec;
+	typedef OptionVec::const_iterator Iterator;
+
+	OptionSet();
+		/// Creates the OptionSet.
+
+	OptionSet(const OptionSet& options);
+		/// Creates an option set from another one.
+
+	~OptionSet();
+		/// Destroys the OptionSet.
+
+	OptionSet& operator = (const OptionSet& options);
+		/// Assignment operator.
+
+	void addOption(const Option& option);
+		/// Adds an option to the collection.
+	
+	bool hasOption(const std::string& name, bool matchShort = false) const;
+		/// Returns a true iff an option with the given name exists.
+		///
+		/// The given name can either be a fully specified short name,
+		/// or a partially specified full name. If a partial name
+		/// matches more than one full name, false is returned.
+		/// The name must either match the short or full name of an
+		/// option. Comparison case sensitive for the short name and
+		/// not case sensitive for the full name.
+		
+	const Option& getOption(const std::string& name, bool matchShort = false) const;
+		/// Returns a reference to the option with the given name.
+		///
+		/// The given name can either be a fully specified short name,
+		/// or a partially specified full name.
+		/// The name must either match the short or full name of an
+		/// option. Comparison case sensitive for the short name and
+		/// not case sensitive for the full name.
+		/// Throws a NotFoundException if no matching option has been found.
+		/// Throws an UnknownOptionException if a partial full name matches
+		/// more than one option.
+
+	Iterator begin() const;
+		/// Supports iterating over all options.
+		
+	Iterator end() const;
+		/// Supports iterating over all options.
+	
+private:	
+	OptionVec _options;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_OptionSet_INCLUDED
diff --git a/Poco/Util/PropertyFileConfiguration.h b/Poco/Util/PropertyFileConfiguration.h
new file mode 100644
index 0000000..bf478d9
--- /dev/null
+++ b/Poco/Util/PropertyFileConfiguration.h
@@ -0,0 +1,99 @@
+//
+// PropertyFileConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  PropertyFileConfiguration
+//
+// Definition of the PropertyFileConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_PropertyFileConfiguration_INCLUDED
+#define Util_PropertyFileConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/MapConfiguration.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API PropertyFileConfiguration: public MapConfiguration
+	/// This implementation of a Configuration reads properties
+	/// from a Java-style properties file.
+	///
+	/// The file syntax is implemented as follows.
+	///   - a line starting with a hash '#' or exclamation mark '!' is treated as a comment and ignored
+	///   - every other line denotes a property assignment in the form
+	///     <key> = <value> or
+	///     <key> : <value>
+	///
+	/// Keys and values may contain special characters represented by the following escape sequences:
+	///   - \t: tab (0x09)
+	///   - \n: line feed (0x0a)
+	///   - \r: carriage return (0x0d)
+	///   - \f: form feed (0x0c)
+	///
+	/// For every other sequence that starts with a backslash, the backslash is removed.
+	/// Therefore, the sequence \a would just yield an 'a'.
+	///
+	/// A value can spread across multiple lines if the last character in a line (the character
+	/// immediately before the carriage return or line feed character) is a single backslash.
+	///
+	/// Property names are case sensitive. Leading and trailing whitespace is
+	/// removed from both keys and values. A property name can neither contain
+	/// a colon ':' nor an equal sign '=' character.
+{
+public:
+	PropertyFileConfiguration();
+		/// Creates an empty PropertyFileConfiguration.
+
+	PropertyFileConfiguration(std::istream& istr);
+		/// Creates an PropertyFileConfiguration and loads the configuration data
+		/// from the given stream, which must be in properties file format.
+		
+	PropertyFileConfiguration(const std::string& path);
+		/// Creates an PropertyFileConfiguration and loads the configuration data
+		/// from the given file, which must be in properties file format.
+		
+	void load(std::istream& istr);
+		/// Loads the configuration data from the given stream, which 
+		/// must be in properties file format.
+		
+	void load(const std::string& path);
+		/// Loads the configuration data from the given file, which 
+		/// must be in properties file format.
+		
+	void save(std::ostream& ostr) const;
+		/// Writes the configuration data to the given stream.
+		///
+		/// The data is written as a sequence of statements in the form
+		/// <key>: <value>
+		/// separated by a newline character.
+
+	void save(const std::string& path) const;
+		/// Writes the configuration data to the given file.
+
+protected:
+	~PropertyFileConfiguration();
+	
+private:
+	void parseLine(std::istream& istr);
+	static int readChar(std::istream& istr);
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_PropertyFileConfiguration_INCLUDED
diff --git a/Poco/Util/RegExpValidator.h b/Poco/Util/RegExpValidator.h
new file mode 100644
index 0000000..81e5d4a
--- /dev/null
+++ b/Poco/Util/RegExpValidator.h
@@ -0,0 +1,54 @@
+//
+// RegExpValidator.h
+//
+// Library: Util
+// Package: Options
+// Module:  RegExpValidator
+//
+// Definition of the RegExpValidator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_RegExpValidator_INCLUDED
+#define Util_RegExpValidator_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/Validator.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API RegExpValidator: public Validator
+	/// This validator matches the option value against
+	/// a regular expression.
+{
+public:
+	RegExpValidator(const std::string& regexp);
+		/// Creates the RegExpValidator, using the given regular expression.
+
+	~RegExpValidator();
+		/// Destroys the RegExpValidator.
+
+	void validate(const Option& option, const std::string& value);
+		/// Validates the value for the given option by
+		/// matching it with the regular expression.
+
+private:
+	RegExpValidator();
+
+	std::string _regexp;	
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_RegExpValidator_INCLUDED
diff --git a/Poco/Util/ServerApplication.h b/Poco/Util/ServerApplication.h
new file mode 100644
index 0000000..b64077e
--- /dev/null
+++ b/Poco/Util/ServerApplication.h
@@ -0,0 +1,287 @@
+//
+// ServerApplication.h
+//
+// Library: Util
+// Package: Application
+// Module:  ServerApplication
+//
+// Definition of the ServerApplication class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_ServerApplication_INCLUDED
+#define Util_ServerApplication_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/Application.h"
+#include "Poco/Event.h"
+#if defined(POCO_OS_FAMILY_WINDOWS)
+#include "Poco/NamedEvent.h"
+#endif
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API ServerApplication: public Application
+	/// A subclass of the Application class that is used
+	/// for implementing server applications.
+	///
+	/// A ServerApplication allows for the application
+	/// to run as a Windows service or as a Unix daemon
+	/// without the need to add extra code.
+	///
+	/// For a ServerApplication to work both from the command line
+	/// and as a daemon or service, a few rules must be met:
+	///   - Subsystems must be registered in the constructor.
+	///   - All non-trivial initializations must be made in the
+	///     initialize() method.
+	///   - At the end of the main() method, waitForTerminationRequest()
+	///     should be called.
+	///   - New threads must only be created in initialize() or main() or
+	///     methods called from there, but not in the application class'
+	///     constructor or in the constructor of instance variables.
+	///     The reason for this is that fork() will be called in order to
+	///     create the daemon process, and threads created prior to calling
+	///     fork() won't be taken over to the daemon process.
+	///   - The main(argc, argv) function must look as follows:
+	///
+	///   int main(int argc, char** argv)
+	///   {
+	///       MyServerApplication app;
+	///       return app.run(argc, argv);
+	///   }
+	///
+	/// The POCO_SERVER_MAIN macro can be used to implement main(argc, argv).
+	/// If POCO has been built with POCO_WIN32_UTF8, POCO_SERVER_MAIN supports
+	/// Unicode command line arguments.
+	///
+	/// On Windows platforms, an application built on top of the
+	/// ServerApplication class can be run both from the command line
+	/// or as a service.
+	///
+	/// To run an application as a Windows service, it must be registered
+	/// with the Windows Service Control Manager (SCM). To do this, the application
+	/// can be started from the command line, with the /registerService option
+	/// specified. This causes the application to register itself with the
+	/// SCM, and then exit. Similarly, an application registered as a service can
+	/// be unregistered, by specifying the /unregisterService option.
+	/// The file name of the application executable (excluding the .exe suffix)
+	/// is used as the service name. Additionally, a more user-friendly name can be
+	/// specified, using the /displayName option (e.g., /displayName="Demo Service")
+	/// and a service description can be added with the /description option.
+	/// The startup mode (automatic or manual) for the service can be specified
+	/// with the /startup option.
+	///
+	/// An application can determine whether it is running as a service by checking
+	/// for the "application.runAsService" configuration property.
+	/// 
+	///     if (config().getBool("application.runAsService", false))
+	///     {
+	///         // do service specific things
+	///     }
+	///
+	/// Note that the working directory for an application running as a service
+	/// is the Windows system directory (e.g., C:\Windows\system32). Take this
+	/// into account when working with relative filesystem paths. Also, services
+	/// run under a different user account, so an application that works when
+	/// started from the command line may fail to run as a service if it depends
+	/// on a certain environment (e.g., the PATH environment variable).
+	///
+	/// An application registered as a Windows service can be started
+	/// with the NET START <name> command and stopped with the NET STOP <name>
+	/// command. Alternatively, the Services MMC applet can be used.
+	///
+	/// On Unix platforms, an application built on top of the ServerApplication
+	/// class can be optionally run as a daemon by giving the --daemon
+	/// command line option. A daemon, when launched, immediately
+	/// forks off a background process that does the actual work. After launching
+	/// the background process, the foreground process exits.
+	/// 
+	/// After the initialization is complete, but before entering the main() method,
+	/// the current working directory for the daemon process is changed to the root
+	/// directory ("/"), as it is common practice for daemon processes. Therefore, be
+	/// careful when working with files, as relative paths may not point to where
+	/// you expect them point to.
+	///
+	/// An application can determine whether it is running as a daemon by checking
+	/// for the "application.runAsDaemon" configuration property.
+	///
+	///     if (config().getBool("application.runAsDaemon", false))
+	///     {
+	///         // do daemon specific things
+	///     }
+	///
+	/// When running as a daemon, specifying the --pidfile option (e.g.,
+	/// --pidfile=/var/run/sample.pid) may be useful to record the process ID of 
+	/// the daemon in a file. The PID file will be removed when the daemon process 
+	/// terminates (but not, if it crashes).
+{
+public:
+	ServerApplication();
+		/// Creates the ServerApplication.
+
+	~ServerApplication();
+		/// Destroys the ServerApplication.
+		
+	bool isInteractive() const;
+		/// Returns true if the application runs from the command line.
+		/// Returns false if the application runs as a Unix daemon
+		/// or Windows service.
+
+	int run(int argc, char** argv);
+		/// Runs the application by performing additional initializations
+		/// and calling the main() method.
+		
+	int run(const std::vector<std::string>& args);
+		/// Runs the application by performing additional initializations
+		/// and calling the main() method.
+
+#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
+	int run(int argc, wchar_t** argv);
+		/// Runs the application by performing additional initializations
+		/// and calling the main() method.
+		///
+		/// This Windows-specific version of init is used for passing
+		/// Unicode command line arguments from wmain().
+#endif
+
+	static void terminate();
+		/// Sends a friendly termination request to the application.
+		/// If the application's main thread is waiting in 
+		/// waitForTerminationRequest(), this method will return
+		/// and the application can shut down.
+		
+protected:
+	int run();
+	void waitForTerminationRequest();
+#if !defined(_WIN32_WCE)
+	void defineOptions(OptionSet& options);
+#endif
+
+private:
+#if defined(POCO_VXWORKS)
+	static Poco::Event _terminate;
+#elif defined(POCO_OS_FAMILY_UNIX)
+	void handleDaemon(const std::string& name, const std::string& value);
+	void handleUMask(const std::string& name, const std::string& value);
+	void handlePidFile(const std::string& name, const std::string& value);
+	bool isDaemon(int argc, char** argv);
+	void beDaemon();
+#if POCO_OS == POCO_OS_ANDROID
+	static Poco::Event _terminate;
+#endif
+#elif defined(POCO_OS_FAMILY_WINDOWS)
+#if !defined(_WIN32_WCE)
+	enum Action
+	{
+		SRV_RUN,
+		SRV_REGISTER,
+		SRV_UNREGISTER
+	};
+	static BOOL __stdcall ConsoleCtrlHandler(DWORD ctrlType);
+	static void __stdcall ServiceControlHandler(DWORD control);
+#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
+	static void __stdcall ServiceMain(DWORD argc, LPWSTR* argv);
+#else
+	static void __stdcall ServiceMain(DWORD argc, LPTSTR* argv);
+#endif
+
+	bool hasConsole();
+	bool isService();
+	void beService();
+	void registerService();
+	void unregisterService();
+	void handleRegisterService(const std::string& name, const std::string& value);
+	void handleUnregisterService(const std::string& name, const std::string& value);
+	void handleDisplayName(const std::string& name, const std::string& value);
+	void handleDescription(const std::string& name, const std::string& value);
+	void handleStartup(const std::string& name, const std::string& value);	
+	
+	Action      _action;
+	std::string _displayName;
+	std::string _description;
+	std::string _startup;
+
+	static Poco::Event           _terminated;
+	static SERVICE_STATUS        _serviceStatus; 
+	static SERVICE_STATUS_HANDLE _serviceStatusHandle; 
+#endif // _WIN32_WCE
+	static Poco::NamedEvent      _terminate;
+#endif
+};
+
+
+} } // namespace Poco::Util
+
+
+//
+// Macro to implement main()
+//
+#if defined(_WIN32) && defined(POCO_WIN32_UTF8)
+	#define POCO_SERVER_MAIN(App) \
+	int wmain(int argc, wchar_t** argv)	\
+	{									\
+		try 							\
+		{								\
+			App app;					\
+			return app.run(argc, argv);	\
+		}								\
+		catch (Poco::Exception& exc)	\
+		{								\
+			std::cerr << exc.displayText() << std::endl;	\
+			return Poco::Util::Application::EXIT_SOFTWARE; 	\
+		}								\
+	}
+#elif defined(POCO_VXWORKS)
+	#define POCO_SERVER_MAIN(App) \
+	int pocoSrvMain(const char* appName, ...) 				\
+	{ 														\
+		std::vector<std::string> args; 						\
+		args.push_back(std::string(appName)); 				\
+		va_list vargs; 										\
+		va_start(vargs, appName); 							\
+		const char* arg = va_arg(vargs, const char*); 		\
+		while (arg) 										\
+		{ 													\
+			args.push_back(std::string(arg));				\
+			arg = va_arg(vargs, const char*); 				\
+		} 													\
+		va_end(vargs); 										\
+		try													\
+		{ 													\
+			App app;										\
+			return app.run(args); 							\
+		} 													\
+		catch (Poco::Exception& exc)						\
+		{													\
+			std::cerr << exc.displayText() << std::endl;	\
+			return Poco::Util::Application::EXIT_SOFTWARE; 	\
+		}													\
+	}
+#else
+	#define POCO_SERVER_MAIN(App) \
+	int main(int argc, char** argv)		\
+	{									\
+		try 							\
+		{								\
+			App app;					\
+			return app.run(argc, argv);	\
+		}								\
+		catch (Poco::Exception& exc)	\
+		{								\
+			std::cerr << exc.displayText() << std::endl;	\
+			return Poco::Util::Application::EXIT_SOFTWARE; 	\
+		}								\
+	}
+#endif
+
+
+#endif // Util_ServerApplication_INCLUDED
diff --git a/Poco/Util/Subsystem.h b/Poco/Util/Subsystem.h
new file mode 100644
index 0000000..ce6eda2
--- /dev/null
+++ b/Poco/Util/Subsystem.h
@@ -0,0 +1,98 @@
+//
+// Subsystem.h
+//
+// Library: Util
+// Package: Application
+// Module:  Subsystem
+//
+// Definition of the Subsystem class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_Subsystem_INCLUDED
+#define Util_Subsystem_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Application;
+class OptionSet;
+
+
+class Util_API Subsystem: public Poco::RefCountedObject
+	/// Subsystems extend an application in a modular way.
+	///
+	/// The Subsystem class provides a common interface
+	/// for subsystems so that subsystems can be automatically
+	/// initialized at startup and uninitialized at shutdown.
+	///
+	/// Subsystems should also support dynamic reconfiguration,
+	/// so that they can be reconfigured anytime during the
+	/// life of a running application.
+	///
+	/// The degree to which dynamic reconfiguration is supported
+	/// is up to the actual subsystem implementation. It can
+	/// range from ignoring the reconfiguration request (not
+	/// recommended), to changing certain settings that affect
+	/// the performance, to a complete reinitialization.
+{
+public:
+	Subsystem();
+		/// Creates the Subsystem.
+
+	virtual const char* name() const = 0;
+		/// Returns the name of the subsystem.
+		/// Must be implemented by subclasses.
+
+protected:
+	virtual void initialize(Application& app) = 0;
+		/// Initializes the subsystem.
+
+	virtual void uninitialize() = 0;
+		/// Uninitializes the subsystem.
+
+	virtual void reinitialize(Application& app);
+		/// Re-initializes the subsystem.
+		///
+		/// The default implementation just calls
+		/// uninitialize() followed by initialize().
+		/// Actual implementations might want to use a
+		/// less radical and possibly more performant
+		/// approach.
+
+	virtual void defineOptions(OptionSet& options);
+		/// Called before the Application's command line processing begins.
+		/// If a subsystem wants to support command line arguments,
+		/// it must override this method.
+		/// The default implementation does not define any options.
+		///
+		/// To effectively handle options, a subsystem should either bind
+		/// the option to a configuration property or specify a callback
+		/// to handle the option.
+
+	virtual ~Subsystem();
+		/// Destroys the Subsystem.
+
+	friend class Application;
+
+private:
+	Subsystem(const Subsystem&);
+	Subsystem& operator = (const Subsystem&);
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_Subsystem_INCLUDED
diff --git a/Poco/Util/SystemConfiguration.h b/Poco/Util/SystemConfiguration.h
new file mode 100644
index 0000000..e80dc6e
--- /dev/null
+++ b/Poco/Util/SystemConfiguration.h
@@ -0,0 +1,99 @@
+//
+// SystemConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  SystemConfiguration
+//
+// Definition of the SystemConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_SystemConfiguration_INCLUDED
+#define Util_SystemConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API SystemConfiguration: public AbstractConfiguration
+	/// This class implements a Configuration interface to 
+	/// various system properties and environment variables.
+	///
+	/// The following properties are supported:
+	///   - system.osName: the operating system name
+	///   - system.osVersion: the operating system version
+	///   - system.osArchitecture: the operating system architecture
+	///   - system.nodeName: the node (or host) name
+	///   - system.nodeId: system ID, based on the Ethernet address (format "xxxxxxxxxxxx") 
+	///     of the first Ethernet adapter found on the system.
+	///   - system.currentDir: the current working directory
+	///   - system.homeDir: the user's home directory
+	///   - system.configHomeDir: the base directory relative to which user specific configuration files should be stored
+	///   - system.cacheHomeDir: the base directory relative to which user specific non-essential data files should be stored
+	///   - system.dataHomeDir: the base directory relative to which user specific data files should be stored
+	///   - system.tempHomeDir: the base directory relative to which user-specific temporary files and other file objects should be placed
+	///   - system.tempDir: the system's temporary directory
+	///   - system.configDir: the system's configuration directory
+	///   - system.dateTime: the current UTC date and time, formatted in ISO 8601 format.
+	///   - system.pid: the current process ID.
+	///   - system.env.<NAME>: the environment variable with the given <NAME>.
+	///
+	/// An attempt to set a system variable will result in an
+	/// InvalidAccessException being thrown.
+	/// 
+	/// Enumerating environment variables is not supported. 
+	/// An attempt to call keys("system.env") will return an empty range. 
+	///
+	/// Removing key is not supported. An attempt to remove a key results
+	/// in a NotImplementedException being thrown.
+{
+public:
+	SystemConfiguration();
+		/// Creates the SystemConfiguration.
+
+protected:
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	~SystemConfiguration();
+
+private:
+	static bool getEnv(const std::string& name, std::string& value);
+
+	static const std::string OSNAME;
+	static const std::string OSVERSION;
+	static const std::string OSARCHITECTURE;
+	static const std::string NODENAME;
+	static const std::string NODEID;
+	static const std::string CURRENTDIR;
+	static const std::string HOMEDIR;
+	static const std::string CONFIGHOMEDIR;
+	static const std::string CACHEHOMEDIR;
+	static const std::string DATAHOMEDIR;
+	static const std::string TEMPHOMEDIR;
+	static const std::string TEMPDIR;
+	static const std::string CONFIGDIR;
+	static const std::string DATETIME;
+#if !defined(POCO_VXWORKS)
+	static const std::string PID;
+#endif
+	static const std::string ENV;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_SystemConfiguration_INCLUDED
diff --git a/Poco/Util/Timer.h b/Poco/Util/Timer.h
new file mode 100644
index 0000000..a3edd47
--- /dev/null
+++ b/Poco/Util/Timer.h
@@ -0,0 +1,169 @@
+//
+// Timer.h
+//
+// Library: Util
+// Package: Timer
+// Module:  Timer
+//
+// Definition of the Timer class.
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_Timer_INCLUDED
+#define Util_Timer_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/TimerTask.h"
+#include "Poco/TimedNotificationQueue.h"
+#include "Poco/Thread.h"
+#include "Poco/Runnable.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API Timer: protected Poco::Runnable
+	/// A Timer allows to schedule tasks (TimerTask objects) for future execution 
+	/// in a background thread. Tasks may be scheduled for one-time execution, 
+	/// or for repeated execution at regular intervals. 
+	///
+	/// The Timer object creates a thread that executes all scheduled tasks
+	/// sequentially. Therefore, tasks should complete their work as quickly
+	/// as possible, otherwise subsequent tasks may be delayed.
+	///
+	/// Timer is safe for multithreaded use - multiple threads can schedule
+	/// new tasks simultaneously.
+	///
+	/// Acknowledgement: The interface of this class has been inspired by
+	/// the java.util.Timer class from Java 1.3.
+{
+public:
+	Timer();
+		/// Creates the Timer.
+	
+	explicit Timer(Poco::Thread::Priority priority);
+		/// Creates the Timer, using a timer thread with
+		/// the given priority.
+	
+	~Timer();
+		/// Destroys the Timer, cancelling all pending tasks.
+		
+	void cancel(bool wait = false);
+		/// Cancels all pending tasks.
+		///
+		/// If a task is currently running, it is allowed to finish.
+		///
+		/// Task cancellation is done asynchronously. If wait
+		/// is false, cancel() returns immediately and the
+		/// task queue will be purged as soon as the currently
+		/// running task finishes. If wait is true, waits
+		/// until the queue has been purged.
+	
+	void schedule(TimerTask::Ptr pTask, Poco::Timestamp time);
+		/// Schedules a task for execution at the specified time.
+		///
+		/// If the time lies in the past, the task is executed
+		/// immediately.
+		///
+		/// Note: the relative time the task will be executed
+		/// won't change if the system's time changes. If the
+		/// given time is 10 seconds in the future at the point
+		/// schedule() is called, the task will be executed 10
+		/// seconds later, even if the system time changes in
+		/// between.
+
+	void schedule(TimerTask::Ptr pTask, Poco::Clock clock);
+		/// Schedules a task for execution at the specified time.
+		///
+		/// If the time lies in the past, the task is executed
+		/// immediately.
+		
+	void schedule(TimerTask::Ptr pTask, long delay, long interval);
+		/// Schedules a task for periodic execution.
+		///
+		/// The task is first executed after the given delay.
+		/// Subsequently, the task is executed periodically with
+		/// the given interval in milliseconds between invocations.
+
+	void schedule(TimerTask::Ptr pTask, Poco::Timestamp time, long interval);
+		/// Schedules a task for periodic execution.
+		///
+		/// The task is first executed at the given time.
+		/// Subsequently, the task is executed periodically with
+		/// the given interval in milliseconds between invocations.
+		///
+		/// Note: the relative time the task will be executed
+		/// won't change if the system's time changes. If the
+		/// given time is 10 seconds in the future at the point
+		/// schedule() is called, the task will be executed 10
+		/// seconds later, even if the system time changes in
+		/// between.
+
+	void schedule(TimerTask::Ptr pTask, Poco::Clock clock, long interval);
+		/// Schedules a task for periodic execution.
+		///
+		/// The task is first executed at the given time.
+		/// Subsequently, the task is executed periodically with
+		/// the given interval in milliseconds between invocations.
+		
+	void scheduleAtFixedRate(TimerTask::Ptr pTask, long delay, long interval);
+		/// Schedules a task for periodic execution at a fixed rate.
+		///
+		/// The task is first executed after the given delay.
+		/// Subsequently, the task is executed periodically 
+		/// every number of milliseconds specified by interval.
+		///
+		/// If task execution takes longer than the given interval,
+		/// further executions are delayed.
+
+	void scheduleAtFixedRate(TimerTask::Ptr pTask, Poco::Timestamp time, long interval);
+		/// Schedules a task for periodic execution at a fixed rate.
+		///
+		/// The task is first executed at the given time.
+		/// Subsequently, the task is executed periodically 
+		/// every number of milliseconds specified by interval.
+		///
+		/// If task execution takes longer than the given interval,
+		/// further executions are delayed.
+		///
+		/// Note: the relative time the task will be executed
+		/// won't change if the system's time changes. If the
+		/// given time is 10 seconds in the future at the point
+		/// scheduleAtFixedRate() is called, the task will be executed 10
+		/// seconds later, even if the system time changes in
+		/// between.
+
+	void scheduleAtFixedRate(TimerTask::Ptr pTask, Poco::Clock clock, long interval);
+		/// Schedules a task for periodic execution at a fixed rate.
+		///
+		/// The task is first executed at the given time.
+		/// Subsequently, the task is executed periodically 
+		/// every number of milliseconds specified by interval.
+		///
+		/// If task execution takes longer than the given interval,
+		/// further executions are delayed.
+
+protected:
+	void run();
+	static void validateTask(const TimerTask::Ptr& pTask);
+	
+private:
+	Timer(const Timer&);
+	Timer& operator = (const Timer&);
+	
+	Poco::TimedNotificationQueue _queue;
+	Poco::Thread _thread;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_Timer_INCLUDED
diff --git a/Poco/Util/TimerTask.h b/Poco/Util/TimerTask.h
new file mode 100644
index 0000000..05263f6
--- /dev/null
+++ b/Poco/Util/TimerTask.h
@@ -0,0 +1,98 @@
+//
+// TimerTask.h
+//
+// Library: Util
+// Package: Timer
+// Module:  TimerTask
+//
+// Definition of the TimerTask class.
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_TimerTask_INCLUDED
+#define Util_TimerTask_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Runnable.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include "Poco/Timestamp.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API TimerTask: public Poco::RefCountedObject, public Poco::Runnable
+	/// A task that can be scheduled for one-time or 
+	/// repeated execution by a Timer.
+	///
+	/// This is an abstract class. Subclasses must override the run() member
+	/// function to implement the actual task logic.
+{
+public:
+	typedef Poco::AutoPtr<TimerTask> Ptr;
+	
+	TimerTask();
+		/// Creates the TimerTask.
+		
+	void cancel();
+		/// Cancels the execution of the timer.
+		/// If the task has been scheduled for one-time execution and has 
+		/// not yet run, or has not yet been scheduled, it will never run. 
+		/// If the task has been scheduled for repeated execution, it will never 
+		/// run again. If the task is running when this call occurs, the task 
+		/// will run to completion, but will never run again.
+		///
+		/// Warning: A TimerTask that has been cancelled must not be scheduled again.
+		/// An attempt to do so results in a Poco::Util::IllegalStateException being thrown.
+	
+	bool isCancelled() const;
+		/// Returns true iff the TimerTask has been cancelled by a call
+		/// to cancel().
+	
+	Poco::Timestamp lastExecution() const;
+		/// Returns the time of the last execution of the timer task.
+		///
+		/// Returns 0 if the timer has never been executed.
+		
+protected:
+	~TimerTask();
+		/// Destroys the TimerTask.
+	
+private:
+	TimerTask(const TimerTask&);
+	TimerTask& operator = (const TimerTask&);
+	
+	Poco::Timestamp _lastExecution;
+	bool _isCancelled;
+	
+	friend class TaskNotification;
+};
+
+
+//
+// inlines
+//
+inline bool TimerTask::isCancelled() const
+{
+	return _isCancelled;
+}
+
+
+inline Poco::Timestamp TimerTask::lastExecution() const
+{
+	return _lastExecution;
+}
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_TimerTask_INCLUDED
diff --git a/Poco/Util/TimerTaskAdapter.h b/Poco/Util/TimerTaskAdapter.h
new file mode 100644
index 0000000..32ff3b9
--- /dev/null
+++ b/Poco/Util/TimerTaskAdapter.h
@@ -0,0 +1,69 @@
+//
+// TimerTaskAdapter.h
+//
+// Library: Util
+// Package: Timer
+// Module:  TimerTaskAdapter
+//
+// Definition of the TimerTaskAdapter class template.
+//
+// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_TimerTaskAdapter_INCLUDED
+#define Util_TimerTaskAdapter_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/TimerTask.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+template <class C>
+class TimerTaskAdapter: public TimerTask
+	/// This class template simplifies the implementation
+	/// of TimerTask objects by allowing a member function
+	/// of an object to be called as task. 
+{
+public:
+	typedef void (C::*Callback)(TimerTask&);
+	
+	TimerTaskAdapter(C& object, Callback method): _pObject(&object), _method(method)
+		/// Creates the TimerTaskAdapter, using the given 
+		/// object and its member function as task target.
+		///
+		/// The member function must accept one argument,
+		/// a reference to a TimerTask object.
+	{
+	}
+	
+	void run()
+	{
+		(_pObject->*_method)(*this);
+	}
+			
+protected:
+	~TimerTaskAdapter()
+		/// Destroys the TimerTaskAdapter.
+	{
+	}
+	
+private:
+	TimerTaskAdapter();
+
+	C*       _pObject;
+	Callback _method;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_TimerTaskAdapter_INCLUDED
diff --git a/Poco/Util/Units.h b/Poco/Util/Units.h
new file mode 100644
index 0000000..e7f3869
--- /dev/null
+++ b/Poco/Util/Units.h
@@ -0,0 +1,1298 @@
+//
+// Units.h
+//
+// Library: Util
+// Package: Units
+// Module:  Units
+//
+// Definitions for the C++ Units library.
+//
+// Copyright (c) 2007-2010, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+// Adapted for POCO from the following source:
+//
+// C++ Units by Calum Grant
+//
+// Written by Calum Grant
+// Copyright (C) Calum Grant 2007
+//
+// Home page: http://calumgrant.net/units
+// File location: http://calumgrant.net/units/units.hpp
+// Manual: http://calumgrant.net/units/units.html
+//
+// Copying permitted under the terms of the Boost software license.
+//
+
+
+#ifndef Util_Units_INCLUDED
+#define Util_Units_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include <cmath>
+
+
+namespace Poco {
+namespace Util {
+namespace Units {
+
+
+namespace Internal
+{
+	template <typename T1, typename T2> struct Convert;	
+	struct None; 
+	template <int Num, int Den, int Div=Num/Den, int Mod=Num%Den>
+	struct FixedPower;
+}
+
+
+template <typename Unit1, typename Unit2>
+struct Compose;
+	/// Construct a unit equivalent to Unit1*Unit2
+
+
+template <typename U, int Num, int Den = 1>
+struct Scale;
+	/// Constructs a unit equivalent to U*Num/Den
+
+
+template <typename U, int Num, int Den = 1>
+struct Translate;
+	/// Constructs a Unit equivalent to U+Num/Den
+
+
+template <typename U, int Num, int Den = 1>
+struct Power;
+	/// Constructs a Unit equivalent to U^(Num/Den)
+
+
+typedef Power<Internal::None, 0> Unit;
+	/// A unit which is effectively no units at all.
+
+
+template <typename V, typename U>
+class Value
+	/// A Value with a unit.
+	///	  - V is the type you are storing
+	///   - U is the unit of the Value
+	///
+	/// This class is usually not used directly;
+	/// client code should use the typedef'd 
+	/// instantiations defined in the Values and
+	/// Constants namespace.
+	///
+	/// Example:
+	///
+	///   using namespace Poco::Util::Units::Values;
+	///
+	///   std::cout << "One mile is " << km(mile(1)) << std::endl;
+	///       // Output: One mile is 1.60934 km
+	///
+	///   std::cout << "Flow rate is " << m3(mile(1)*inch(80)*foot(9))/s(minute(5));
+	///       // Output: Flow rate is 29.9026 (m)^3.(s)^-1
+	///
+	///   hours h;
+	///   h = cm(3);   // Compile-time error: incompatible units
+	///   h = 4;       // Compile-time error: 4 of what?
+	///   h = days(4); // Ok: h is 96 hours
+{
+public:
+	typedef V ValueType;
+	typedef U Unit;
+
+	Value(): _rep() 
+	{ 
+	}
+
+	explicit Value(const ValueType& v): _rep(v) 
+	{ 
+	}
+	
+	template <typename OV, typename OU>
+	Value(const Value<OV, OU>& v):
+		_rep(Internal::Convert<OU, U>::fn(v.get()))
+	{
+	}
+
+	const ValueType& get() const 
+	{ 
+		return _rep; 
+	}
+	 
+	template <typename OV, typename OU>
+	Value& operator = (const Value<OV, OU>& other)
+	{
+		_rep = Value(other).get();
+		return *this;
+	}
+
+	template <typename OV, typename OU>
+	Value operator + (const Value<OV, OU>& other) const
+	{
+		return Value(get() + Value(other).get());
+	}
+
+	template <typename OV, typename OU>
+	Value& operator += (const Value<OV, OU>& other)
+	{
+		_rep += Value(other).get();
+		return *this;
+	}
+
+	template <typename OV, typename OU>
+	Value& operator -= (const Value<OV, OU>& other)
+	{
+		_rep -= Value(other).get();
+		return *this;
+	}
+
+	template <typename OV, typename OU>
+	Value operator - (const Value<OV, OU>& other) const
+	{
+		return Value(get() - Value(other).get());
+	}
+
+	Value operator - () const
+	{
+		return Value(-get());
+	}
+
+	template <typename OV, typename OU>
+	Value<V, Compose<U, OU> >
+		operator * (const Value<OV, OU>& other) const
+	{
+		return Value<V, Compose<U, OU> >(get() * other.get());
+	}
+
+	Value operator * (const ValueType& v) const
+	{
+		return Value(get() * v);
+	}
+
+	Value& operator *= (const ValueType& v)
+	{
+		_rep *= v;
+		return *this;
+	}
+
+	template <typename OV, typename OU>
+	Value<V, Compose<U, Power<OU, -1> > > operator / (const Value<OV, OU>& other) const
+	{
+		return Value<V, Compose<U, Power<OU, -1> > >(get() / other.get());
+	}
+
+	Value operator / (const ValueType& v) const
+	{
+		return Value(get() / v);
+	}
+
+	Value& operator /= (const ValueType& v)
+	{
+		_rep /= v;
+		return *this;
+	}
+
+	template <typename OV, typename OU>
+	bool operator == (const Value<OV, OU>& other) const
+	{
+		return get() == Value(other).get();
+	}
+
+	template <typename OV, typename OU>
+	bool operator != (const Value<OV, OU>& other) const
+	{
+		return get() != Value(other).get();
+	}
+
+	template <typename OV, typename OU>
+	bool operator < (const Value<OV, OU>& other) const
+	{
+		return get() < Value(other).get();
+	}
+
+	template <typename OV, typename OU>
+	bool operator <= (const Value<OV, OU>& other) const
+	{
+		return get() <= Value(other).get();
+	}
+
+	template <typename OV, typename OU>
+	bool operator > (const Value<OV, OU>& other) const
+	{
+		return get() > Value(other).get();
+	}
+
+	template <typename OV, typename OU>
+	bool operator >= (const Value<OV, OU>& other) const
+	{
+		return get() >= Value(other).get();
+	}
+
+	Value& operator ++ () 
+	{ 
+		++_rep; 
+		return *this; 
+	}
+
+	Value operator ++ (int) 
+	{ 
+		Value v = *this; 
+		++_rep; 
+		return v; 
+	}
+
+	Value& operator -- () 
+	{ 
+		--_rep; 
+		return *this; 
+	}
+
+	Value operator -- (int) 
+	{ 
+		Value v = *this; 
+		--_rep; 
+		return v; 
+	}
+
+private:
+	ValueType _rep;
+};
+
+
+template <typename V, typename U>
+Value<V, Power<U, -1> > operator / (const V& a, const Value<V, U>& b)
+{
+	return Value<V, Power<U, -1> >(a / b.get());
+}
+
+
+template <typename V, typename U>
+Value<V, U > operator * (const V& a, const Value<V, U>& b)
+{
+	return Value<V, U>(a * b.get());
+}
+
+
+template <typename V, typename U>
+Value<V, Power<U, 1, 2> > sqrt(const Value<V, U>& a)
+{
+	return Value<V, Power<U, 1, 2> >(std::sqrt(a.get()));
+}
+
+
+template <typename V, typename U>
+Value<V, Power<U, 2, 1> > square(const Value<V, U>& a)
+{
+	return Value<V, Power<U, 2, 1> >(std::pow(a.get(), 2));
+}
+
+
+template <typename V, typename U>
+Value<V, Power<U, 3, 1> > cube(const Value<V, U>& a)
+{
+	return Value<V, Power<U, 3, 1> >(std::pow(a.get(), 3));
+}
+
+
+template <int Num, int Den, typename V, typename U>
+Value<V, Power<U, Num, Den> > raise(const Value<V, U>& a)
+{
+	return Value<V, Power<U, Num, Den> >(Internal::FixedPower<Num, Den>::Power(a.get()));
+}
+
+
+namespace Internal
+{
+	template <typename T1, typename T2>
+	struct Convertible;
+
+	template <typename U>
+	struct ScalingFactor;
+
+	template <typename T1, typename T2> 
+	struct Convert3
+		/// Converts T1 to T2.
+		/// Stage 3 - performed after Stage 1 and Stage 2.
+		/// The reason we perform Convert in stages is so that the compiler
+		/// can resolve templates in the order we want it to.
+	{
+		template <typename V>
+		static V fn(const V& v)
+			/// The default implementation assumes that the two quantities are in compatible
+			/// Units up to some scaling factor.  Find the scaling factor and apply it.
+		{
+			return v * ScalingFactor<T2>::template fn<V>() / ScalingFactor<T1>::template fn<V>();
+		}
+	};
+
+	template <typename T1, typename T2> 
+	struct Convert2
+		/// Converts T1 to T2.
+		/// Template matches the first argument (T1),
+		/// this is the fall-through to Convert3.
+	{
+		template <typename V>
+		static V fn(const V& v)
+		{
+			return Convert3<T1,T2>::fn(v);
+		}
+	};
+
+	template <typename T1, typename T2> 
+	struct Convert
+		/// Converts T1 to T2.
+		/// If you really want to implement your own conversion routine,
+		/// specialize this template.
+		/// The default implementation falls through to Convert2.
+	{
+		/// If this fails, then T1 is not Convertible to T2:
+		poco_static_assert ((Convertible<T1,T2>::Value));
+
+		template <typename V>
+		static V fn(const V& v)
+		{
+			return Convert2<T1,T2>::fn(v);
+		}
+	};
+
+	template <typename T>
+	struct Convert<T, T>
+		// Trivial conversion to the same type.
+	{
+		template <typename U>
+		static const U& fn(const U& u) { return u; }
+	};
+	
+	template <typename T>
+	struct Convert3<T, T>
+		// Convert to same type.
+	{
+		template <typename U>
+		static const U& fn(const U& u) { return u; }
+	};
+
+	template <typename T, typename U, int Num, int Den>
+	struct Convert2<Scale<T, Num, Den>, U>
+		// Convert from a scaled Unit.
+	{
+		template <typename V>
+		static V fn(const V& v)
+		{
+			return Convert<T, U>::fn((v * Den)/Num);
+		}
+	};
+	
+	template <typename T, typename U, int Num, int Den>
+	struct Convert3<T, Scale<U, Num, Den> >
+		// Convert to a scaled Unit.
+	{
+		template <typename V>
+		static V fn(const V& v)
+		{
+			return (Convert<T, U>::fn(v) * Num)/ Den;
+		}
+	};
+
+	template <typename T, typename U, int Num, int Den>
+	struct Convert2<Translate<T, Num, Den>, U>
+		// Convert from a translated Unit.
+	{
+		template <typename V>
+		static V fn(const V& v)
+		{
+			return Convert<T, U>::fn(v - static_cast<V>(Num) / static_cast<V>(Den));
+		}
+	};
+
+	template <typename T, typename U, int Num, int Den>
+	struct Convert3<T, Translate<U, Num, Den> >
+		// Convert to a translated Unit.
+	{
+		template <typename V>
+		static V fn(const V& v)
+		{
+			return Convert<T, U>::fn(v) + static_cast<V>(Num) / static_cast<V>(Den);
+		}
+	};
+
+	template <typename Term, typename List>
+	struct CountTerms
+		/// Count the power to which Unit Term is raised in the Unit List.
+		/// Returns a rational num/den of the power of term Term in List.
+		/// The default assumes that Term is not found (num/den=0).
+	{
+		static const int num = 0;
+		static const int den = 1;
+	};
+
+	template <typename Term>
+	struct CountTerms<Term, Term>
+	{
+		static const int num = 1;
+		static const int den = 1;
+	}; 
+ 
+	template <typename Term, typename U, int N, int D>
+	struct CountTerms<Term, Scale<U, N, D> >
+		// CountTerms ignores scaling factors - that is taken care of by ScalingFactor.
+	{
+		typedef CountTerms<Term, U> result;
+		static const int num = result::num;
+		static const int den = result::den;
+	};
+
+	template <typename Term, typename U, int N, int D>
+	struct CountTerms<Term, Translate<U, N, D> >
+		// CountTerms ignores translation.
+	{
+		typedef CountTerms<Term, U> result;
+		static const int num = result::num;
+		static const int den = result::den;
+	};
+
+	template <typename Term, typename T1, typename T2>
+	struct CountTerms<Term, Compose<T1,T2> >
+		// Addition of fractions.
+	{
+		typedef CountTerms<Term, T1> result1;
+		typedef CountTerms<Term, T2> result2;
+		static const int num = result1::num * result2::den + result1::den * result2::num;
+		static const int den = result1::den * result2::den;
+	};
+
+	template <typename Term, typename U, int N, int D>
+	struct CountTerms<Term, Power<U, N, D> >
+		// Multiplication of fractions.
+	{
+		typedef CountTerms<Term, U> result;
+		static const int num = N * result::num;
+		static const int den = D * result::den;
+	};
+
+	template <typename Term, typename T1, typename T2>
+	struct CheckTermsEqual
+		/// Counts the power of the Unit Term in Units T1 and T2.
+		/// Reports if they are equal, using equality of fractions.
+		/// Does a depth-first search of the Unit "Term", 
+		/// or counts the terms in the default case.
+	{
+		typedef CountTerms<Term, T1> count1;
+		typedef CountTerms<Term, T2> count2;
+
+		static const bool Value =
+			count1::num * count2::den ==
+			count1::den * count2::num;
+	};
+
+	template <typename U, int N, int D, typename T1, typename T2>
+	struct CheckTermsEqual<Power<U, N, D>, T1, T2 >
+	{
+		static const bool Value = CheckTermsEqual<U, T1, T2>::Value;
+	};
+
+	template <typename U, int N, int D, typename T1, typename T2>
+	struct CheckTermsEqual<Scale<U, N, D>, T1, T2 >
+	{
+		static const bool Value = CheckTermsEqual<U, T1, T2>::Value;
+	};
+
+	template <typename U, int N, int D, typename T1, typename T2>
+	struct CheckTermsEqual<Translate<U, N, D>, T1, T2 >
+	{
+		static const bool Value = CheckTermsEqual<U, T1, T2>::Value;
+	};
+
+	template <typename T1, typename T2, typename T3, typename T4>
+	struct CheckTermsEqual<Compose<T1,T2>,T3,T4>
+	{
+		static const bool Value =
+			CheckTermsEqual<T1, T3, T4>::Value &&
+			CheckTermsEqual<T2, T3, T4>::Value;
+	};
+
+	template <typename T1, typename T2>
+	struct Convertible
+		/// Determines whether two types are Convertible.
+		/// Counts the powers in the LHS and RHS and ensures they are equal.
+	{
+		static const bool Value =
+			CheckTermsEqual<T1,T1,T2>::Value &&
+			CheckTermsEqual<T2,T1,T2>::Value;
+	};
+
+	template <int Num, int Den, int Div, int Mod>
+	struct FixedPower
+		/// A functor that raises a Value to the power Num/Den.
+		/// The template is specialised for efficiency 
+		/// so that we don't always have to call the std::power function.
+	{
+		template <typename T> static T Power(const T& t)
+		{
+			return std::pow(t, static_cast<T>(Num)/static_cast<T>(Den));
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, 1, 0>
+	{
+		template <typename T> static const T& Power(const T& t)
+		{
+			return t;
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, 2, 0>
+	{
+		template <typename T> static T Power(const T& t)
+		{
+			return t*t;
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, 3, 0>
+	{
+		template <typename T> static T Power(const T& t)
+		{
+			return t*t*t;
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, 4, 0>
+	{
+		template <typename T> static const T& Power(const T& t)
+		{
+			T u = t*t;
+			return u*u;
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, -1, 0>
+	{
+		template <typename T> static T Power(const T& t)
+		{
+			return 1/t;
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, -2, 0>
+	{
+		template <typename T> static T Power(const T& t)
+		{
+			return 1/(t*t);
+		}
+	};
+
+	template <int N, int D>
+	struct FixedPower<N, D, 0, 0>
+	{
+		template <typename T> static T Power(const T& t)
+		{
+			return 1;
+		}
+	};
+
+	template <typename U>
+	struct ScalingFactor
+		/// Determine the scaling factor of a Unit in relation to its "base" Units.
+		/// Default is that U is a primitive Unit and is not scaled.
+	{
+		template <typename T>
+		static T fn() { return 1; }
+	};
+
+	template <typename U1, typename U2>
+	struct ScalingFactor< Compose<U1, U2> >
+	{
+		template <typename T>
+		static T fn()
+		{
+			return
+				ScalingFactor<U1>::template fn<T>() *
+				ScalingFactor<U2>::template fn<T>();
+		}
+	};
+
+	template <typename U, int N, int D>
+	struct ScalingFactor< Scale<U, N, D> >
+	{
+		template <typename T>
+		static T fn()
+		{
+			return
+				ScalingFactor<U>::template fn<T>() *
+				static_cast<T>(N) / static_cast<T>(D);
+		}
+	};
+
+	template <typename U, int N, int D>
+	struct ScalingFactor< Power<U, N, D> >
+	{
+		template <typename T>
+		static T fn()
+		{
+			return FixedPower<N, D>::Power(ScalingFactor<U>::template fn<T>());
+		}
+	};
+
+	template <typename U, int N, int D>
+	struct ScalingFactor< Translate<U, N, D> >
+	{
+		template <typename T>
+		static T fn()
+		{
+			return ScalingFactor<U>::template fn<T>();
+		}
+	};
+} // namespace Internal
+
+
+///
+/// Display
+///
+
+
+#define UNIT_DISPLAY_NAME(Unit, string) \
+	template <> \
+	struct OutputUnit<Unit> \
+	{ \
+		template <typename Stream> \
+		static void fn(Stream& os) \
+		{ \
+			os << string; \
+		} \
+	}
+
+
+namespace Internal
+{
+	template <typename U>
+	struct OutputUnit2
+		/// The default Unit formatting mechanism.
+	{
+		template <typename Stream>
+		static void fn(Stream &os) 
+		{
+			os << "Units";
+		}
+	};
+}
+
+
+template <typename U>
+struct OutputUnit
+	/// Functor to write Unit text to stream.
+{
+	template <typename Stream>
+	static void fn(Stream &os) 
+	{
+		Internal::OutputUnit2<U>::fn(os);
+	}
+};
+
+
+UNIT_DISPLAY_NAME(Unit, "1");
+
+
+namespace Internal
+{
+	template <typename U1, typename U2>
+	struct OutputUnit2< Compose<U1,U2> >
+	{
+		template <typename Stream>
+		static void fn(Stream &os) 
+		{ 
+			OutputUnit<U1>::fn(os); 
+			os << '.';
+			OutputUnit<U2>::fn(os); 
+		}
+	};
+
+	template <typename U, int Num, int Den>
+	struct OutputUnit2< Power<U, Num, Den > >
+	{
+		template <typename Stream>
+		static void fn(Stream &os) 
+		{ 
+			if(Num!=Den) os << '(';
+			OutputUnit<U>::fn(os); 
+			if(Num!=Den)
+			{
+				os << ')';
+				os << '^' << Num;
+				if(Num%Den)
+				{
+					os << '/' << Den;
+				}
+			}
+		}
+	};
+
+	template <typename U, int Num, int Den>
+	struct OutputUnit2< Translate<U, Num, Den > >
+	{
+		template <typename Stream>
+		static void fn(Stream &os) 
+		{ 
+			os << '(';
+			OutputUnit<U>::fn(os); 
+			os << '+' << Num;
+			if(Den!=1) os << '/' << Den;
+			os << ')';
+		}
+	};
+
+	template <typename U, int Num, int Den>
+	struct OutputUnit2< Scale<U, Num, Den > >
+	{
+		template <typename Stream>
+		static void fn(Stream &os) 
+		{ 
+			os << Den;
+			if(Num != 1)
+				os << '/' << Num;
+			os << '.';
+			OutputUnit<U>::fn(os); 
+		}
+	};
+} // namespace Internal
+
+
+template <typename Str, typename V, typename U>
+Str& operator << (Str& os, const Value<V, U>& value)
+{
+	os << value.get() << ' ';
+	OutputUnit<U>::fn(os);
+	return os;
+}
+
+
+///
+/// Additional Units
+///
+
+
+namespace Units
+{
+	typedef Poco::Util::Units::Unit Unit;
+
+	// SI base Units:
+
+	struct m;	/// meter
+	struct kg;	/// kilogram
+	struct s;	/// second
+	struct K;	/// Kelvin
+	struct A;	/// Ampere
+	struct mol;	/// mole
+	struct cd;	/// candela
+}
+
+
+UNIT_DISPLAY_NAME(Units::m,   "m");
+UNIT_DISPLAY_NAME(Units::kg,  "kg");
+UNIT_DISPLAY_NAME(Units::s,   "s");
+UNIT_DISPLAY_NAME(Units::K,   "K");
+UNIT_DISPLAY_NAME(Units::A,   "A");
+UNIT_DISPLAY_NAME(Units::mol, "mol");
+UNIT_DISPLAY_NAME(Units::cd,  "cd");
+
+
+namespace Units
+{
+	// SI derived Units:
+	typedef Compose<m, Power<m, -1> > rad;
+	typedef Compose<Power<m, 2>, Power<m, -2> > sr;
+	typedef Power<s, -1> Hz;
+	typedef Compose<m, Compose<kg, Power<s, -2> > > N;
+	typedef Compose<N, Power<m, -2> > Pa;
+	typedef Compose<N, m> J;
+	typedef Compose<J, Power<s, -1> > W;
+	typedef Compose<s, A> C;
+	typedef Compose<W, Power<A, -1> > V;
+	typedef Compose<C, Power<V, -1> > F;
+	typedef Compose<V, Power<A, -1> > Ohm;
+	typedef Compose<A, Power<V, -1> > S;
+	typedef Compose<V, s> Wb;
+	typedef Compose<Wb, Power<m, -2> > T;
+	typedef Compose<Wb, Power<A, -1> > H;
+	typedef cd lm;
+	typedef Compose<lm, Power<m, -2> > lx;
+	typedef Power<s, -1> Bq;
+	typedef Compose<J, Power<kg, -1> > Gy;
+	typedef Gy Sv;
+	typedef Compose<Power<s, -1>,mol> kat;
+}
+
+
+UNIT_DISPLAY_NAME(Units::rad, "rad");
+UNIT_DISPLAY_NAME(Units::sr,  "sr");
+// UNIT_DISPLAY_NAME(Units::Hz, "Hz");	// Too problematic
+UNIT_DISPLAY_NAME(Units::N,   "N");
+UNIT_DISPLAY_NAME(Units::Pa,  "Pa");
+UNIT_DISPLAY_NAME(Units::J,   "J");
+UNIT_DISPLAY_NAME(Units::W,   "W");
+UNIT_DISPLAY_NAME(Units::C,   "C");
+UNIT_DISPLAY_NAME(Units::V,   "V");
+UNIT_DISPLAY_NAME(Units::F,   "F");
+UNIT_DISPLAY_NAME(Units::Ohm, "Ohm");
+UNIT_DISPLAY_NAME(Units::S,   "S");
+UNIT_DISPLAY_NAME(Units::Wb,  "Wb");
+UNIT_DISPLAY_NAME(Units::T,   "T");
+UNIT_DISPLAY_NAME(Units::H,   "H");
+UNIT_DISPLAY_NAME(Units::lx,  "lx");
+UNIT_DISPLAY_NAME(Units::Gy,  "Gy");
+UNIT_DISPLAY_NAME(Units::kat,  "kat");
+
+
+namespace Units
+{
+	// SI prefixes:
+	template <typename U> struct deca { typedef Scale<U, 1, 10> type; };
+	template <typename U> struct hecto { typedef Scale<U, 1, 100> type; };
+	template <typename U> struct kilo { typedef Scale<U, 1, 1000> type; };
+	template <typename U> struct mega { typedef Scale<typename kilo<U>::type, 1, 1000> type; };
+	template <typename U> struct giga { typedef Scale<typename mega<U>::type, 1, 1000> type; };
+	template <typename U> struct tera { typedef Scale<typename giga<U>::type, 1, 1000> type; };
+	template <typename U> struct peta { typedef Scale<typename tera<U>::type, 1, 1000> type; };
+	template <typename U> struct exa { typedef Scale<typename peta<U>::type, 1, 1000> type; };
+	template <typename U> struct zetta { typedef Scale<typename exa<U>::type, 1, 1000> type; };
+	template <typename U> struct yotta { typedef Scale<typename zetta<U>::type, 1, 1000> type; };
+
+	template <typename U> struct deci { typedef Scale<U, 10> type; };
+	template <typename U> struct centi { typedef Scale<U, 100> type; };
+	template <typename U> struct milli { typedef Scale<U, 1000> type; };
+	template <typename U> struct micro { typedef Scale<typename milli<U>::type, 1000> type; };
+	template <typename U> struct nano { typedef Scale<typename micro<U>::type, 1000> type; };
+	template <typename U> struct pico { typedef Scale<typename nano<U>::type, 1000> type; };
+	template <typename U> struct femto { typedef Scale<typename pico<U>::type, 1000> type; };
+	template <typename U> struct atto { typedef Scale<typename femto<U>::type, 1000> type; };
+	template <typename U> struct zepto { typedef Scale<typename atto<U>::type, 1000> type; };
+	template <typename U> struct yocto { typedef Scale<typename zepto<U>::type, 1000> type; };
+
+
+	// Some prefixed SI Units:
+	typedef centi<m>::type cm;
+	typedef milli<m>::type mm;
+	typedef kilo<m>::type km;
+	typedef milli<kg>::type g;
+	typedef milli<g>::type mg;
+	typedef milli<s>::type ms;
+
+
+	class Prefix
+		/// Parent class for unit prefixes.
+		/// Use classes inheriting from this class to scale
+		/// the values.
+	{
+	public:
+		template <typename T>
+		Prefix(const T& val, double multiplier = 1, const std::string& prefix = ""): 
+			_pHolder(new Holder<T>(val)),
+			_multiplier(multiplier),
+			_prefix(prefix)
+		{ 
+		}
+
+		double value() const
+		{ 
+			return _pHolder->get() * _multiplier;
+		}
+
+		void addPrefix(std::ostream& os) const
+		{
+			os << _prefix;
+		}
+
+		void addUnit(std::ostream& os) const
+		{
+			_pHolder->appendUnit(os);
+		}
+
+	private:
+		Prefix();
+
+		class Placeholder
+		{
+		public:
+			virtual ~Placeholder() { }
+			virtual double get() const = 0;
+			virtual void appendUnit(std::ostream& os) const = 0;
+		};
+
+		template <typename U>
+		struct Holder : public Placeholder
+		{
+			typedef Value<typename U::ValueType, typename U::Unit> ValueType;
+
+			Holder (const U& val): _val(ValueType(val)) 
+			{
+			}
+
+			double get() const
+			{
+				return _val.get();
+			}
+
+			void appendUnit(std::ostream& os) const
+			{
+				OutputUnit<typename U::Unit>::fn(os);
+			}
+
+			ValueType _val;
+		};
+
+		Placeholder* _pHolder;
+		double       _multiplier;
+		std::string  _prefix;
+	};
+}
+
+
+template <typename Str>
+Str& streamOp (Str& os, const Units::Prefix& val)
+{
+	os << val.value() << ' ';
+	val.addPrefix(os);
+	val.addUnit(os);
+	return os;
+}
+
+
+template <typename Str>
+Str& operator << (Str& os, const Units::Prefix& val)
+	/// Streaming operator for prefixed values.
+{
+	return streamOp(os, val);
+}
+
+
+UNIT_DISPLAY_NAME(Units::cm, "cm");
+UNIT_DISPLAY_NAME(Units::mm, "mm");
+UNIT_DISPLAY_NAME(Units::km, "km");
+UNIT_DISPLAY_NAME(Units::g,  "g");
+UNIT_DISPLAY_NAME(Units::mg, "mg");
+UNIT_DISPLAY_NAME(Units::ms, "ms");
+
+
+namespace Units
+{
+	// Non-SI mass
+	typedef Scale<kg, 22046223, 10000000> lb;
+	typedef Scale<lb, 16> oz;
+	typedef Scale<kg, 1, 1000> tonne;
+
+	// Non-SI temperature
+	typedef Translate<K, -27315, 100> Celsius;
+	typedef Translate<Scale<Celsius, 9, 5>, 32> Fahrenheit;
+
+	// Non-SI time
+	typedef Scale<s, 1, 60> minute;
+	typedef Scale<minute, 1, 60> hour;
+	typedef Scale<hour, 1, 24> day;
+	typedef Scale<day, 1, 7> week;
+	struct month;	// No fixed ratio with week 
+	typedef Scale<month, 1, 12> year;
+	typedef Scale<year, 1, 100> century;
+	typedef Scale<year, 1, 1000> millennium;
+
+	// Non-SI length
+	typedef Scale<cm, 100, 254> inch;
+	typedef Scale<inch, 1, 12> foot;
+	typedef Scale<inch, 1, 36> yard;
+	typedef Scale<yard, 1, 1760> mile;
+	typedef Scale<m, 1, 1852> nautical_mile;
+
+	// Non-SI area
+	typedef Power<m, 2> m2;
+	typedef Power<mm, 2> mm2;
+	typedef Scale<m2, 1, 10000> hectare;
+	typedef Scale<m2, 1, 100> are;
+	typedef Power<inch, 2> inch2;
+	typedef Scale<hectare, 24710538, 10000000> acre;
+
+	// Non-SI volume
+	typedef Power<cm, 3> cm3;
+	typedef cm3 ml;
+	typedef Scale<ml, 1, 1000> liter;
+	typedef Scale<liter, 10> dl;
+	typedef Scale<liter, 100> cl;
+	typedef Power<m, 3> m3;
+
+	// Non-SI velocity
+	typedef Compose<mile, Power<hour, -1> > mph;
+	typedef Compose<km, Power<hour, -1> > kph;
+	typedef Compose<m, Power<s, -1> > meters_per_second;
+	typedef Compose<nautical_mile, Power<hour, -1> > knot;
+	typedef Scale<meters_per_second, 100, 34029> mach;
+
+	// Angles
+	typedef Scale<rad, 180000000, 3141593> degree;
+	typedef Scale<rad, 200000000, 3141593> grad;
+	typedef Scale< degree, 60 > degree_minute;
+	typedef Scale< degree_minute, 60 > degree_second;
+
+	// Pressure
+	typedef Scale<Pa, 1, 1000> kPa;
+	typedef Scale<kPa, 1450377, 10000000> psi;
+	typedef Scale<kPa, 10> millibar;
+
+	// Other
+	typedef Scale<Hz, 60> rpm;
+	typedef Scale<Unit, 100> percent;
+	typedef Scale<Unit, 1, 12> dozen;
+	typedef Scale<Unit, 1, 13> bakers_dozen;
+}
+
+
+UNIT_DISPLAY_NAME(Units::lb,            "lb");
+UNIT_DISPLAY_NAME(Units::oz,            "oz");
+UNIT_DISPLAY_NAME(Units::tonne,         "tonnes");
+UNIT_DISPLAY_NAME(Units::Celsius,       "'C");
+UNIT_DISPLAY_NAME(Units::Fahrenheit,    "'F");
+UNIT_DISPLAY_NAME(Units::minute,        "minutes");
+UNIT_DISPLAY_NAME(Units::hour,          "hours");
+UNIT_DISPLAY_NAME(Units::day,           "days");
+UNIT_DISPLAY_NAME(Units::week,          "weeks");
+UNIT_DISPLAY_NAME(Units::month,         "months");
+UNIT_DISPLAY_NAME(Units::year,          "years");
+UNIT_DISPLAY_NAME(Units::century,       "centuries");
+UNIT_DISPLAY_NAME(Units::millennium,    "millennia");
+UNIT_DISPLAY_NAME(Units::inch,          "inches");
+UNIT_DISPLAY_NAME(Units::foot,          "foot");
+UNIT_DISPLAY_NAME(Units::yard,          "yards");
+UNIT_DISPLAY_NAME(Units::mile,          "miles");
+UNIT_DISPLAY_NAME(Units::nautical_mile, "nautical miles");
+UNIT_DISPLAY_NAME(Units::hectare,       "ha");
+UNIT_DISPLAY_NAME(Units::are,           "are");
+UNIT_DISPLAY_NAME(Units::acre,          "acres");
+UNIT_DISPLAY_NAME(Units::ml,            "ml");
+UNIT_DISPLAY_NAME(Units::liter,         "l");
+UNIT_DISPLAY_NAME(Units::dl,            "dl");
+UNIT_DISPLAY_NAME(Units::cl,            "cl");
+UNIT_DISPLAY_NAME(Units::mph,           "mph");
+UNIT_DISPLAY_NAME(Units::kph,           "km/h");
+UNIT_DISPLAY_NAME(Units::knot,          "knots");
+UNIT_DISPLAY_NAME(Units::mach,          "mach");
+UNIT_DISPLAY_NAME(Units::degree,        "deg");
+UNIT_DISPLAY_NAME(Units::grad,          "grad");
+UNIT_DISPLAY_NAME(Units::degree_minute, "'");
+UNIT_DISPLAY_NAME(Units::degree_second, "\"");
+UNIT_DISPLAY_NAME(Units::kPa,           "kPa");
+UNIT_DISPLAY_NAME(Units::psi,           "PSI");
+UNIT_DISPLAY_NAME(Units::millibar,      "millibars");
+UNIT_DISPLAY_NAME(Units::percent,       "%");
+UNIT_DISPLAY_NAME(Units::rpm,           "rpm");
+UNIT_DISPLAY_NAME(Units::dozen,         "dozen");
+UNIT_DISPLAY_NAME(Units::bakers_dozen,  "bakers dozen");
+
+
+namespace Values
+{
+	typedef Value<double, Units::Unit> Unit;
+
+	// SI Units
+	typedef Value<double, Units::m> m;
+	typedef Value<double, Units::kg> kg;
+	typedef Value<double, Units::s> s;
+	typedef Value<double, Units::K> K;
+	typedef Value<double, Units::A> A;
+	typedef Value<double, Units::mol> mol;
+	typedef Value<double, Units::cd> cd;
+
+	// SI derived
+	typedef Value<double, Units::rad> rad;
+	typedef Value<double, Units::sr> sr;
+	typedef Value<double, Units::Hz> Hz;
+	typedef Value<double, Units::N> N;
+	typedef Value<double, Units::Pa> Pa;
+	typedef Value<double, Units::J> J;
+	typedef Value<double, Units::W> W;
+	typedef Value<double, Units::C> C;
+	typedef Value<double, Units::V> V;
+	typedef Value<double, Units::F> F;
+	typedef Value<double, Units::Ohm> Ohm;
+	typedef Value<double, Units::S> S;
+	typedef Value<double, Units::Wb> Wb;
+	typedef Value<double, Units::T> T;
+	typedef Value<double, Units::H> H;
+	typedef Value<double, Units::lm> lm;
+	typedef Value<double, Units::lx> lx;
+	typedef Value<double, Units::Bq> Bq;
+	typedef Value<double, Units::Gy> Gy;
+	typedef Value<double, Units::Sv> Sv;
+	typedef Value<double, Units::kat> kat;
+
+	// Prefixed Units
+	typedef Value<double, Units::cm> cm;
+	typedef Value<double, Units::mm> mm;
+	typedef Value<double, Units::km> km;
+	typedef Value<double, Units::g> g;
+	typedef Value<double, Units::mg> mg;
+	typedef Value<double, Units::ms> ms;
+
+	// Non-SI
+	typedef Value<double, Units::lb> lb;
+	typedef Value<double, Units::oz> oz;
+	typedef Value<double, Units::tonne> tonne;
+
+	typedef Value<double, Units::Celsius> Celsius;
+	typedef Value<double, Units::Fahrenheit> Fahrenheit;
+
+	typedef Value<double, Units::minute> minute;
+	typedef Value<double, Units::hour> hour;
+	typedef Value<double, Units::day> day;
+	typedef Value<double, Units::week> week;
+	typedef Value<double, Units::month> month;
+	typedef Value<double, Units::year> year;
+	typedef Value<double, Units::century> century;
+	typedef Value<double, Units::millennium> millennium;
+
+	typedef Value<double, Units::inch> inch;
+	typedef Value<double, Units::foot> foot;
+	typedef Value<double, Units::yard> yard;
+	typedef Value<double, Units::mile> mile;
+	typedef Value<double, Units::nautical_mile> nautical_mile;
+
+	typedef Value<double, Units::m2> m2;
+	typedef Value<double, Units::mm2> mm2;
+	typedef Value<double, Units::hectare> hectare;
+	typedef Value<double, Units::are> are;
+	typedef Value<double, Units::inch2> inch2;
+	typedef Value<double, Units::acre> acre;
+
+	typedef Value<double, Units::cm3> cm3;
+	typedef Value<double, Units::ml> ml;
+	typedef Value<double, Units::cl> cl;
+	typedef Value<double, Units::liter> liter;
+	typedef Value<double, Units::dl> dl;
+	typedef Value<double, Units::m3> m3;
+
+	typedef Value<double, Units::mph> mph;
+	typedef Value<double, Units::kph> kph;
+	typedef Value<double, Units::meters_per_second> meters_per_second;
+	typedef Value<double, Units::knot> knot;
+	typedef Value<double, Units::mach> mach;
+
+	typedef Value<double, Units::degree> degree;
+	typedef Value<double, Units::grad> grad;
+	typedef Value<double, Units::degree_minute> degree_minute;
+	typedef Value<double, Units::degree_second> degree_second;
+
+	typedef Value<double, Units::kPa> kPa;
+	typedef Value<double, Units::psi> psi;
+	typedef Value<double, Units::millibar> millibar;
+
+	typedef Value<double, Units::percent> percent;
+	typedef Value<double, Units::rpm> rpm;
+	typedef Value<double, Units::dozen> dozen;
+	typedef Value<double, Units::bakers_dozen> bakers_dozen;
+
+	#define DEFINE_PREFIX_CLASS(name, scale, prefix) \
+		struct name: public Units::Prefix \
+		{ \
+			template <typename T> \
+			name(const T& val): Prefix(val, scale, prefix) \
+			{ \
+			} \
+		}; \
+		template <typename Str> \
+		Str& operator << (Str& os, const name& val) \
+		{ \
+			return streamOp<Str>(os, val); \
+		}
+
+	DEFINE_PREFIX_CLASS (deca, .1, "da")
+	DEFINE_PREFIX_CLASS (hecto, .01, "h")
+	DEFINE_PREFIX_CLASS (kilo, .001, "k")
+	DEFINE_PREFIX_CLASS (mega, 1e-6, "M")
+	DEFINE_PREFIX_CLASS (giga, 1e-9, "G")
+	DEFINE_PREFIX_CLASS (tera, 1e-12, "T") 
+	DEFINE_PREFIX_CLASS (peta, 1e-15, "P")
+	DEFINE_PREFIX_CLASS (exa, 1e-18, "E")
+	DEFINE_PREFIX_CLASS (zetta, 1e-21, "Z")
+	DEFINE_PREFIX_CLASS (yotta, 1e-24, "Y")
+
+	DEFINE_PREFIX_CLASS (deci, 10, "d")
+	DEFINE_PREFIX_CLASS (centi, 100, "c")
+	DEFINE_PREFIX_CLASS (milli, 1000, "m")
+	DEFINE_PREFIX_CLASS (micro, 1e6, "u")
+	DEFINE_PREFIX_CLASS (nano, 1e9, "n")
+	DEFINE_PREFIX_CLASS (pico, 1e12, "p")
+	DEFINE_PREFIX_CLASS (femto, 1e15, "f")
+	DEFINE_PREFIX_CLASS (atto, 1e18, "a")
+	DEFINE_PREFIX_CLASS (zepto, 1e21, "z")
+	DEFINE_PREFIX_CLASS (yocto, 1e24, "y")
+}
+
+
+namespace Constants
+{
+	// Physical constants:
+	const Value<double, Compose<Units::J, Power<Units::K, -1> > > k (1.3806504e-23);
+	const Value<double, Units::kg> mu (1.660538782e-27);
+	const Value<double, Power<Units::mol, -1> > NA (6.02214179e23);
+	const Value<double, Units::s> G0 (7.7480917004e-5);
+	const Value<double, Compose<Units::F, Power<Units::m, -1> > > e0 (8.854187817e-12);
+	const Value<double, Units::kg> me (9.10938215e-31);
+	const Value<double, Units::J> eV (1.602176487e-19);
+	const Value<double, Units::C> e (1.602176487e-19);
+	const Value<double, Units::F> F (96485.3399);
+	const Value<double, Units::Unit> alpha (7.2973525376e-3);
+	const Value<double, Units::Unit> inv_alpha (137.035999679);
+	const Value<double, Compose<Units::N, Power<Units::A, -2> > > u0 (12.566370614);
+	const Value<double, Units::Wb> phi0 (2.067833667e-15);	// ??
+	const Value<double, Compose<Units::J, Compose<Power<Units::mol, -1>, Power<Units::kg, -1> > > > R (8.314472);
+	const Value<double, Compose< Power<Units::m, 3>, Compose<Power<Units::kg, -1>, Power<Units::s, -2> > > > G (6.67428e-11);
+	const Value<double, Compose< Units::J, Units::s > > h (6.62606896e-34);
+	const Value<double, Compose< Units::J, Units::s > > h_bar (1.054571628e-34);
+	const Value<double, Units::kg> mp (1.672621637e-27);
+	const Value<double, Unit> mpme (1836.15267247);
+	const Value<double, Power<Units::m, -1> > Rinf (10973731.568527);
+	const Value<double, Compose<Units::m, Power<Units::s, -1> > > c (299792458);
+	const Value<double, Compose<Units::W, Compose< Power<Units::m, -1>, Power<Units::K, -4> > > > rho (5.6704e-8);
+
+	// Other constants:
+	const Value<double, Units::rad> pi (3.141592653589793);
+	const Value<double, Units::m> lightyear (9.4605284e15);
+	const Value<double, Units::km> AU(149597871);
+	const Value<double, Compose<Units::m, Power<Units::s, -2> > > g (9.80665);
+}
+
+
+//
+// Trigonometry
+//
+
+
+template <typename V, typename U>
+V sin(const Value<V, U>& angle)
+{
+	return std::sin(Value<V, Units::rad>(angle).get());
+}
+
+
+template <typename V, typename U>
+V cos(const Value<V, U>& angle)
+{
+	return std::cos(Value<V, Units::rad>(angle).get());
+}
+
+
+template <typename V, typename U>
+V tan(const Value<V, U>& angle)
+{
+	return std::tan(Value<V, Units::rad>(angle).get());
+}
+
+
+} } } // namespace Poco::Util::Units
+
+
+#endif // Util_Units_INCLUDED
diff --git a/Poco/Util/Util.h b/Poco/Util/Util.h
new file mode 100644
index 0000000..f567243
--- /dev/null
+++ b/Poco/Util/Util.h
@@ -0,0 +1,62 @@
+//
+// Util.h
+//
+// Library: Util
+// Package: Util
+// Module:  Util
+//
+// Basic definitions for the Poco Util library.
+// This file must be the first file included by every other Util
+// header file.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_Util_INCLUDED
+#define Util_Util_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Util_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Util_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(Util_EXPORTS)
+		#define Util_API __declspec(dllexport)
+	#else
+		#define Util_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Util_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Util_API __attribute__ ((visibility ("default")))
+	#else
+		#define Util_API
+	#endif
+#endif
+
+
+//
+// Automatically link Util library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Util_EXPORTS)
+		#pragma comment(lib, "PocoUtil" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // Util_Util_INCLUDED
diff --git a/Poco/Util/Validator.h b/Poco/Util/Validator.h
new file mode 100644
index 0000000..38cbc4c
--- /dev/null
+++ b/Poco/Util/Validator.h
@@ -0,0 +1,57 @@
+//
+// Validator.h
+//
+// Library: Util
+// Package: Options
+// Module:  Validator
+//
+// Definition of the Validator class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_Validator_INCLUDED
+#define Util_Validator_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/RefCountedObject.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Option;
+
+
+class Util_API Validator: public Poco::RefCountedObject
+	/// Validator specifies the interface for option validators.
+	///
+	/// Option validators provide a simple way for the automatic
+	/// validation of command line argument values.
+{
+public:
+	virtual void validate(const Option& option, const std::string& value) = 0;
+		/// Validates the value for the given option.
+		/// Does nothing if the value is valid.
+		///
+		/// Throws an OptionException otherwise.
+
+protected:
+	Validator();
+		/// Creates the Validator.
+
+	virtual ~Validator();
+		/// Destroys the Validator.
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_Validator_INCLUDED
diff --git a/Poco/Util/WinRegistryConfiguration.h b/Poco/Util/WinRegistryConfiguration.h
new file mode 100644
index 0000000..e7e49fc
--- /dev/null
+++ b/Poco/Util/WinRegistryConfiguration.h
@@ -0,0 +1,71 @@
+//
+// WinRegistryConfiguration.h
+//
+// Library: Util
+// Package: Windows
+// Module:  WinRegistryConfiguration
+//
+// Definition of the WinRegistryConfiguration class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_WinRegistryConfiguration_INCLUDED
+#define Util_WinRegistryConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/Util/AbstractConfiguration.h"
+#include "Poco/String.h"
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API WinRegistryConfiguration: public AbstractConfiguration
+	/// An implementation of AbstractConfiguration that stores configuration data
+	/// in the Windows registry.
+	///
+	/// Removing key is not supported. An attempt to remove a key results
+	/// in a NotImplementedException being thrown.
+{
+public:
+	WinRegistryConfiguration(const std::string& rootPath, REGSAM extraSam = 0);
+		/// Creates the WinRegistryConfiguration. 
+		/// The rootPath must start with one of the root key names
+		/// like HKEY_CLASSES_ROOT, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
+		/// All further keys are relative to the root path and can be
+		/// dot separated, e.g. the path MyService.ServiceName will be converted to
+		/// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService\ServiceName.
+        /// The extraSam parameter will be passed along to WinRegistryKey, to control
+        /// registry virtualization for example.
+
+protected:
+	~WinRegistryConfiguration();
+		/// Destroys the WinRegistryConfiguration.
+
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+
+	std::string convertToRegFormat(const std::string& key, std::string& keyName) const;
+		/// Takes a key in the format of A.B.C and converts it to
+		/// registry format A\B\C, the last entry is the keyName, the rest is returned as path
+
+	friend class WinConfigurationTest;
+private:
+	std::string _rootPath;
+    REGSAM _extraSam;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_WinRegistryConfiguration_INCLUDED
diff --git a/Poco/Util/WinRegistryKey.h b/Poco/Util/WinRegistryKey.h
new file mode 100644
index 0000000..ca1f9fa
--- /dev/null
+++ b/Poco/Util/WinRegistryKey.h
@@ -0,0 +1,198 @@
+//
+// WinRegistryKey.h
+//
+// Library: Util
+// Package: Windows
+// Module:  WinRegistryKey
+//
+// Definition of the WinRegistryKey class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_WinRegistryKey_INCLUDED
+#define Util_WinRegistryKey_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/UnWindows.h"
+#include <vector>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API WinRegistryKey
+	/// This class implements a convenient interface to the
+	/// Windows Registry.
+	///
+	/// This class is only available on Windows platforms.
+{
+public:
+	typedef std::vector<std::string> Keys;
+	typedef std::vector<std::string> Values;
+
+	enum Type
+	{
+		REGT_NONE = 0,
+		REGT_STRING = 1,
+		REGT_STRING_EXPAND = 2,
+		REGT_BINARY = 3,
+		REGT_DWORD = 4,
+		REGT_DWORD_BIG_ENDIAN = 5,
+		REGT_LINK = 6,
+		REGT_MULTI_STRING = 7,
+		REGT_RESOURCE_LIST = 8,
+		REGT_FULL_RESOURCE_DESCRIPTOR = 9,
+		REGT_RESOURCE_REQUIREMENTS_LIST = 10,
+		REGT_QWORD = 11
+	};
+
+	WinRegistryKey(const std::string& key, bool readOnly = false, REGSAM extraSam = 0);
+		/// Creates the WinRegistryKey.
+		///
+		/// The key must start with one of the root key names
+		/// like HKEY_CLASSES_ROOT, e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
+		///
+		/// If readOnly is true, then only read access to the registry
+		/// is available and any attempt to write to the registry will
+		/// result in an exception.
+		///
+		/// extraSam is used to pass extra flags (in addition to KEY_READ and KEY_WRITE)
+		/// to the samDesired argument of RegOpenKeyEx() or RegCreateKeyEx().
+
+	WinRegistryKey(HKEY hRootKey, const std::string& subKey, bool readOnly = false, REGSAM extraSam = 0);
+		/// Creates the WinRegistryKey.
+		///
+		/// If readOnly is true, then only read access to the registry
+		/// is available and any attempt to write to the registry will
+		/// result in an exception.
+		///
+		/// extraSam is used to pass extra flags (in addition to KEY_READ and KEY_WRITE)
+		/// to the samDesired argument of RegOpenKeyEx() or RegCreateKeyEx().
+
+	~WinRegistryKey();
+		/// Destroys the WinRegistryKey.
+
+	void setString(const std::string& name, const std::string& value);
+		/// Sets the string value (REG_SZ) with the given name.
+		/// An empty name denotes the default value.
+
+	std::string getString(const std::string& name);
+		/// Returns the string value (REG_SZ) with the given name.
+		/// An empty name denotes the default value.
+		///
+		/// Throws a NotFoundException if the value does not exist.
+
+	void setStringExpand(const std::string& name, const std::string& value);
+		/// Sets the expandable string value (REG_EXPAND_SZ) with the given name.
+		/// An empty name denotes the default value.
+
+	std::string getStringExpand(const std::string& name);
+		/// Returns the string value (REG_EXPAND_SZ) with the given name.
+		/// An empty name denotes the default value.
+		/// All references to environment variables (%VAR%) in the string
+		/// are expanded.
+		///
+		/// Throws a NotFoundException if the value does not exist.
+
+	void setBinary(const std::string& name, const std::vector<char>& value);
+		/// Sets the string value (REG_BINARY) with the given name.
+		/// An empty name denotes the default value.
+
+	std::vector<char> getBinary(const std::string& name);
+		/// Returns the string value (REG_BINARY) with the given name.
+		/// An empty name denotes the default value.
+		///
+		/// Throws a NotFoundException if the value does not exist.
+
+	void setInt(const std::string& name, int value);
+		/// Sets the numeric (REG_DWORD) value with the given name.
+		/// An empty name denotes the default value.
+
+	int getInt(const std::string& name);
+		/// Returns the numeric value (REG_DWORD) with the given name.
+		/// An empty name denotes the default value.
+		///
+		/// Throws a NotFoundException if the value does not exist.
+
+#if defined(POCO_HAVE_INT64)
+
+	void setInt64(const std::string& name, Poco::Int64 value);
+		/// Sets the numeric (REG_QWORD) value with the given name.
+		/// An empty name denotes the default value.
+
+	Poco::Int64 getInt64(const std::string& name);
+		/// Returns the numeric value (REG_QWORD) with the given name.
+		/// An empty name denotes the default value.
+		///
+		/// Throws a NotFoundException if the value does not exist.
+
+#endif // POCO_HAVE_INT64
+
+	void deleteValue(const std::string& name);
+		/// Deletes the value with the given name.
+		///
+		/// Throws a NotFoundException if the value does not exist.
+
+	void deleteKey();
+		/// Recursively deletes the key and all subkeys.
+
+	bool exists();
+		/// Returns true iff the key exists.
+
+	Type type(const std::string& name);
+		/// Returns the type of the key value.
+
+	bool exists(const std::string& name);
+		/// Returns true iff the given value exists under that key.
+
+	void subKeys(Keys& keys);
+		/// Appends all subKey names to keys.
+
+	void values(Values& vals);
+		/// Appends all value names to vals;
+
+	bool isReadOnly() const;
+		/// Returns true iff the key has been opened for read-only access only.
+
+protected:
+	void open();
+	void close();
+	std::string key() const;
+	std::string key(const std::string& valueName) const;
+	HKEY handle();
+	void handleSetError(const std::string& name);
+	static HKEY handleFor(const std::string& rootKey);
+
+private:
+	WinRegistryKey();
+	WinRegistryKey(const WinRegistryKey&);
+	WinRegistryKey& operator = (const WinRegistryKey&);
+
+	HKEY        _hRootKey;
+	std::string _subKey;
+	HKEY        _hKey;
+	bool        _readOnly;
+	REGSAM      _extraSam;
+};
+
+
+//
+// inlines
+//
+inline bool WinRegistryKey::isReadOnly() const
+{
+	return _readOnly;
+}
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_WinRegistryKey_INCLUDED
diff --git a/Poco/Util/WinService.h b/Poco/Util/WinService.h
new file mode 100644
index 0000000..8a3c49b
--- /dev/null
+++ b/Poco/Util/WinService.h
@@ -0,0 +1,141 @@
+//
+// WinService.h
+//
+// Library: Util
+// Package: Windows
+// Module:  WinService
+//
+// Definition of the WinService class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_WinService_INCLUDED
+#define Util_WinService_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+#include "Poco/UnWindows.h"
+
+
+#if defined(POCO_WIN32_UTF8)
+#define POCO_LPQUERY_SERVICE_CONFIG LPQUERY_SERVICE_CONFIGW
+#else
+#define POCO_LPQUERY_SERVICE_CONFIG LPQUERY_SERVICE_CONFIGA
+#endif
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API WinService
+	/// This class provides an object-oriented interface to
+	/// the Windows Service Control Manager for registering,
+	/// unregistering, configuring, starting and stopping
+	/// services.
+	///
+	/// This class is only available on Windows platforms.
+{
+public:
+	enum Startup
+	{
+		SVC_AUTO_START,
+		SVC_MANUAL_START,
+		SVC_DISABLED
+	};
+	
+	WinService(const std::string& name);
+		/// Creates the WinService, using the given service name.
+
+	~WinService();
+		/// Destroys the WinService.
+
+	const std::string& name() const;
+		/// Returns the service name.
+
+	std::string displayName() const;
+		/// Returns the service's display name.
+
+	std::string path() const;
+		/// Returns the path to the service executable. 
+		///
+		/// Throws a NotFoundException if the service has not been registered.
+
+	void registerService(const std::string& path, const std::string& displayName);
+		/// Creates a Windows service with the executable specified by path
+		/// and the given displayName.
+		///
+		/// Throws a ExistsException if the service has already been registered.
+		
+	void registerService(const std::string& path);
+		/// Creates a Windows service with the executable specified by path
+		/// and the given displayName. The service name is used as display name.
+		///
+		/// Throws a ExistsException if the service has already been registered.
+
+	void unregisterService();
+		/// Deletes the Windows service. 
+		///
+		/// Throws a NotFoundException if the service has not been registered.
+
+	bool isRegistered() const;
+		/// Returns true if the service has been registered with the Service Control Manager.
+
+	bool isRunning() const;
+		/// Returns true if the service is currently running.
+		
+	void start();
+		/// Starts the service.
+		/// Does nothing if the service is already running.
+		///
+		/// Throws a NotFoundException if the service has not been registered.
+
+	void stop();
+		/// Stops the service.
+		/// Does nothing if the service is not running.
+		///
+		/// Throws a NotFoundException if the service has not been registered.
+
+	void setStartup(Startup startup);
+		/// Sets the startup mode for the service.
+		
+	Startup getStartup() const;
+		/// Returns the startup mode for the service.
+		
+	void setDescription(const std::string& description);
+		/// Sets the service description in the registry.
+		
+	std::string getDescription() const;
+		/// Returns the service description from the registry.
+
+	static const int STARTUP_TIMEOUT;
+
+protected:
+	static const std::string REGISTRY_KEY;
+	static const std::string REGISTRY_DESCRIPTION;
+
+private:
+	void open() const;
+	bool tryOpen() const;
+	void close() const;
+	POCO_LPQUERY_SERVICE_CONFIG config() const;
+
+	WinService();
+	WinService(const WinService&);
+	WinService& operator = (const WinService&);
+
+	std::string       _name;
+	SC_HANDLE         _scmHandle;
+	mutable SC_HANDLE _svcHandle;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // Util_WinService_INCLUDED
diff --git a/Poco/Util/XMLConfiguration.h b/Poco/Util/XMLConfiguration.h
new file mode 100644
index 0000000..c47505e
--- /dev/null
+++ b/Poco/Util/XMLConfiguration.h
@@ -0,0 +1,209 @@
+//
+// XMLConfiguration.h
+//
+// Library: Util
+// Package: Configuration
+// Module:  XMLConfiguration
+//
+// Definition of the XMLConfiguration class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Util_XMLConfiguration_INCLUDED
+#define Util_XMLConfiguration_INCLUDED
+
+
+#include "Poco/Util/Util.h"
+
+
+#ifndef POCO_UTIL_NO_XMLCONFIGURATION
+
+
+#include "Poco/Util/MapConfiguration.h"
+#include "Poco/DOM/Document.h"
+#include "Poco/DOM/AutoPtr.h"
+#include "Poco/DOM/DOMWriter.h"
+#include "Poco/SAX/InputSource.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Util {
+
+
+class Util_API XMLConfiguration: public AbstractConfiguration
+	/// This configuration class extracts configuration properties
+	/// from an XML document. An XPath-like syntax for property
+	/// names is supported to allow full access to the XML document.
+	/// XML namespaces are not supported. The name of the root element
+	/// of the XML document is not significant and ignored. 
+	/// Periods in tag names are not supported.
+	/// 
+	/// Given the following XML document as an example:
+	///
+	///     <config>
+	///         <prop1>value1</prop1>
+	///         <prop2>value2</prop2>
+	///         <prop3>
+	///            <prop4 attr="value3"/>
+	///            <prop4 attr="value4"/>
+	///         </prop3>
+	///         <prop5 id="first">value5</prop5>
+	///         <prop5 id="second">value6</prop5>
+	///     </config>
+	///
+	/// The following property names would be valid and would
+	/// yield the shown values:
+	///
+	///     prop1                 -> value1
+	///     prop2                 -> value2
+	///     prop3.prop4           -> (empty string)
+	///     prop3.prop4[@attr]    -> value3
+	///     prop3.prop4[1][@attr] -> value4
+	///     prop5[0]              -> value5
+	///     prop5[1]              -> value6
+	///     prop5[@id=first]      -> value5
+	///     prop5[@id='second']   -> value6
+	///
+	/// Enumerating attributes is not supported.
+	/// Calling keys("prop3.prop4") will return an empty range.
+	///
+	/// As a special feature, the delimiter character used to delimit
+	/// property names can be changed to something other than period ('.') by
+	/// passing the desired character to the constructor. This allows
+	/// working with XML documents having element names with periods
+	/// in them.
+{
+public:
+	XMLConfiguration();
+		/// Creates an empty XMLConfiguration with a "config" root element.
+
+	XMLConfiguration(char delim);
+		/// Creates an empty XMLConfiguration with a "config" root element,
+		/// using the given delimiter char instead of the default '.'.
+
+	XMLConfiguration(Poco::XML::InputSource* pInputSource);
+		/// Creates an XMLConfiguration and loads the XML document from
+		/// the given InputSource.
+
+	XMLConfiguration(Poco::XML::InputSource* pInputSource, char delim);
+		/// Creates an XMLConfiguration and loads the XML document from
+		/// the given InputSource. Uses the given delimiter char instead
+		/// of the default '.'.
+
+	XMLConfiguration(std::istream& istr);
+		/// Creates an XMLConfiguration and loads the XML document from
+		/// the given stream.
+
+	XMLConfiguration(std::istream& istr, char delim);
+		/// Creates an XMLConfiguration and loads the XML document from
+		/// the given stream. Uses the given delimiter char instead
+		/// of the default '.'.
+
+	XMLConfiguration(const std::string& path);
+		/// Creates an XMLConfiguration and loads the XML document from
+		/// the given path.
+
+	XMLConfiguration(const std::string& path, char delim);
+		/// Creates an XMLConfiguration and loads the XML document from
+		/// the given path. Uses the given delimiter char instead
+		/// of the default '.'.
+
+	XMLConfiguration(const Poco::XML::Document* pDocument);
+		/// Creates the XMLConfiguration using the given XML document.
+
+	XMLConfiguration(const Poco::XML::Document* pDocument, char delim);
+		/// Creates the XMLConfiguration using the given XML document.
+		/// Uses the given delimiter char instead of the default '.'.
+		
+	XMLConfiguration(const Poco::XML::Node* pNode);
+		/// Creates the XMLConfiguration using the given XML node.
+
+	XMLConfiguration(const Poco::XML::Node* pNode, char delim);
+		/// Creates the XMLConfiguration using the given XML node.
+		/// Uses the given delimiter char instead of the default '.'.
+
+	void load(Poco::XML::InputSource* pInputSource);
+		/// Loads the XML document containing the configuration data
+		/// from the given InputSource.
+
+	void load(Poco::XML::InputSource* pInputSource, unsigned long namePoolSize);
+		/// Loads the XML document containing the configuration data
+		/// from the given InputSource. Uses the give namePoolSize (which 
+		/// should be a suitable prime like 251, 509, 1021, 4093) for the
+		/// internal DOM Document's name pool.
+
+	void load(std::istream& istr);
+		/// Loads the XML document containing the configuration data
+		/// from the given stream.
+		
+	void load(const std::string& path);
+		/// Loads the XML document containing the configuration data
+		/// from the given file.
+		
+	void load(const Poco::XML::Document* pDocument);
+		/// Loads the XML document containing the configuration data
+		/// from the given XML document.
+
+	void load(const Poco::XML::Node* pNode);
+		/// Loads the XML document containing the configuration data
+		/// from the given XML node.
+	
+	void loadEmpty(const std::string& rootElementName);
+		/// Loads an empty XML document containing only the
+		/// root element with the given name.
+		
+	void save(const std::string& path) const;
+		/// Writes the XML document containing the configuration data
+		/// to the file given by path.
+
+	void save(std::ostream& str) const;
+		/// Writes the XML document containing the configuration data
+		/// to the given stream.
+
+	void save(Poco::XML::DOMWriter& writer, const std::string& path) const;
+		/// Writes the XML document containing the configuration data
+		/// to the file given by path, using the given DOMWriter.
+		///
+		/// This can be used to use a DOMWriter with custom options.
+
+	void save(Poco::XML::DOMWriter& writer, std::ostream& str) const;
+		/// Writes the XML document containing the configuration data
+		/// to the given stream.
+		///
+		/// This can be used to use a DOMWriter with custom options.
+
+protected:
+	bool getRaw(const std::string& key, std::string& value) const;
+	void setRaw(const std::string& key, const std::string& value);
+	void enumerate(const std::string& key, Keys& range) const;
+	void removeRaw(const std::string& key);
+	~XMLConfiguration();
+
+private:
+	const Poco::XML::Node* findNode(const std::string& key) const;
+	Poco::XML::Node* findNode(const std::string& key);
+	Poco::XML::Node* findNode(std::string::const_iterator& it, const std::string::const_iterator& end, Poco::XML::Node* pNode, bool create = false) const;
+	static Poco::XML::Node* findElement(const std::string& name, Poco::XML::Node* pNode, bool create);
+	static Poco::XML::Node* findElement(int index, Poco::XML::Node* pNode, bool create);
+	static Poco::XML::Node* findElement(const std::string& attr, const std::string& value, Poco::XML::Node* pNode);
+	static Poco::XML::Node* findAttribute(const std::string& name, Poco::XML::Node* pNode, bool create);
+
+	Poco::XML::AutoPtr<Poco::XML::Node>     _pRoot;
+	Poco::XML::AutoPtr<Poco::XML::Document> _pDocument;
+	char _delim;
+};
+
+
+} } // namespace Poco::Util
+
+
+#endif // POCO_UTIL_NO_XMLCONFIGURATION
+
+
+#endif // Util_XMLConfiguration_INCLUDED
diff --git a/Poco/ValidArgs.h b/Poco/ValidArgs.h
new file mode 100644
index 0000000..7928a0f
--- /dev/null
+++ b/Poco/ValidArgs.h
@@ -0,0 +1,74 @@
+//
+// ValidArgs.h
+//
+// Library: Foundation
+// Package: Cache
+// Module:  ValidArgs
+//
+// Definition of the ValidArgs class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_ValidArgs_INCLUDED
+#define Foundation_ValidArgs_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+template <class TKey>
+class ValidArgs
+{
+public:
+	ValidArgs(const TKey& key):
+		_key(key), 
+		_isValid(true)
+	{
+	}
+
+	ValidArgs(const ValidArgs& args): 
+		_key(args._key), 
+		_isValid(args._isValid)
+	{
+	}
+
+	~ValidArgs()
+	{
+	}
+	
+	const TKey&	key() const
+	{
+		return _key;
+	}
+
+	bool isValid() const
+	{
+		return _isValid;
+	}
+
+	void invalidate()
+	{
+		_isValid = false;
+	}
+
+protected:
+	const TKey& _key;
+	bool        _isValid;
+
+private:
+	ValidArgs& operator = (const ValidArgs& args);
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_ValidArgs_INCLUDED
diff --git a/Poco/Version.h b/Poco/Version.h
new file mode 100644
index 0000000..8a43d9d
--- /dev/null
+++ b/Poco/Version.h
@@ -0,0 +1,41 @@
+//
+// Version.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Version
+//
+// Version information for the POCO C++ Libraries.
+//
+// Copyright (c) 2004-2016, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Version_INCLUDED
+#define Foundation_Version_INCLUDED
+
+
+//
+// Version Information
+//
+// Since 1.6.0, we're using Semantic Versioning 2.0
+// (http://semver.org/spec/v2.0.0.html)
+//
+// Version format is 0xAABBCCDD, where
+//    - AA is the major version number,
+//    - BB is the minor version number,
+//    - CC is the patch	version number, and
+//    - DD is the pre-release designation/number.
+//      The pre-release designation hex digits have a special meaning:
+//      00: final/stable releases
+//      Dx: development releases
+//      Ax: alpha releases
+//      Bx: beta releases
+//
+#define POCO_VERSION 0x01090200
+
+
+#endif // Foundation_Version_INCLUDED
diff --git a/Poco/Void.h b/Poco/Void.h
new file mode 100644
index 0000000..fa0cd31
--- /dev/null
+++ b/Poco/Void.h
@@ -0,0 +1,73 @@
+//
+// Void.h
+//
+// Library: Foundation
+// Package: Core
+// Module:  Void
+//
+// Definition of the Void class.
+//
+// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Void_INCLUDED
+#define Foundation_Void_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Void
+	/// A dummy class with value-type semantics, 
+	/// mostly useful as a template argument.
+	///
+	/// This class is typically used together with ActiveMethod,
+	/// if no argument or return value is needed.
+{
+public:
+	Void();
+		/// Creates the Void.
+
+	Void(const Void& v);
+		/// Creates the Void from another Void.
+		///
+		/// The philosophical aspects of this operation 
+		/// remain undiscussed for now.
+		
+	~Void();
+		/// Destroys the Void.
+
+	Void& operator = (const Void& v);
+		/// Assigns another void.
+
+	bool operator ==(const Void& v) const;
+		/// Will return always true due to Voids having no members.
+
+	bool operator !=(const Void& v) const;
+		/// Will return always false due to Voids having no members.
+};
+
+
+inline bool Void::operator ==(const Void& /*v*/) const
+{
+	return true;
+}
+
+
+inline bool Void::operator !=(const Void& /*v*/) const
+{
+	return false;
+}
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Void_INCLUDED
diff --git a/Poco/Windows1250Encoding.h b/Poco/Windows1250Encoding.h
new file mode 100644
index 0000000..c40a428
--- /dev/null
+++ b/Poco/Windows1250Encoding.h
@@ -0,0 +1,52 @@
+//
+// Windows1250Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Windows1250Encoding
+//
+// Definition of the Windows1250Encoding class.
+//
+// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Windows1250Encoding_INCLUDED
+#define Foundation_Windows1250Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Windows1250Encoding: public TextEncoding
+	/// Windows Codepage 1250 text encoding.
+	/// Based on: http://msdn.microsoft.com/en-us/goglobal/cc305143
+{
+public:
+	Windows1250Encoding();
+	~Windows1250Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Windows1250Encoding_INCLUDED
diff --git a/Poco/Windows1251Encoding.h b/Poco/Windows1251Encoding.h
new file mode 100644
index 0000000..87510a9
--- /dev/null
+++ b/Poco/Windows1251Encoding.h
@@ -0,0 +1,52 @@
+//
+// Windows1251Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Windows1251Encoding
+//
+// Definition of the Windows1251Encoding class.
+//
+// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Windows1251Encoding_INCLUDED
+#define Foundation_Windows1251Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Windows1251Encoding: public TextEncoding
+	/// Windows Codepage 1251 text encoding.
+	/// Based on: http://msdn.microsoft.com/en-us/goglobal/cc305144
+{
+public:
+	Windows1251Encoding();
+	~Windows1251Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Windows1251Encoding_INCLUDED
diff --git a/Poco/Windows1252Encoding.h b/Poco/Windows1252Encoding.h
new file mode 100644
index 0000000..a5e2901
--- /dev/null
+++ b/Poco/Windows1252Encoding.h
@@ -0,0 +1,51 @@
+//
+// Windows1252Encoding.h
+//
+// Library: Foundation
+// Package: Text
+// Module:  Windows1252Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_Windows1252Encoding_INCLUDED
+#define Foundation_Windows1252Encoding_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/TextEncoding.h"
+
+
+namespace Poco {
+
+
+class Foundation_API Windows1252Encoding: public TextEncoding
+	/// Windows Codepage 1252 text encoding.
+{
+public:
+	Windows1252Encoding();
+	~Windows1252Encoding();
+	const char* canonicalName() const;
+	bool isA(const std::string& encodingName) const;
+	const CharacterMap& characterMap() const;
+	int convert(const unsigned char* bytes) const;
+	int convert(int ch, unsigned char* bytes, int length) const;
+	int queryConvert(const unsigned char* bytes, int length) const;
+	int sequenceLength(const unsigned char* bytes, int length) const;
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_Windows1252Encoding_INCLUDED
diff --git a/Poco/Windows1253Encoding.h b/Poco/Windows1253Encoding.h
new file mode 100644
index 0000000..ef5af62
--- /dev/null
+++ b/Poco/Windows1253Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows1253Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows1253Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows1253Encoding_INCLUDED
+#define Encodings_Windows1253Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows1253Encoding: public DoubleByteEncoding
+	/// windows-1253 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1253.TXT.
+{
+public:
+	Windows1253Encoding();
+	~Windows1253Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows1253Encoding_INCLUDED
diff --git a/Poco/Windows1254Encoding.h b/Poco/Windows1254Encoding.h
new file mode 100644
index 0000000..558da86
--- /dev/null
+++ b/Poco/Windows1254Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows1254Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows1254Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows1254Encoding_INCLUDED
+#define Encodings_Windows1254Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows1254Encoding: public DoubleByteEncoding
+	/// windows-1254 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT.
+{
+public:
+	Windows1254Encoding();
+	~Windows1254Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows1254Encoding_INCLUDED
diff --git a/Poco/Windows1255Encoding.h b/Poco/Windows1255Encoding.h
new file mode 100644
index 0000000..e2b88fd
--- /dev/null
+++ b/Poco/Windows1255Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows1255Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows1255Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows1255Encoding_INCLUDED
+#define Encodings_Windows1255Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows1255Encoding: public DoubleByteEncoding
+	/// windows-1255 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1255.TXT.
+{
+public:
+	Windows1255Encoding();
+	~Windows1255Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows1255Encoding_INCLUDED
diff --git a/Poco/Windows1256Encoding.h b/Poco/Windows1256Encoding.h
new file mode 100644
index 0000000..1629cc8
--- /dev/null
+++ b/Poco/Windows1256Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows1256Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows1256Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows1256Encoding_INCLUDED
+#define Encodings_Windows1256Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows1256Encoding: public DoubleByteEncoding
+	/// windows-1256 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1256.TXT.
+{
+public:
+	Windows1256Encoding();
+	~Windows1256Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows1256Encoding_INCLUDED
diff --git a/Poco/Windows1257Encoding.h b/Poco/Windows1257Encoding.h
new file mode 100644
index 0000000..5fd7127
--- /dev/null
+++ b/Poco/Windows1257Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows1257Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows1257Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows1257Encoding_INCLUDED
+#define Encodings_Windows1257Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows1257Encoding: public DoubleByteEncoding
+	/// windows-1257 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT.
+{
+public:
+	Windows1257Encoding();
+	~Windows1257Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows1257Encoding_INCLUDED
diff --git a/Poco/Windows1258Encoding.h b/Poco/Windows1258Encoding.h
new file mode 100644
index 0000000..b735217
--- /dev/null
+++ b/Poco/Windows1258Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows1258Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows1258Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows1258Encoding_INCLUDED
+#define Encodings_Windows1258Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows1258Encoding: public DoubleByteEncoding
+	/// windows-1258 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT.
+{
+public:
+	Windows1258Encoding();
+	~Windows1258Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows1258Encoding_INCLUDED
diff --git a/Poco/Windows874Encoding.h b/Poco/Windows874Encoding.h
new file mode 100644
index 0000000..2434adf
--- /dev/null
+++ b/Poco/Windows874Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows874Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows874Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows874Encoding_INCLUDED
+#define Encodings_Windows874Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows874Encoding: public DoubleByteEncoding
+	/// windows-874 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP874.TXT.
+{
+public:
+	Windows874Encoding();
+	~Windows874Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows874Encoding_INCLUDED
diff --git a/Poco/Windows932Encoding.h b/Poco/Windows932Encoding.h
new file mode 100644
index 0000000..e2c9e9e
--- /dev/null
+++ b/Poco/Windows932Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows932Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows932Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows932Encoding_INCLUDED
+#define Encodings_Windows932Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows932Encoding: public DoubleByteEncoding
+	/// windows-932 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT.
+{
+public:
+	Windows932Encoding();
+	~Windows932Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows932Encoding_INCLUDED
diff --git a/Poco/Windows936Encoding.h b/Poco/Windows936Encoding.h
new file mode 100644
index 0000000..25910f2
--- /dev/null
+++ b/Poco/Windows936Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows936Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows936Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows936Encoding_INCLUDED
+#define Encodings_Windows936Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows936Encoding: public DoubleByteEncoding
+	/// windows-936 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT.
+{
+public:
+	Windows936Encoding();
+	~Windows936Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows936Encoding_INCLUDED
diff --git a/Poco/Windows949Encoding.h b/Poco/Windows949Encoding.h
new file mode 100644
index 0000000..974959a
--- /dev/null
+++ b/Poco/Windows949Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows949Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows949Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows949Encoding_INCLUDED
+#define Encodings_Windows949Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows949Encoding: public DoubleByteEncoding
+	/// windows-949 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT.
+{
+public:
+	Windows949Encoding();
+	~Windows949Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows949Encoding_INCLUDED
diff --git a/Poco/Windows950Encoding.h b/Poco/Windows950Encoding.h
new file mode 100644
index 0000000..21dc03c
--- /dev/null
+++ b/Poco/Windows950Encoding.h
@@ -0,0 +1,48 @@
+//
+// Windows950Encoding.h
+//
+// Library: Encodings
+// Package: Encodings
+// Module:  Windows950Encoding
+//
+// Definition of the Windows1252Encoding class.
+//
+// Copyright (c) 2018, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#ifndef Encodings_Windows950Encoding_INCLUDED
+#define Encodings_Windows950Encoding_INCLUDED
+
+
+#include "Poco/DoubleByteEncoding.h"
+
+
+namespace Poco {
+
+
+class Encodings_API Windows950Encoding: public DoubleByteEncoding
+	/// windows-950 Encoding.
+	///
+	/// This text encoding class has been generated from
+	/// http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT.
+{
+public:
+	Windows950Encoding();
+	~Windows950Encoding();
+	
+private:
+	static const char* _names[];
+	static const CharacterMap _charMap;
+	static const Mapping _mappingTable[];
+	static const Mapping _reverseMappingTable[];
+};
+
+
+} // namespace Poco
+
+
+#endif // Encodings_Windows950Encoding_INCLUDED
diff --git a/Poco/WindowsConsoleChannel.h b/Poco/WindowsConsoleChannel.h
new file mode 100644
index 0000000..b395c26
--- /dev/null
+++ b/Poco/WindowsConsoleChannel.h
@@ -0,0 +1,183 @@
+//
+// WindowsConsoleChannel.h
+//
+// Library: Foundation
+// Package: Logging
+// Module:  WindowsConsoleChannel
+//
+// Definition of the WindowsConsoleChannel class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Foundation_WindowsConsoleChannel_INCLUDED
+#define Foundation_WindowsConsoleChannel_INCLUDED
+
+
+#include "Poco/Foundation.h"
+#include "Poco/Channel.h"
+#include "Poco/Mutex.h"
+#include "Poco/UnWindows.h"
+
+
+namespace Poco {
+
+
+class Foundation_API WindowsConsoleChannel: public Channel
+	/// A channel that writes to the Windows console.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// If POCO has been compiled with POCO_WIN32_UTF8,
+	/// log messages are assumed to be UTF-8 encoded, and
+	/// are converted to UTF-16 prior to writing them to the
+	/// console. This is the main difference to the ConsoleChannel
+	/// class, which cannot handle UTF-8 encoded messages on Windows.
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is contained 
+	/// in the text.
+	///
+	/// Only available on Windows platforms.
+{
+public:
+	WindowsConsoleChannel();
+		/// Creates the WindowsConsoleChannel.
+
+	void log(const Message& msg);
+		/// Logs the given message to the channel's stream.
+		
+protected:
+	~WindowsConsoleChannel();
+
+private:
+	HANDLE _hConsole;
+	bool   _isFile;
+};
+
+
+class Foundation_API WindowsColorConsoleChannel: public Channel
+	/// A channel that writes to the Windows console.
+	///
+	/// Only the message's text is written, followed
+	/// by a newline.
+	///
+	/// If POCO has been compiled with POCO_WIN32_UTF8,
+	/// log messages are assumed to be UTF-8 encoded, and
+	/// are converted to UTF-16 prior to writing them to the
+	/// console. This is the main difference to the ConsoleChannel
+	/// class, which cannot handle UTF-8 encoded messages on Windows.
+	///
+	/// Messages can be colored depending on priority.
+	///
+	/// To enable message coloring, set the "enableColors"
+	/// property to true (default). Furthermore, colors can be
+	/// configured by setting the following properties
+	/// (default values are given in parenthesis):
+	/// 
+	///   * traceColor (gray)
+	///   * debugColor (gray)
+	///   * informationColor (default)
+	///   * noticeColor (default)
+	///   * warningColor (yellow)
+	///   * errorColor (lightRed)
+	///   * criticalColor (lightRed)
+	///   * fatalColor (lightRed)
+	///
+	/// The following color values are supported:
+	/// 
+	///   * default
+	///   * black
+	///   * red
+	///   * green
+	///   * brown
+	///   * blue
+	///   * magenta
+	///   * cyan
+	///   * gray
+	///   * darkgray
+	///   * lightRed
+	///   * lightGreen
+	///   * yellow
+	///   * lightBlue
+	///   * lightMagenta
+	///   * lightCyan
+	///   * white
+	///
+	/// Chain this channel to a FormattingChannel with an
+	/// appropriate Formatter to control what is contained 
+	/// in the text.
+	///
+	/// Only available on Windows platforms.
+{
+public:
+	WindowsColorConsoleChannel();
+		/// Creates the WindowsConsoleChannel.
+
+	void log(const Message& msg);
+		/// Logs the given message to the channel's stream.
+
+	void setProperty(const std::string& name, const std::string& value);
+		/// Sets the property with the given name. 
+		/// 
+		/// The following properties are supported:
+		///   * enableColors:      Enable or disable colors.
+		///   * traceColor:        Specify color for trace messages.
+		///   * debugColor:        Specify color for debug messages.
+		///   * informationColor:  Specify color for information messages.
+		///   * noticeColor:       Specify color for notice messages.
+		///   * warningColor:      Specify color for warning messages.
+		///   * errorColor:        Specify color for error messages.
+		///   * criticalColor:     Specify color for critical messages.
+		///   * fatalColor:        Specify color for fatal messages.
+		///
+		/// See the class documentation for a list of supported color values.
+
+	std::string getProperty(const std::string& name) const;
+		/// Returns the value of the property with the given name.
+		/// See setProperty() for a description of the supported
+		/// properties.
+		
+protected:
+	enum Color
+	{
+		CC_BLACK        = 0x0000,
+		CC_RED          = 0x0004,
+		CC_GREEN        = 0x0002,
+		CC_BROWN        = 0x0006,
+		CC_BLUE         = 0x0001,
+		CC_MAGENTA      = 0x0005,
+		CC_CYAN         = 0x0003,
+		CC_GRAY         = 0x0007,
+		CC_DARKGRAY     = 0x0008,
+		CC_LIGHTRED     = 0x000C,
+		CC_LIGHTGREEN   = 0x000A,
+		CC_YELLOW       = 0x000E,
+		CC_LIGHTBLUE    = 0x0009,
+		CC_LIGHTMAGENTA = 0x000D,
+		CC_LIGHTCYAN    = 0x000B,
+		CC_WHITE        = 0x000F
+	};
+
+	~WindowsColorConsoleChannel();
+	WORD parseColor(const std::string& color) const;
+	std::string formatColor(WORD color) const;
+	void initColors();
+
+private:
+	bool _enableColors;
+	HANDLE _hConsole;
+	bool   _isFile;
+	WORD   _colors[9];
+};
+
+
+} // namespace Poco
+
+
+#endif // Foundation_WindowsConsoleChannel_INCLUDED
diff --git a/Poco/XML/Content.h b/Poco/XML/Content.h
new file mode 100644
index 0000000..8b2b312
--- /dev/null
+++ b/Poco/XML/Content.h
@@ -0,0 +1,63 @@
+//
+// Content.h
+//
+// Library: XML
+// Package: XML
+// Module:  Content
+//
+// Definition of the Content enum.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Based on libstudxml (http://www.codesynthesis.com/projects/libstudxml/).
+// Copyright (c) 2009-2013 Code Synthesis Tools CC.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_Content_INCLUDED
+#define XML_Content_INCLUDED
+
+
+namespace Poco {
+namespace XML {
+
+
+struct Content
+	/// XML content model. C++11 enum class emulated for C++98.
+	///
+	///               element   characters  whitespaces  notes
+	///     Empty     no          no        ignored
+	///     Simple    no          yes       preserved    content accumulated
+	///     Complex   yes         no        ignored
+	///     Mixed     yes         yes       preserved
+{
+	enum value
+	{
+		Empty,
+		Simple,
+		Complex,
+		Mixed
+	};
+
+	Content(value v)
+		: _v(v)
+	{
+	}
+
+	operator value() const
+	{
+		return _v;
+	}
+
+private:
+	value _v;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_Content_INCLUDED
diff --git a/Poco/XML/Name.h b/Poco/XML/Name.h
new file mode 100644
index 0000000..d21219b
--- /dev/null
+++ b/Poco/XML/Name.h
@@ -0,0 +1,138 @@
+//
+// Name.h
+//
+// Library: XML
+// Package: XML
+// Module:  Name
+//
+// Definition of the Name class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_Name_INCLUDED
+#define XML_Name_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API Name
+	/// An XML element or attribute name, consisting of a
+	/// qualified name, a namespace URI and a local name.
+{
+public:
+	Name();
+		/// Creates an empty Name.
+		
+	Name(const XMLString& qname);
+		/// Creates a Name from a qualified name only.
+
+	Name(const XMLString& qname, const XMLString& namespaceURI);
+		/// Creates a Name from a qualified name and a namespace URI.
+		/// The local name is extracted from the qualified name.
+		
+	Name(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName);
+		/// Creates a Name from a qualified name, a namespace URI and a local name.
+		
+	Name(const Name& name);
+		/// Copy constructor.
+		
+	~Name();
+		/// Destroys the name.
+		
+	Name& operator = (const Name& name);
+		/// Assignment operator.
+		
+	void swap(Name& name);
+		/// Swaps the name with another one.	
+		
+	void assign(const XMLString& qname);
+		/// Assigns a new value to the name.
+
+	void assign(const XMLString& qname, const XMLString& namespaceURI);
+		/// Assigns new values to the name.
+		/// The local name is extracted from the qualified name.
+
+	void assign(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName);
+		/// Assigns new values to the name.
+	
+	bool equals(const Name& name) const;
+		/// Returns true if both names are equal.
+		
+	bool equals(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns true if all the name's components are equal to the given ones.
+
+	bool equalsWeakly(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName) const;
+		/// Returns true if either the qnames are identical or the namespaceURIs and the localNames are identical.
+	
+	const XMLString& qname() const;
+		/// Returns the qualified name.
+		
+	const XMLString& namespaceURI() const;
+		/// Returns the namespace URI.
+		
+	const XMLString& localName() const;
+		/// Returns the local name.
+		
+	XMLString prefix() const;
+		/// Returns the namespace prefix.
+		
+	static void split(const XMLString& qname, XMLString& prefix, XMLString& localName);
+		/// Splits the given qualified name into its prefix and localName parts.
+	
+	static XMLString localName(const XMLString& qname);
+		/// Returns the local name part of the given qualified name.
+
+	static XMLString prefix(const XMLString& qname);
+		/// Returns the prefix part of the given qualified name.
+
+	static const XMLString EMPTY_NAME;
+
+private:
+	XMLString _qname;
+	XMLString _namespaceURI;
+	XMLString _localName;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& Name::qname() const
+{
+	return _qname;
+}
+
+
+inline const XMLString& Name::namespaceURI() const
+{
+	return _namespaceURI;
+}
+
+
+inline const XMLString& Name::localName() const
+{
+	return _localName;
+}
+
+
+inline void swap(Name& n1, Name& n2)
+{
+	n1.swap(n2);
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_Name_INCLUDED
diff --git a/Poco/XML/NamePool.h b/Poco/XML/NamePool.h
new file mode 100644
index 0000000..9ffadf1
--- /dev/null
+++ b/Poco/XML/NamePool.h
@@ -0,0 +1,83 @@
+//
+// NamePool.h
+//
+// Library: XML
+// Package: XML
+// Module:  NamePool
+//
+// Definition of the NamePool class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_NamePool_INCLUDED
+#define XML_NamePool_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/XML/Name.h"
+
+
+#ifndef POCO_XML_NAMEPOOL_DEFAULT_SIZE
+#define POCO_XML_NAMEPOOL_DEFAULT_SIZE 509
+#endif
+
+
+namespace Poco {
+namespace XML {
+
+
+class NamePoolItem;
+
+
+class XML_API NamePool
+	/// A hashtable that stores XML names consisting of an URI, a
+	/// local name and a qualified name.
+{
+public:
+	NamePool(unsigned long size = POCO_XML_NAMEPOOL_DEFAULT_SIZE);
+		/// Creates a name pool with room for up to size strings.
+		///
+		/// The given size should be a suitable prime number, 
+		/// e.g. 251, 509, 1021 or 4093.
+	
+	const Name& insert(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName);	
+		/// Returns a const reference to an Name for the given names.
+		/// Creates the Name if it does not already exist.
+		/// Throws a PoolOverflowException if the name pool is full.
+
+	const Name& insert(const Name& name);	
+		/// Returns a const reference to an Name for the given name.
+		/// Creates the Name if it does not already exist.
+		/// Throws a PoolOverflowException if the name pool is full.
+
+	void duplicate();
+		/// Increments the reference count.
+
+	void release();
+		/// Decrements the reference count and deletes the object if the reference count reaches zero.
+
+protected:
+	unsigned long hash(const XMLString& qname, const XMLString& namespaceURI, const XMLString& localName);
+	~NamePool();
+
+private:
+	NamePool(const NamePool&);
+	NamePool& operator = (const NamePool&);
+
+	NamePoolItem* _pItems;
+	unsigned long _size;
+	unsigned long _salt;
+	int           _rc;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_NamePool_INCLUDED
diff --git a/Poco/XML/NamespaceStrategy.h b/Poco/XML/NamespaceStrategy.h
new file mode 100644
index 0000000..1f27e3c
--- /dev/null
+++ b/Poco/XML/NamespaceStrategy.h
@@ -0,0 +1,115 @@
+//
+// NamespaceStrategy.h
+//
+// Library: XML
+// Package: XML
+// Module:  NamespaceStrategy
+//
+// Definition of the NamespaceStrategy class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_NamespaceStrategy_INCLUDED
+#define XML_NamespaceStrategy_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/SAX/NamespaceSupport.h"
+#include "Poco/SAX/AttributesImpl.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class ContentHandler;
+
+
+class XML_API NamespaceStrategy
+	/// This class is used by ParserEngine to handle the
+	/// startElement, endElement, startPrefixMapping and
+	/// endPrefixMapping events.
+{
+public:
+	virtual ~NamespaceStrategy();
+
+	virtual void startElement(const XMLChar* name, const XMLChar** atts, int specifiedCount, ContentHandler* pContentHandler) = 0;
+		/// Translate the arguments as delivered by Expat and
+		/// call the startElement() method of the ContentHandler.
+		
+	virtual void endElement(const XMLChar* name, ContentHandler* pContentHandler) = 0;
+		/// Translate the arguments as delivered by Expat and
+		/// call the endElement() method of the ContentHandler.
+
+protected:
+	static void splitName(const XMLChar* qname, XMLString& uri, XMLString& localName);
+	static void splitName(const XMLChar* qname, XMLString& uri, XMLString& localName, XMLString& prefix);
+
+	static const XMLString NOTHING;
+};
+
+
+class XML_API NoNamespacesStrategy: public NamespaceStrategy
+	/// The NamespaceStrategy implementation used if no namespaces
+	/// processing is requested.
+{
+public:
+	NoNamespacesStrategy();
+	~NoNamespacesStrategy();
+	
+	void startElement(const XMLChar* name, const XMLChar** atts, int specifiedCount, ContentHandler* pContentHandler);
+	void endElement(const XMLChar* name, ContentHandler* pContentHandler);
+	
+private:
+	XMLString _name;
+	AttributesImpl _attrs;
+};
+
+
+class XML_API NoNamespacePrefixesStrategy: public NamespaceStrategy
+	/// The NamespaceStrategy implementation used if namespaces
+	/// processing is requested, but prefixes are not reported.
+{
+public:
+	NoNamespacePrefixesStrategy();
+	~NoNamespacePrefixesStrategy();
+	
+	void startElement(const XMLChar* name, const XMLChar** atts, int specifiedCount, ContentHandler* pContentHandler);
+	void endElement(const XMLChar* name, ContentHandler* pContentHandler);
+
+private:
+	XMLString _uri;
+	XMLString _local;
+	AttributesImpl _attrs;
+};
+
+
+class XML_API NamespacePrefixesStrategy: public NamespaceStrategy
+	/// The NamespaceStrategy implementation used if namespaces
+	/// processing is requested and prefixes are reported.
+{
+public:
+	NamespacePrefixesStrategy();
+	~NamespacePrefixesStrategy();
+	
+	void startElement(const XMLChar* name, const XMLChar** atts, int specifiedCount, ContentHandler* pContentHandler);
+	void endElement(const XMLChar* name, ContentHandler* pContentHandler);
+	
+private:
+	XMLString _uri;
+	XMLString _local;
+	XMLString _qname;
+	AttributesImpl _attrs;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_NamespaceStrategy_INCLUDED
diff --git a/Poco/XML/ParserEngine.h b/Poco/XML/ParserEngine.h
new file mode 100644
index 0000000..665d378
--- /dev/null
+++ b/Poco/XML/ParserEngine.h
@@ -0,0 +1,358 @@
+//
+// ParserEngine.h
+//
+// Library: XML
+// Package: XML
+// Module:  ParserEngine
+//
+// Definition of the ParseEngine class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+
+
+#ifndef XML_ParserEngine_INCLUDED
+#define XML_ParserEngine_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#if defined(POCO_UNBUNDLED)
+#include <expat.h>
+#else
+#include "Poco/XML/expat.h"
+#endif
+#include "Poco/XML/XMLString.h"
+#include "Poco/XML/XMLStream.h"
+#include "Poco/SAX/Locator.h"
+#include "Poco/TextEncoding.h"
+#include <map>
+#include <vector>
+
+
+namespace Poco {
+namespace XML {
+
+
+class InputSource;
+class EntityResolver;
+class DTDHandler;
+class DeclHandler;
+class ContentHandler;
+class LexicalHandler;
+class ErrorHandler;
+class NamespaceStrategy;
+class ContextLocator;
+
+
+class XML_API ParserEngine: public Locator
+	/// This class provides an object-oriented, stream-based, 
+	/// low-level interface to the XML Parser Toolkit (expat).
+	/// It is strongly recommended, that you use the
+	/// SAX parser classes (which are based on this
+	/// class) instead of this class, since they provide 
+	/// a standardized, higher-level interface to the parser.
+{
+public:
+	ParserEngine();
+		/// Creates the parser engine.
+		
+	ParserEngine(const XMLString& encoding);
+		/// Creates the parser engine and passes the encoding
+		/// to the underlying parser.
+		
+	~ParserEngine();
+		/// Destroys the parser.
+
+	void setEncoding(const XMLString& encoding);
+		/// Sets the encoding used by expat. The encoding must be
+		/// set before parsing begins, otherwise it will be ignored.
+		
+	const XMLString& getEncoding() const;
+		/// Returns the encoding used by expat.
+
+	void addEncoding(const XMLString& name, Poco::TextEncoding* pEncoding);
+		/// Adds an encoding to the parser.
+
+	void setNamespaceStrategy(NamespaceStrategy* pStrategy);
+		/// Sets the NamespaceStrategy used by the parser.
+		/// The parser takes ownership of the strategy object
+		/// and deletes it when it's no longer needed.
+		/// The default is NoNamespacesStrategy.
+		
+	NamespaceStrategy* getNamespaceStrategy() const;
+		/// Returns the NamespaceStrategy currently in use.
+
+	void setExpandInternalEntities(bool flag = true);
+		/// Enables/disables expansion of internal entities (enabled by
+		/// default). If entity expansion is disabled, internal entities 
+		/// are reported via the default handler.
+		/// Must be set before parsing begins, otherwise it will be
+		/// ignored.
+		
+	bool getExpandInternalEntities() const;
+		/// Returns true if internal entities will be expanded automatically,
+		/// which is the default.
+
+	void setExternalGeneralEntities(bool flag = true);
+		/// Enable or disable processing of external general entities.
+		
+	bool getExternalGeneralEntities() const;
+		/// Returns true if external general entities will be processed; false otherwise.
+
+	void setExternalParameterEntities(bool flag = true);
+		/// Enable or disable processing of external parameter entities.
+		
+	bool getExternalParameterEntities() const;
+		/// Returns true if external parameter entities will be processed; false otherwise.
+		
+	void setEntityResolver(EntityResolver* pResolver);
+		/// Allow an application to register an entity resolver.
+
+	EntityResolver* getEntityResolver() const;
+		/// Return the current entity resolver.
+
+	void setDTDHandler(DTDHandler* pDTDHandler);
+		/// Allow an application to register a DTD event handler.
+
+	DTDHandler* getDTDHandler() const;
+		/// Return the current DTD handler.
+
+	void setDeclHandler(DeclHandler* pDeclHandler);
+		/// Allow an application to register a DTD declarations event handler.
+		
+	DeclHandler* getDeclHandler() const;
+		/// Return the current DTD declarations handler.
+
+	void setContentHandler(ContentHandler* pContentHandler);
+		/// Allow an application to register a content event handler.
+
+	ContentHandler* getContentHandler() const;
+		/// Return the current content handler.
+
+	void setLexicalHandler(LexicalHandler* pLexicalHandler);
+		/// Allow an application to register a lexical event handler.
+		
+	LexicalHandler* getLexicalHandler() const;
+		/// Return the current lexical handler.
+
+	void setErrorHandler(ErrorHandler* pErrorHandler);
+		/// Allow an application to register an error event handler.
+
+	ErrorHandler* getErrorHandler() const;
+		/// Return the current error handler.
+		
+	void setEnablePartialReads(bool flag = true);
+		/// Enable or disable partial reads from the input source.
+		///
+		/// This is useful for parsing XML from a socket stream for
+		/// a protocol like XMPP, where basically single elements 
+		/// are read one at a time from the input source's stream, and
+		/// following elements depend upon responses sent back to
+		/// the peer.
+		///
+		/// Normally, the parser always reads blocks of PARSE_BUFFER_SIZE
+		/// at a time, and blocks until a complete block has been read (or
+		/// the end of the stream has been reached).
+		/// This allows for efficient parsing of "complete" XML documents,
+		/// but fails in a case such as XMPP, where only XML fragments
+		/// are sent at a time.
+		
+	bool getEnablePartialReads() const;
+		/// Returns true if partial reads are enabled (see
+		/// setEnablePartialReads()), false otherwise.
+	
+	void parse(InputSource* pInputSource);
+		/// Parse an XML document from the given InputSource.
+		
+	void parse(const char* pBuffer, std::size_t size);
+		/// Parses an XML document from the given buffer.
+	
+	// Locator
+	XMLString getPublicId() const;
+		/// Return the public identifier for the current document event.
+	
+	XMLString getSystemId() const;
+		/// Return the system identifier for the current document event.
+
+	int getLineNumber() const;
+		/// Return the line number where the current document event ends.
+
+	int getColumnNumber() const;
+		/// Return the column number where the current document event ends. 
+
+protected:
+	void init();
+		/// initializes expat
+
+	void parseByteInputStream(XMLByteInputStream& istr);
+		/// Parses an entity from the given stream.
+
+	void parseCharInputStream(XMLCharInputStream& istr);
+		/// Parses an entity from the given stream.
+		
+	std::streamsize readBytes(XMLByteInputStream& istr, char* pBuffer, std::streamsize bufferSize);
+		/// Reads at most bufferSize bytes from the given stream into the given buffer.
+
+	std::streamsize readChars(XMLCharInputStream& istr, XMLChar* pBuffer, std::streamsize bufferSize);
+		/// Reads at most bufferSize chars from the given stream into the given buffer.
+
+	void handleError(int errorNo);
+		/// Throws an XMLException with a message corresponding
+		/// to the given Expat error code.
+
+	void parseExternal(XML_Parser extParser, InputSource* pInputSource);
+		/// Parse an XML document from the given InputSource.
+
+	void parseExternalByteInputStream(XML_Parser extParser, XMLByteInputStream& istr);
+		/// Parses an external entity from the given stream, with a separate parser.
+
+	void parseExternalCharInputStream(XML_Parser extParser, XMLCharInputStream& istr);
+		/// Parses an external entity from the given stream, with a separate parser.
+
+	void pushContext(XML_Parser parser, InputSource* pInputSource);
+		/// Pushes a new entry to the context stack.
+		
+	void popContext();
+		/// Pops the top-most entry from the context stack.
+	
+	void resetContext();
+		/// Resets and clears the context stack.
+
+	const Locator& locator() const;
+		/// Returns a locator denoting the current parse location.
+
+	// expat handler procedures
+	static void handleStartElement(void* userData, const XML_Char* name, const XML_Char** atts);
+	static void handleEndElement(void* userData, const XML_Char* name);
+	static void handleCharacterData(void* userData, const XML_Char* s, int len);
+	static void handleProcessingInstruction(void* userData, const XML_Char* target, const XML_Char* data);
+	static void handleDefault(void* userData, const XML_Char* s, int len);
+	static void handleUnparsedEntityDecl(void* userData, const XML_Char* entityName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId, const XML_Char* notationName);
+	static void handleNotationDecl(void* userData, const XML_Char* notationName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
+	static int handleExternalEntityRef(XML_Parser parser, const XML_Char* openEntityNames, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
+	static int handleUnknownEncoding(void* encodingHandlerData, const XML_Char* name, XML_Encoding* info);
+	static void handleComment(void* userData, const XML_Char* data);
+	static void handleStartCdataSection(void* userData);
+	static void handleEndCdataSection(void* userData);
+	static void handleStartNamespaceDecl(void* userData, const XML_Char* prefix, const XML_Char* uri);
+	static void handleEndNamespaceDecl(void* userData, const XML_Char* prefix);
+	static void handleStartDoctypeDecl(void* userData, const XML_Char* doctypeName, const XML_Char *systemId, const XML_Char* publicId, int hasInternalSubset);
+	static void handleEndDoctypeDecl(void* userData);
+	static void handleEntityDecl(void *userData, const XML_Char *entityName, int isParamEntity, const XML_Char *value, int valueLength, 
+	                             const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName);
+	static void handleExternalParsedEntityDecl(void* userData, const XML_Char* entityName, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
+	static void handleInternalParsedEntityDecl(void* userData, const XML_Char* entityName, const XML_Char* replacementText, int replacementTextLength);
+	static void handleSkippedEntity(void* userData, const XML_Char* entityName, int isParameterEntity);
+
+	// encoding support
+	static int convert(void *data, const char *s);
+	
+private:
+	typedef std::map<XMLString, Poco::TextEncoding*> EncodingMap;
+	typedef std::vector<ContextLocator*> ContextStack;
+	
+	XML_Parser _parser;
+	char*      _pBuffer;
+	bool       _encodingSpecified; 
+	XMLString  _encoding;
+	bool       _expandInternalEntities;
+	bool       _externalGeneralEntities;
+	bool       _externalParameterEntities;
+	bool       _enablePartialReads;
+	NamespaceStrategy* _pNamespaceStrategy;
+	EncodingMap        _encodings;
+	ContextStack       _context;
+	
+	EntityResolver* _pEntityResolver;
+	DTDHandler*     _pDTDHandler;
+	DeclHandler*    _pDeclHandler;
+	ContentHandler* _pContentHandler;
+	LexicalHandler* _pLexicalHandler;
+	ErrorHandler*   _pErrorHandler;
+	
+	static const int PARSE_BUFFER_SIZE;
+	static const XMLString EMPTY_STRING;
+};
+
+
+//
+// inlines
+//
+inline const XMLString& ParserEngine::getEncoding() const
+{
+	return _encoding;
+}
+
+
+inline NamespaceStrategy* ParserEngine::getNamespaceStrategy() const
+{
+	return _pNamespaceStrategy;
+}
+
+
+inline bool ParserEngine::getExpandInternalEntities() const
+{
+	return _expandInternalEntities;
+}
+
+
+inline bool ParserEngine::getExternalGeneralEntities() const
+{
+	return _externalGeneralEntities;
+}
+
+
+inline bool ParserEngine::getExternalParameterEntities() const
+{
+	return _externalParameterEntities;
+}
+
+
+inline EntityResolver* ParserEngine::getEntityResolver() const
+{
+	return _pEntityResolver;
+}
+
+
+inline DTDHandler* ParserEngine::getDTDHandler() const
+{
+	return _pDTDHandler;
+}
+
+
+inline DeclHandler* ParserEngine::getDeclHandler() const
+{
+	return _pDeclHandler;
+}
+
+
+inline ContentHandler* ParserEngine::getContentHandler() const
+{
+	return _pContentHandler;
+}
+
+
+inline LexicalHandler* ParserEngine::getLexicalHandler() const
+{
+	return _pLexicalHandler;
+}
+
+
+inline ErrorHandler* ParserEngine::getErrorHandler() const
+{
+	return _pErrorHandler;
+}
+
+
+inline bool ParserEngine::getEnablePartialReads() const
+{
+	return _enablePartialReads;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_ParserEngine_INCLUDED
diff --git a/Poco/XML/QName.h b/Poco/XML/QName.h
new file mode 100644
index 0000000..6a6a246
--- /dev/null
+++ b/Poco/XML/QName.h
@@ -0,0 +1,135 @@
+//
+// QName.h
+//
+// Library: XML
+// Package: XML
+// Module:  QName
+//
+// Definition of the QName class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Based on libstudxml (http://www.codesynthesis.com/projects/libstudxml/).
+// Copyright (c) 2009-2013 Code Synthesis Tools CC.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_QName_INCLUDED
+#define XML_QName_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include <string>
+#include <iosfwd>
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API QName
+	/// This class represents a qualified XML name in the stream parser.
+	///
+	/// Note that the optional prefix is just a "syntactic sugar". In
+	/// particular, it is ignored by the comparison operators and the
+	/// std::ostream insertion operator.
+{
+public:
+	QName();
+	QName(const std::string& name);
+	QName(const std::string& ns, const std::string& name);
+	QName(const std::string& ns, const std::string& name, const std::string& prefix);
+
+	const std::string& namespaceURI() const;
+		/// Returns the namespace URI part of the name.
+
+	const std::string& localName() const;
+		/// Returns the local part of the name.
+		
+	const std::string& prefix() const;
+		/// Returns the namespace prefix of the name.
+		
+	std::string& namespaceURI();
+		/// Returns the namespace URI part of the name.
+
+	std::string& localName();
+		/// Returns the local part of the name.
+
+	std::string& prefix();
+		/// Returns the namespace prefix of the name.
+
+	std::string toString() const;
+		/// Returns a printable representation in the [<namespace>#]<name> form.
+	
+public:
+	friend bool operator < (const QName& x, const QName& y)
+	{
+		return x._ns < y._ns || (x._ns == y._ns && x._name < y._name);
+	}
+
+	friend bool operator == (const QName& x, const QName& y)
+	{
+		return x._ns == y._ns && x._name == y._name;
+	}
+
+	friend bool operator != (const QName& x, const QName& y)
+	{
+		return !(x == y);
+	}
+
+private:
+	std::string _ns;
+	std::string _name;
+	std::string _prefix;
+};
+
+
+//
+// inlines
+//
+inline const std::string& QName::namespaceURI() const
+{
+	return _ns;
+}
+
+
+inline const std::string& QName::localName() const
+{
+	return _name;
+}
+
+
+inline const std::string& QName::prefix() const
+{
+	return _prefix;
+}
+
+
+inline std::string& QName::namespaceURI()
+{
+	return _ns;
+}
+
+
+inline std::string& QName::localName()
+{
+	return _name;
+}
+
+
+inline std::string& QName::prefix()
+{
+	return _prefix;
+}
+
+
+XML_API std::ostream& operator << (std::ostream&, const QName&);
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_QName_INCLUDED
diff --git a/Poco/XML/ValueTraits.h b/Poco/XML/ValueTraits.h
new file mode 100644
index 0000000..46631c9
--- /dev/null
+++ b/Poco/XML/ValueTraits.h
@@ -0,0 +1,104 @@
+//
+// ValueTraits.h
+//
+// Library: XML
+// Package: XML
+// Module:  ValueTraits
+//
+// Definition of the ValueTraits templates.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Based on libstudxml (http://www.codesynthesis.com/projects/libstudxml/).
+// Copyright (c) 2009-2013 Code Synthesis Tools CC.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_ValueTraits_INCLUDED
+#define XML_ValueTraits_INCLUDED
+
+
+#include "XMLStreamParserException.h"
+#include <string>
+#include <cstddef>
+#include <iostream>
+#include <sstream>
+
+
+namespace Poco {
+namespace XML {
+
+
+class XMLStreamParser;
+class XMLStreamSerializer;
+
+
+template <typename T>
+struct DefaultValueTraits
+{
+	static T
+	parse(std::string, const XMLStreamParser&);
+
+	static std::string
+	serialize(const T&, const XMLStreamSerializer&);
+};
+
+
+template <>
+struct XML_API DefaultValueTraits<bool>
+{
+	static bool
+	parse(std::string, const XMLStreamParser&);
+
+	static std::string serialize(bool v, const XMLStreamSerializer&)
+	{
+		return v ? "true" : "false";
+	}
+};
+
+
+template <>
+struct XML_API DefaultValueTraits<std::string>
+{
+	static std::string parse(std::string s, const XMLStreamParser&)
+	{
+		return s;
+	}
+
+	static std::string serialize(const std::string& v, const XMLStreamSerializer&)
+	{
+		return v;
+	}
+};
+
+
+template <typename T>
+struct ValueTraits: DefaultValueTraits<T>
+{
+};
+
+
+template <typename T, std::size_t N>
+struct ValueTraits<T[N]> : DefaultValueTraits<const T*>
+{
+};
+
+
+template <typename T>
+T DefaultValueTraits<T>::parse(std::string s, const XMLStreamParser& p)
+{
+	T r;
+	std::istringstream is(s);
+	if (!(is >> r && is.eof()))
+		throw XMLStreamParserException(p, "invalid value '" + s + "'");
+	return r;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_ValueTraits_INCLUDED
diff --git a/Poco/XML/XML.h b/Poco/XML/XML.h
new file mode 100644
index 0000000..19a21a3
--- /dev/null
+++ b/Poco/XML/XML.h
@@ -0,0 +1,62 @@
+//
+// XML.h
+//
+// Library: XML
+// Package: XML
+// Module:  XML
+//
+// Basic definitions for the Poco XML library.
+// This file must be the first file included by every other XML
+// header file.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XML_INCLUDED
+#define XML_XML_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting 
+// from a DLL simpler. All files within this DLL are compiled with the XML_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see 
+// XML_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(XML_EXPORTS)
+		#define XML_API __declspec(dllexport)
+	#else
+		#define XML_API __declspec(dllimport)	
+	#endif
+#endif
+
+
+#if !defined(XML_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define XML_API __attribute__ ((visibility ("default")))
+	#else
+		#define XML_API
+	#endif
+#endif
+
+
+//
+// Automatically link XML library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(XML_EXPORTS)
+		#pragma comment(lib, "PocoXML" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // XML_XML_INCLUDED
diff --git a/Poco/XML/XMLException.h b/Poco/XML/XMLException.h
new file mode 100644
index 0000000..9805bad
--- /dev/null
+++ b/Poco/XML/XMLException.h
@@ -0,0 +1,37 @@
+//
+// XMLException.h
+//
+// Library: XML
+// Package: XML
+// Module:  XMLException
+//
+// Definition of the XMLException class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XMLException_INCLUDED
+#define XML_XMLException_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+POCO_DECLARE_EXCEPTION(XML_API, XMLException, Poco::RuntimeException)
+	/// The base class for all XML-related exceptions like SAXException
+	/// and DOMException.
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_XMLException_INCLUDED
diff --git a/Poco/XML/XMLStream.h b/Poco/XML/XMLStream.h
new file mode 100644
index 0000000..e75705a
--- /dev/null
+++ b/Poco/XML/XMLStream.h
@@ -0,0 +1,71 @@
+//
+// XMLStream.h
+//
+// Library: XML
+// Package: XML
+// Module:  XMLStream
+//
+// Definition of the XMLByteInputStream and XMLCharInputStream classes.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XMLStream_INCLUDED
+#define XML_XMLStream_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace XML {
+
+
+// The byte input stream is always a narrow stream.
+typedef std::istream XMLByteInputStream;
+typedef std::ostream XMLByteOutputStream;
+
+
+//
+// The XML parser uses the stream classes provided by the C++
+// standard library (based on the basic_stream<> template).
+// In Unicode mode, a wide stream is used.
+// To turn on Unicode mode, #define XML_UNICODE and
+// XML_UNICODE_WCHAR_T when compiling the library.
+//
+// XML_UNICODE  XML_UNICODE_WCHAR_T  XMLCharInputStream  XMLCharOutputStream
+// -------------------------------------------------------------------------
+//     N                 N           std::istream        std::ostream
+//     N                 Y           std::wistream       std::wostream
+//     Y                 Y           std::wistream       std::wostream
+//     Y                 N           <not supported>
+//
+#if defined(XML_UNICODE_WCHAR_T)
+
+	// Unicode - use wide streams
+	typedef std::wistream XMLCharInputStream;
+	typedef std::wostream XMLCharOutputStream;
+
+#elif defined(XML_UNICODE)
+
+	// not supported - leave XMLString undefined
+
+#else
+
+	// Characters are UTF-8 encoded
+	typedef std::istream XMLCharInputStream;
+	typedef std::ostream XMLCharOutputStream;
+
+#endif
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_XMLStream_INCLUDED
diff --git a/Poco/XML/XMLStreamParser.h b/Poco/XML/XMLStreamParser.h
new file mode 100644
index 0000000..99520eb
--- /dev/null
+++ b/Poco/XML/XMLStreamParser.h
@@ -0,0 +1,634 @@
+//
+// XMLStreamParser.h
+//
+// Library: XML
+// Package: XML
+// Module:  XMLStreamParser
+//
+// Definition of the XMLStreamParser class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Based on libstudxml (http://www.codesynthesis.com/projects/libstudxml/).
+// Copyright (c) 2009-2013 Code Synthesis Tools CC.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XMLStreamParser_INCLUDED
+#define XML_XMLStreamParser_INCLUDED
+
+
+// We only support UTF-8 expat.
+#ifdef XML_UNICODE
+#error UTF-16 expat (XML_UNICODE defined) is not supported
+#endif
+
+
+#include "Poco/XML/QName.h"
+#include "Poco/XML/ValueTraits.h"
+#include "Poco/XML/Content.h"
+#if defined(POCO_UNBUNDLED)
+#include <expat.h>
+#else
+#include "Poco/XML/expat.h"
+#endif
+#include <map>
+#include <vector>
+#include <string>
+#include <iosfwd>
+#include <cstddef>
+
+
+namespace Poco {
+namespace XML {
+
+
+class XML_API XMLStreamParser
+	/// The streaming XML pull parser and streaming XML serializer. The parser
+	/// is a conforming, non-validating XML 1.0 implementation (see Implementation Notes
+	/// for details). The application character encoding (that is, the encoding used
+	/// in the application's memory) for both parser and serializer is UTF-8.
+	/// The output encoding of the serializer is UTF-8 as well. The parser supports
+	/// UTF-8, UTF-16, ISO-8859-1, and US-ASCII input encodings.
+	///
+	/// Attribute map:
+	///
+	/// Attribute map lookup. If attribute is not found, then the version
+	/// without the default value throws an appropriate parsing exception
+	/// while the version with the default value returns that value.
+	///
+	/// Note also that there is no attribute(ns, name) version since it
+	/// would conflict with attribute(name, dv) (qualified attributes
+	/// are not very common).
+	///
+	/// Attribute map is valid throughout at the "element level" until
+	/// end_element and not just during EV_START_ELEMENT. As a special case,
+	/// the map is still valid after peek() that returned end_element until
+	/// this end_element event is retrieved with next().
+	///
+	/// Using parser:
+	///
+	///     XMLStreamParser p(ifs, argv[1]);
+	///     for (XMLStreamParser::EventType e: p)
+	///     {
+	///         switch (e)
+	///         {
+	///         case XMLStreamParser::EV_START_ELEMENT:
+	///             cerr << p.line () << ':' << p.column () << ": start " << p.name () << endl;
+	///             break;
+	///         case XMLStreamParser::EV_END_ELEMENT:
+	///             cerr << p.line () << ':' << p.column () << ": end " << p.name () << endl;
+	///             break;
+	///         case XMLStreamParser::EV_START_ATTRIBUTE:
+	///             ...
+	///         case XMLStreamParser::EV_END_ATTRIBUTE:
+	///             ...
+	///         case XMLStreamParser::EV_CHARACTERS:
+	///             ...
+	///         }
+	///     }
+{
+public:
+	enum EventType
+		/// Parsing events.
+	{
+		EV_START_ELEMENT,
+		EV_END_ELEMENT,
+		EV_START_ATTRIBUTE,
+		EV_END_ATTRIBUTE,
+		EV_CHARACTERS,
+		EV_START_NAMESPACE_DECL,
+		EV_END_NAMESPACE_DECL,
+		EV_EOF
+	};
+
+	typedef unsigned short FeatureType;
+		/// If both receive_attributes_event and RECEIVE_ATTRIBUTE_MAP are
+		/// specified, then RECEIVE_ATTRIBUTES_EVENT is assumed.
+
+	static const FeatureType RECEIVE_ELEMENTS = 0x0001;
+	static const FeatureType RECEIVE_CHARACTERS = 0x0002;
+	static const FeatureType RECEIVE_ATTRIBUTE_MAP = 0x0004;
+	static const FeatureType RECEIVE_ATTRIBUTES_EVENT = 0x0008;
+	static const FeatureType RECEIVE_NAMESPACE_DECLS = 0x0010;
+	static const FeatureType RECEIVE_DEFAULT = RECEIVE_ELEMENTS | RECEIVE_CHARACTERS | RECEIVE_ATTRIBUTE_MAP;
+
+	struct XML_API AttributeValueType
+	{
+		std::string value;
+		mutable bool handled;
+	};
+
+	typedef std::map<QName, AttributeValueType> AttributeMapType;
+
+	struct XML_API Iterator
+		// C++11 range-based for support. Generally, the iterator interface
+		// doesn't make much sense for the XMLStreamParser so for now we have an
+		// implementation that is just enough to the range-based for.
+	{
+		typedef EventType value_type;
+
+		Iterator(XMLStreamParser* p = 0, EventType e = EV_EOF):
+			_parser(p),
+			_e(e)
+		{
+		}
+
+		value_type operator * () const
+		{
+			return _e;
+		}
+
+		Iterator& operator ++ ()
+		{
+			_e = _parser->next();
+			return *this;
+		}
+
+		bool operator == (Iterator y) const
+			/// Comparison only makes sense when comparing to end (eof).
+		{
+			return _e == EV_EOF && y._e == EV_EOF;
+		}
+
+		bool operator != (Iterator y) const
+			/// Comparison only makes sense when comparing to end (eof).
+		{
+			return !(*this == y);
+		}
+
+	private:
+		XMLStreamParser* _parser;
+		EventType _e;
+	};
+
+	Iterator begin()
+	{
+		return Iterator(this, next());
+	}
+
+	Iterator end()
+	{
+		return Iterator(this, EV_EOF);
+	}
+
+	XMLStreamParser(std::istream&, const std::string& inputName, FeatureType = RECEIVE_DEFAULT);
+		/// The parser constructor takes three arguments: the stream to parse,
+		/// input name that is used in diagnostics to identify the document being
+		/// parsed, and the list of events we want the parser to report.
+		///
+		/// Parse std::istream. Input name is used in diagnostics to identify
+		/// the document being parsed.
+		///
+		/// If stream exceptions are enabled then std::ios_base::failure
+		/// exception is used to report io errors (badbit and failbit).
+		/// Otherwise, those are reported as the parsing exception.
+
+	XMLStreamParser(const void* data, std::size_t size, const std::string& inputName, FeatureType = RECEIVE_DEFAULT);
+		/// Parse memory buffer that contains the whole document. Input name
+		/// is used in diagnostics to identify the document being parsed.
+
+	~XMLStreamParser();
+		/// Destroys the XMLStreamParser.
+
+	EventType next();
+		/// Call the next() function when we are ready to handle the next piece of XML.
+
+	void nextExpect(EventType);
+		/// Get the next event and make sure that it's what's expected. If it
+		/// is not, then throw an appropriate parsing exception.
+
+	void nextExpect(EventType, const std::string& name);
+	void nextExpect(EventType, const QName& qname);
+	void nextExpect(EventType, const std::string& ns, const std::string& name);
+
+	EventType peek();
+	EventType event();
+		/// Return the event that was last returned by the call to next() or peek().
+
+	const std::string& inputName() const;
+	const QName& getQName() const;
+	const std::string& namespaceURI() const;
+	const std::string& localName() const;
+	const std::string& prefix() const;
+	std::string& value();
+	const std::string& value() const;
+	template <typename T> T value() const;
+	Poco::UInt64 line() const;
+	Poco::UInt64 column() const;
+	const std::string& attribute(const std::string& name) const;
+	template <typename T>
+	T attribute(const std::string& name) const;
+	std::string attribute(const std::string& name, const std::string& deflt) const;
+	template <typename T>
+	T attribute(const std::string& name, const T& deflt) const;
+	const std::string& attribute(const QName& qname) const;
+	template <typename T>
+	T attribute(const QName& qname) const;
+	std::string attribute(const QName& qname, const std::string& deflt) const;
+	template <typename T>
+	T attribute(const QName& qname, const T& deflt) const;
+	bool attributePresent(const std::string& name) const;
+	bool attributePresent(const QName& qname) const;
+	const AttributeMapType& attributeMap() const;
+
+	void content(Content);
+	Content content() const;
+
+	void nextExpect(EventType, const std::string& name, Content);
+	void nextExpect(EventType, const QName& qname, Content);
+	void nextExpect(EventType, const std::string& ns, const std::string& name, Content);
+
+	// Helpers for parsing elements with simple content. The first two
+	// functions assume that EV_START_ELEMENT has already been parsed. The
+	// rest parse the complete element, from start to end.
+	//
+	// Note also that as with attribute(), there is no (namespace,name)
+	// overload since it would conflicts with (namespace,deflt).
+	std::string element();
+
+	template <typename T>
+	T element();
+	std::string element(const std::string& name);
+	std::string element(const QName& qname);
+	template <typename T>
+	T element(const std::string& name);
+	template <typename T>
+	T element(const QName& qname);
+	std::string element(const std::string& name, const std::string& deflt);
+	std::string element(const QName& qname, const std::string& deflt);
+	template <typename T>
+	T element(const std::string& name, const T& deflt);
+	template <typename T>
+	T element(const QName& qname, const T& deflt);
+
+private:
+	XMLStreamParser(const XMLStreamParser&);
+	XMLStreamParser& operator = (const XMLStreamParser&);
+
+	static void XMLCALL handleStartElement(void*, const XML_Char*, const XML_Char**);
+	static void XMLCALL handleEndElement(void*, const XML_Char*);
+	static void XMLCALL handleCharacters(void*, const XML_Char*, int);
+	static void XMLCALL handleStartNamespaceDecl(void*, const XML_Char*, const XML_Char*);
+	static void XMLCALL handleEndNamespaceDecl(void*, const XML_Char*);
+
+	void init();
+	EventType nextImpl(bool peek);
+	EventType nextBody();
+	void handleError();
+
+	// If _size is 0, then data is std::istream. Otherwise, it is a buffer.
+	union
+	{
+		std::istream* is;
+		const void* buf;
+	}
+	_data;
+
+	std::size_t _size;
+	const std::string _inputName;
+	FeatureType _feature;
+	XML_Parser _parser;
+	std::size_t _depth;
+	bool _accumulateContent; // Whether we are accumulating character content.
+	enum { state_next, state_peek } _parserState;
+	EventType _currentEvent;
+	EventType _queue;
+	QName _qname;
+	std::string _value;
+	const QName* _qualifiedName;
+	std::string* _pvalue;
+	Poco::UInt64 _line;
+	Poco::UInt64 _column;
+
+	struct AttributeType
+	{
+		QName qname;
+		std::string value;
+	};
+
+	typedef std::vector<AttributeType> attributes;
+	attributes _attributes;
+	attributes::size_type _currentAttributeIndex; // Index of the current attribute.
+
+	typedef std::vector<QName> NamespaceDecls;
+	NamespaceDecls _startNamespace;
+	NamespaceDecls::size_type _startNamespaceIndex;// Index of the current decl.
+	NamespaceDecls _endNamespace;
+	NamespaceDecls::size_type _endNamespaceIndex;// Index of the current decl.
+
+	struct ElementEntry
+	{
+		ElementEntry(std::size_t d, Content c = Content::Mixed):
+			depth(d),
+			content(c),
+			attributesUnhandled(0)
+		{
+		}
+
+		std::size_t depth;
+		Content content;
+		AttributeMapType attributeMap;
+		mutable AttributeMapType::size_type attributesUnhandled;
+	};
+
+	typedef std::vector<ElementEntry> ElementState;
+	std::vector<ElementEntry> _elementState;
+
+	const AttributeMapType _emptyAttrMap;
+
+	const ElementEntry* getElement() const;
+	const ElementEntry* getElementImpl() const;
+	void popElement();
+};
+
+
+XML_API std::ostream& operator << (std::ostream&, XMLStreamParser::EventType);
+
+
+//
+// inlines
+//
+inline XMLStreamParser::EventType XMLStreamParser::event()
+	// Return the even that was last returned by the call to next() or peek().
+{
+	return _currentEvent;
+}
+
+
+inline const std::string& XMLStreamParser::inputName() const
+{
+	return _inputName;
+}
+
+
+inline const QName& XMLStreamParser::getQName() const
+{
+	return *_qualifiedName;
+}
+
+
+inline const std::string& XMLStreamParser::namespaceURI() const
+{
+	return _qualifiedName->namespaceURI();
+}
+
+
+inline const std::string& XMLStreamParser::localName() const
+{
+	return _qualifiedName->localName();
+}
+
+
+inline const std::string& XMLStreamParser::prefix() const
+{
+	return _qualifiedName->prefix();
+}
+
+
+inline std::string& XMLStreamParser::value()
+{
+	return *_pvalue;
+}
+
+
+inline const std::string& XMLStreamParser::value() const
+{
+	return *_pvalue;
+}
+
+
+inline Poco::UInt64 XMLStreamParser::line() const
+{
+	return _line;
+}
+
+
+inline Poco::UInt64 XMLStreamParser::column() const
+{
+	return _column;
+}
+
+
+inline XMLStreamParser::EventType XMLStreamParser::peek()
+{
+	if (_parserState == state_peek)
+		return _currentEvent;
+	else
+	{
+		EventType e(nextImpl(true));
+		_parserState = state_peek; // Set it after the call to nextImpl().
+		return e;
+	}
+}
+
+
+template <typename T>
+inline T XMLStreamParser::value() const
+{
+	return ValueTraits < T > ::parse(value(), *this);
+}
+
+
+inline const std::string& XMLStreamParser::attribute(const std::string& n) const
+{
+	return attribute(QName(n));
+}
+
+
+template <typename T>
+inline T XMLStreamParser::attribute(const std::string& n) const
+{
+	return attribute < T > (QName(n));
+}
+
+
+inline std::string XMLStreamParser::attribute(const std::string& n, const std::string& dv) const
+{
+	return attribute(QName(n), dv);
+}
+
+
+template <typename T>
+inline T XMLStreamParser::attribute(const std::string& n, const T& dv) const
+{
+	return attribute < T > (QName(n), dv);
+}
+
+
+template <typename T>
+inline T XMLStreamParser::attribute(const QName& qn) const
+{
+	return ValueTraits < T > ::parse(attribute(qn), *this);
+}
+
+
+inline bool XMLStreamParser::attributePresent(const std::string& n) const
+{
+	return attributePresent(QName(n));
+}
+
+
+inline const XMLStreamParser::AttributeMapType& XMLStreamParser::attributeMap() const
+{
+	if (const ElementEntry* e = getElement())
+	{
+		e->attributesUnhandled = 0; // Assume all handled.
+		return e->attributeMap;
+	}
+
+	return _emptyAttrMap;
+}
+
+
+inline void XMLStreamParser::nextExpect(EventType e, const QName& qn)
+{
+	nextExpect(e, qn.namespaceURI(), qn.localName());
+}
+
+
+inline void XMLStreamParser::nextExpect(EventType e, const std::string& n)
+{
+	nextExpect(e, std::string(), n);
+}
+
+
+inline void XMLStreamParser::nextExpect(EventType e, const QName& qn, Content c)
+{
+	nextExpect(e, qn);
+	poco_assert(e == EV_START_ELEMENT);
+	content(c);
+}
+
+
+inline void XMLStreamParser::nextExpect(EventType e, const std::string& n, Content c)
+{
+	nextExpect(e, std::string(), n);
+	poco_assert(e == EV_START_ELEMENT);
+	content(c);
+}
+
+
+inline void XMLStreamParser::nextExpect(EventType e, const std::string& ns, const std::string& n, Content c)
+{
+	nextExpect(e, ns, n);
+	poco_assert(e == EV_START_ELEMENT);
+	content(c);
+}
+
+
+template <typename T>
+inline T XMLStreamParser::element()
+{
+	return ValueTraits < T > ::parse(element(), *this);
+}
+
+
+inline std::string XMLStreamParser::element(const std::string& n)
+{
+	nextExpect(EV_START_ELEMENT, n);
+	return element();
+}
+
+
+inline std::string XMLStreamParser::element(const QName& qn)
+{
+	nextExpect(EV_START_ELEMENT, qn);
+	return element();
+}
+
+
+template <typename T>
+inline T XMLStreamParser::element(const std::string& n)
+{
+	return ValueTraits < T > ::parse(element(n), *this);
+}
+
+
+template <typename T>
+inline T XMLStreamParser::element(const QName& qn)
+{
+	return ValueTraits < T > ::parse(element(qn), *this);
+}
+
+
+inline std::string XMLStreamParser::element(const std::string& n, const std::string& dv)
+{
+	return element(QName(n), dv);
+}
+
+
+template <typename T>
+inline T XMLStreamParser::element(const std::string& n, const T& dv)
+{
+	return element < T > (QName(n), dv);
+}
+
+
+inline void XMLStreamParser::content(Content c)
+{
+	poco_assert(_parserState == state_next);
+
+	if (!_elementState.empty() && _elementState.back().depth == _depth)
+		_elementState.back().content = c;
+	else
+		_elementState.push_back(ElementEntry(_depth, c));
+}
+
+
+inline Content XMLStreamParser::content() const
+{
+	poco_assert(_parserState == state_next);
+
+	return !_elementState.empty() && _elementState.back().depth == _depth ? _elementState.back().content : Content(Content::Mixed);
+}
+
+
+inline const XMLStreamParser::ElementEntry* XMLStreamParser::getElement() const
+{
+	return _elementState.empty() ? 0 : getElementImpl();
+}
+
+
+template <typename T>
+T XMLStreamParser::attribute(const QName& qn, const T& dv) const
+{
+	if (const ElementEntry* e = getElement())
+	{
+		AttributeMapType::const_iterator i(e->attributeMap.find(qn));
+
+		if (i != e->attributeMap.end())
+		{
+			if (!i->second.handled)
+			{
+				i->second.handled = true;
+				e->attributesUnhandled--;
+			}
+			return ValueTraits < T > ::parse(i->second.value, *this);
+		}
+	}
+
+	return dv;
+}
+
+
+template <typename T>
+T XMLStreamParser::element(const QName& qn, const T& dv)
+{
+	if (peek() == EV_START_ELEMENT && getQName() == qn)
+	{
+		next();
+		return element<T>();
+	}
+
+	return dv;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_XMLStreamParser_INCLUDED
diff --git a/Poco/XML/XMLStreamParserException.h b/Poco/XML/XMLStreamParserException.h
new file mode 100644
index 0000000..bc31b05
--- /dev/null
+++ b/Poco/XML/XMLStreamParserException.h
@@ -0,0 +1,58 @@
+//
+// XMLStreamParserException.h
+//
+// Library: XML
+// Package: XML
+// Module:  XMLStreamParserException
+//
+// Definition of the XMLStreamParserException class.
+//
+// Copyright (c) 2015, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XMLStreamParserException_INCLUDED
+#define XML_XMLStreamParserException_INCLUDED
+
+
+#include "Poco/XML/XMLException.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+class XMLStreamParser;
+
+
+class XML_API XMLStreamParserException: public Poco::XML::XMLException
+{
+public:
+	XMLStreamParserException(const std::string& name, Poco::UInt64 line, Poco::UInt64 column, const std::string& description);
+	XMLStreamParserException(const XMLStreamParser&, const std::string& description);
+	virtual ~XMLStreamParserException() throw ();
+
+	const char* name() const throw();
+	Poco::UInt64 line() const;
+	Poco::UInt64 column() const;
+	const std::string& description() const;
+	virtual const char* what() const throw ();
+
+private:
+	void init();
+
+	std::string _name;
+	Poco::UInt64 _line;
+	Poco::UInt64 _column;
+	std::string _description;
+	std::string _what;
+};
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_XMLStreamParserException_INCLUDED
diff --git a/Poco/XML/XMLString.h b/Poco/XML/XMLString.h
new file mode 100644
index 0000000..4f6d24b
--- /dev/null
+++ b/Poco/XML/XMLString.h
@@ -0,0 +1,87 @@
+//
+// XMLString.h
+//
+// Library: XML
+// Package: XML
+// Module:  XMLString
+//
+// Definition of the XMLString class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XMLString_INCLUDED
+#define XML_XMLString_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+
+
+namespace Poco {
+namespace XML {
+
+
+//
+// The XML parser uses the string classes provided by the C++
+// standard library (based on the basic_string<> template).
+// In Unicode mode, a std::wstring is used, otherwise
+// a std::string is used.
+// To turn on Unicode mode, #define XML_UNICODE and
+// XML_UNICODE_WCHAR_T when compiling the library.
+//
+// XML_UNICODE  XML_UNICODE_WCHAR_T  XMLChar    XMLString
+// --------------------------------------------------------------
+//     N                 N           char       std::string
+//     N                 Y           wchar_t    std::wstring
+//     Y                 Y           wchar_t    std::wstring
+//     Y                 N           <not supported>
+//
+#if defined(XML_UNICODE_WCHAR_T)
+
+	// Unicode - use wchar_t
+	typedef wchar_t      XMLChar;
+	typedef std::wstring XMLString;
+
+	std::string fromXMLString(const XMLString& str);
+		/// Converts an XMLString into an UTF-8 encoded
+		/// string.
+		
+	XMLString toXMLString(const std::string& str);
+		/// Converts an UTF-8 encoded string into an
+		/// XMLString
+		
+	#define XML_LIT(lit) L##lit
+
+#elif defined(XML_UNICODE)
+
+	// not supported - leave XMLString undefined
+
+#else
+
+	// Characters are UTF-8 encoded
+	typedef char        XMLChar;
+	typedef std::string XMLString;
+
+	inline const std::string& fromXMLString(const XMLString& str)
+	{
+		return str;
+	}
+
+	inline const XMLString& toXMLString(const std::string& str)
+	{
+		return str;
+	}
+	
+	#define XML_LIT(lit) lit
+
+#endif
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_XMLString_INCLUDED
diff --git a/Poco/XML/XMLWriter.h b/Poco/XML/XMLWriter.h
new file mode 100644
index 0000000..b87fd30
--- /dev/null
+++ b/Poco/XML/XMLWriter.h
@@ -0,0 +1,375 @@
+//
+// XMLWriter.h
+//
+// Library: XML
+// Package: XML
+// Module:  XMLWriter
+//
+// Definition of the XMLWriter class.
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef XML_XMLWriter_INCLUDED
+#define XML_XMLWriter_INCLUDED
+
+
+#include "Poco/XML/XML.h"
+#include "Poco/SAX/ContentHandler.h"
+#include "Poco/SAX/LexicalHandler.h"
+#include "Poco/SAX/DTDHandler.h"
+#include "Poco/SAX/NamespaceSupport.h"
+#include "Poco/XML/XMLString.h"
+#include "Poco/XML/XMLStream.h"
+#include "Poco/XML/Name.h"
+#include "Poco/TextEncoding.h"
+#include "Poco/StreamConverter.h"
+#include <vector>
+#include <map>
+
+
+namespace Poco {
+namespace XML {
+
+
+class Locator;
+
+
+class XML_API XMLWriter: public ContentHandler, public LexicalHandler, public DTDHandler
+	/// This class serializes SAX2 ContentHandler, LexicalHandler and
+	/// DTDHandler events back into a stream.
+	/// 
+	/// Various consistency checks are performed on the written data
+	/// (i.e. there must be exactly one root element and every startElement() 
+	/// must have a matching endElement()).
+	///
+	/// The XMLWriter supports optional pretty-printing of the serialized XML.
+	/// Note, however, that pretty-printing XML data alters the
+	/// information set of the document being written, since in
+	/// XML all whitespace is potentially relevant to an application.
+	///
+	/// The writer contains extensive support for XML Namespaces, so that a client  
+	/// application does not have to keep track of prefixes and supply xmlns attributes.
+	///
+	/// If the client does not provide namespace prefixes (either by specifying them
+	/// as part of the qualified name given to startElement(), or by calling
+	/// startPrefixMapping()), the XMLWriter automatically generates namespace
+	/// prefixes in the form ns1, ns2, etc.
+{
+public:
+	enum Options
+	{
+		CANONICAL               = 0x00,
+			/// Do not write an XML declaration (default).
+
+		CANONICAL_XML           = 0x01, 
+			/// Enables basic support for Canonical XML: 
+			///   - do not write an XML declaration
+			///   - do not use special empty element syntax
+			///   - set the New Line character to NEWLINE_LF
+			///   - write namespace declarations and attributes 
+			///     in canonical order
+			///   - use default namespace as much as possible
+
+		WRITE_XML_DECLARATION   = 0x02, 
+			/// Write an XML declaration.
+
+		PRETTY_PRINT            = 0x04, 
+			/// Pretty-print XML markup.
+
+		PRETTY_PRINT_ATTRIBUTES = 0x08
+			/// Write each attribute on a separate line. 
+			/// PRETTY_PRINT must be specified as well.
+	};
+
+	XMLWriter(XMLByteOutputStream& str, int options);
+		/// Creates the XMLWriter and sets the specified options.
+		///
+		/// The resulting stream will be UTF-8 encoded.
+
+	XMLWriter(XMLByteOutputStream& str, int options, const std::string& encodingName, Poco::TextEncoding& textEncoding);
+		/// Creates the XMLWriter and sets the specified options.
+		///
+		/// The encoding is reflected in the XML declaration.
+		/// The caller is responsible for that the given encodingName matches with
+		/// the given textEncoding.
+
+	XMLWriter(XMLByteOutputStream& str, int options, const std::string& encodingName, Poco::TextEncoding* pTextEncoding);
+		/// Creates the XMLWriter and sets the specified options.
+		///
+		/// The encoding is reflected in the XML declaration.
+		/// The caller is responsible for that the given encodingName matches with
+		/// the given textEncoding.
+		/// If pTextEncoding is null, the given encodingName is ignored and the
+		/// default UTF-8 encoding is used.
+
+	~XMLWriter();
+		/// Destroys the XMLWriter.
+
+	void setNewLine(const std::string& newLineCharacters);
+		/// Sets the line ending for the resulting XML file.
+		///
+		/// Possible values are:
+		///   * NEWLINE_DEFAULT (whatever is appropriate for the current platform)
+		///   * NEWLINE_CRLF    (Windows),
+		///   * NEWLINE_LF      (Unix),
+		///   * NEWLINE_CR      (Macintosh)
+
+	const std::string& getNewLine() const;
+		/// Returns the line ending currently in use.
+
+	void setIndent(const std::string& indent);
+		/// Sets the string used for one indentation step.
+		///
+		/// The default is a single TAB character.
+		/// The given string should only contain TAB or SPACE
+		/// characters (e.g., a single TAB character, or
+		/// two to four SPACE characters).
+		
+	const std::string& getIndent() const;
+		/// Returns the string used for one indentation step.
+
+	// ContentHandler
+	void setDocumentLocator(const Locator* loc);
+		/// Currently unused.
+
+	void startDocument();
+		/// Writes a generic XML declaration to the stream.
+		/// If a document type has been set (see SetDocumentType),
+		/// a DOCTYPE declaration is also written.
+
+	void endDocument();
+		/// Checks that all elements are closed and prints a final newline.
+
+	void startFragment();
+		/// Use this instead of StartDocument() if you want to write
+		/// a fragment rather than a document (no XML declaration and
+		/// more than one "root" element allowed).
+
+	void endFragment();
+		/// Checks that all elements are closed and prints a final newline.
+
+	void startElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+		/// Writes an XML start element tag.
+		///
+		/// Namespaces are handled as follows.
+		///   1. If a qname, but no namespaceURI and localName are given, the qname is taken as element name.
+		///   2. If a namespaceURI and a localName, but no qname is given, and the given namespaceURI has been
+		///      declared earlier, the namespace prefix for the given namespaceURI together with the localName
+		///      is taken as element name. If the namespace has not been declared, a prefix in the form
+		///      "ns1", "ns2", etc. is generated and the namespace is declared with the generated prefix.
+		///   3. If all three are given, and the namespace given in namespaceURI has not been declared, it is declared now.
+		///      Otherwise, see 2.
+
+	void startElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname);
+		/// Writes an XML start element tag with no attributes.
+		/// See the other startElement() method for more information.
+		
+	void endElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname);
+		/// Writes an XML end element tag.
+		///
+		/// Throws an exception if the name of doesn't match the
+		/// one of the most recent startElement().
+
+	void emptyElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname);
+		/// Writes an empty XML element tag (<elem/>).
+
+	void emptyElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+		/// Writes an empty XML element tag with the given attributes (<elem attr1="value1"... />).
+
+	void characters(const XMLChar ch[], int start, int length);
+		/// Writes XML character data. Quotes, ampersand's, less-than and
+		/// greater-than signs are escaped, unless a CDATA section
+		/// has been opened by calling startCDATA().
+		///
+		/// The characters must be encoded in UTF-8 (if XMLChar is char) or 
+		/// UTF-16 (if XMLChar is wchar_t).
+
+	void characters(const XMLString& str);
+		/// Writes XML character data. Quotes, ampersand's, less-than and
+		/// greater-than signs are escaped, unless a CDATA section
+		/// has been opened by calling startCDATA().
+		///
+		/// The characters must be encoded in UTF-8 (if XMLChar is char) or 
+		/// UTF-16 (if XMLChar is wchar_t).
+
+	void rawCharacters(const XMLString& str);
+		/// Writes the characters in the given string as they are.
+		/// The caller is responsible for escaping characters as
+		/// necessary to produce valid XML.
+		///
+		/// The characters must be encoded in UTF-8 (if XMLChar is char) or 
+		/// UTF-16 (if XMLChar is wchar_t).
+
+	void ignorableWhitespace(const XMLChar ch[], int start, int length);
+		/// Writes whitespace characters by simply passing them to
+		/// characters().
+
+	void processingInstruction(const XMLString& target, const XMLString& data);
+		/// Writes a processing instruction.
+
+	void startPrefixMapping(const XMLString& prefix, const XMLString& namespaceURI);
+		/// Begin the scope of a prefix-URI Namespace mapping.
+		/// A namespace declaration is written with the next element.
+
+	void endPrefixMapping(const XMLString& prefix);
+		/// End the scope of a prefix-URI mapping.
+
+	void skippedEntity(const XMLString& name);
+		/// Does nothing.
+
+	void dataElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const XMLString& data, 
+	                         const XMLString& attr1 = XMLString(), const XMLString& value1 = XMLString(),
+							 const XMLString& attr2 = XMLString(), const XMLString& value2 = XMLString(),
+							 const XMLString& attr3 = XMLString(), const XMLString& value3 = XMLString());
+		/// Writes a data element in the form <name attr1="value1"...>data</name>.
+
+	// LexicalHandler
+	void startCDATA();
+		/// Writes the <![CDATA[ string that begins a CDATA section.
+		/// Use characters() to write the actual character data.
+
+	void endCDATA();
+		/// Writes the ]]> string that ends a CDATA section.
+
+	void comment(const XMLChar ch[], int start, int length);
+		/// Writes a comment.
+
+	void startDTD(const XMLString& name, const XMLString& publicId, const XMLString& systemId);
+		/// Writes a DTD declaration.
+
+	void endDTD();
+		/// Writes the closing characters of a DTD declaration.
+
+	void startEntity(const XMLString& name);
+		/// Does nothing.
+
+	void endEntity(const XMLString& name);
+		/// Does nothing.
+	
+	// DTDHandler
+	void notationDecl(const XMLString& name, const XMLString* publicId, const XMLString* systemId);
+	void unparsedEntityDecl(const XMLString& name, const XMLString* publicId, const XMLString& systemId, const XMLString& notationName);
+
+	static const std::string NEWLINE_DEFAULT;
+	static const std::string NEWLINE_CR;
+	static const std::string NEWLINE_CRLF;
+	static const std::string NEWLINE_LF;
+
+	// Namespace support.
+	XMLString uniquePrefix();
+		/// Creates and returns a unique namespace prefix that
+		/// can be used with startPrefixMapping().
+
+	bool isNamespaceMapped(const XMLString& namespc) const;
+		/// Returns true if the given namespace has been mapped
+		/// to a prefix in the current element or its ancestors.
+		
+	// Misc.
+	int depth() const;
+		/// Return the number of nested XML elements.
+		///
+		/// Will be -1 if no document or fragment has been started, 
+		/// 0 if the document or fragment has been started,
+		/// 1 if the document element has been written and
+		/// > 1 for every element nested within the document element.
+
+protected:
+	typedef std::map<XMLString, XMLString> AttributeMap;
+	typedef std::map<XMLString, std::pair<XMLString, XMLString> > CanonicalAttributeMap;
+
+	void writeStartElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+	void writeCanonicalStartElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+	void writeEndElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname);
+	void writeMarkup(const std::string& str) const;
+	void writeXML(const XMLString& str) const;
+	void writeXML(XMLChar ch) const;
+	void writeNewLine() const;
+	void writeIndent() const;
+	void writeIndent(int indent) const;
+	void writeName(const XMLString& prefix, const XMLString& localName);
+	void writeXMLDeclaration();
+	void closeStartTag();
+	void declareNamespaces(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes);
+	void declareAttributeNamespaces(const Attributes& attributes);
+	void addNamespaceAttributes(AttributeMap& attributeMap);
+	void addNamespaceAttributes(CanonicalAttributeMap& attributeMap);
+	void addAttributes(AttributeMap& attributeMap, const Attributes& attributes, const XMLString& elementNamespaceURI);
+	void addAttributes(CanonicalAttributeMap& attributeMap, const Attributes& attributes, const XMLString& elementNamespaceURI);
+	void writeAttributes(const AttributeMap& attributeMap);
+	void writeAttributes(const CanonicalAttributeMap& attributeMap);
+	void prettyPrint() const;
+	static std::string nameToString(const XMLString& localName, const XMLString& qname);
+
+private:
+	struct Namespace
+	{
+		Namespace(const XMLString& thePrefix, const XMLString& theNamespaceURI):
+			prefix(thePrefix),
+			namespaceURI(theNamespaceURI)
+		{
+		}
+
+		XMLString prefix;
+		XMLString namespaceURI;
+	};
+	typedef std::vector<Name> ElementStack;
+	
+	Poco::OutputStreamConverter* _pTextConverter;
+	Poco::TextEncoding*          _pInEncoding;
+	Poco::TextEncoding*          _pOutEncoding;
+	int              _options;
+	std::string      _encoding;
+	std::string      _newLine;
+	int              _depth;
+	int              _elementCount;
+	bool             _inFragment;
+	bool             _inCDATA;
+	bool             _inDTD;
+	bool             _inInternalDTD;
+	bool             _contentWritten;
+	bool             _unclosedStartTag;
+	ElementStack     _elementStack;
+	NamespaceSupport _namespaces;
+	int              _prefix;
+	bool             _nsContextPushed;
+	std::string      _indent;
+
+	static const std::string MARKUP_QUOTENC;
+	static const std::string MARKUP_AMPENC;
+	static const std::string MARKUP_LTENC;
+	static const std::string MARKUP_GTENC;
+	static const std::string MARKUP_TABENC;
+	static const std::string MARKUP_CRENC;
+	static const std::string MARKUP_LFENC;
+	static const std::string MARKUP_LT;
+	static const std::string MARKUP_GT;
+	static const std::string MARKUP_SLASHGT;
+	static const std::string MARKUP_LTSLASH;
+	static const std::string MARKUP_COLON;
+	static const std::string MARKUP_EQQUOT;
+	static const std::string MARKUP_QUOT;
+	static const std::string MARKUP_SPACE;
+	static const std::string MARKUP_TAB;
+	static const std::string MARKUP_BEGIN_CDATA;
+	static const std::string MARKUP_END_CDATA;
+};
+
+
+//
+// inlines
+//
+inline int XMLWriter::depth() const
+{
+	return _depth;
+}
+
+
+} } // namespace Poco::XML
+
+
+#endif // XML_XMLWriter_INCLUDED
diff --git a/Poco/XML/expat.h b/Poco/XML/expat.h
new file mode 100644
index 0000000..c050f1d
--- /dev/null
+++ b/Poco/XML/expat.h
@@ -0,0 +1,1085 @@
+/*
+                            __  __            _
+                         ___\ \/ /_ __   __ _| |_
+                        / _ \\  /| '_ \ / _` | __|
+                       |  __//  \| |_) | (_| | |_
+                        \___/_/\_\ .__/ \__,_|\__|
+                                 |_| XML parser
+
+   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
+   Copyright (c) 2000-2017 Expat development team
+   Licensed under the MIT license:
+
+   Permission is  hereby granted,  free of charge,  to any  person obtaining
+   a  copy  of  this  software   and  associated  documentation  files  (the
+   "Software"),  to  deal in  the  Software  without restriction,  including
+   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
+   distribute, sublicense, and/or sell copies of the Software, and to permit
+   persons  to whom  the Software  is  furnished to  do so,  subject to  the
+   following conditions:
+
+   The above copyright  notice and this permission notice  shall be included
+   in all copies or substantial portions of the Software.
+
+   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 AND NONINFRINGEMENT. IN
+   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
+   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+   USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef Expat_INCLUDED
+#define Expat_INCLUDED 1
+
+#ifdef __VMS
+/*      0        1         2         3      0        1         2         3
+        1234567890123456789012345678901     1234567890123456789012345678901 */
+#define XML_SetProcessingInstructionHandler XML_SetProcessingInstrHandler
+#define XML_SetUnparsedEntityDeclHandler    XML_SetUnparsedEntDeclHandler
+#define XML_SetStartNamespaceDeclHandler    XML_SetStartNamespcDeclHandler
+#define XML_SetExternalEntityRefHandlerArg  XML_SetExternalEntRefHandlerArg
+#endif
+
+#include <stdlib.h>
+#include "expat_external.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct XML_ParserStruct;
+typedef struct XML_ParserStruct *XML_Parser;
+
+typedef unsigned char XML_Bool;
+#define XML_TRUE   ((XML_Bool) 1)
+#define XML_FALSE  ((XML_Bool) 0)
+
+/* The XML_Status enum gives the possible return values for several
+   API functions.  The preprocessor #defines are included so this
+   stanza can be added to code that still needs to support older
+   versions of Expat 1.95.x:
+
+   #ifndef XML_STATUS_OK
+   #define XML_STATUS_OK    1
+   #define XML_STATUS_ERROR 0
+   #endif
+
+   Otherwise, the #define hackery is quite ugly and would have been
+   dropped.
+*/
+enum XML_Status {
+  XML_STATUS_ERROR = 0,
+#define XML_STATUS_ERROR XML_STATUS_ERROR
+  XML_STATUS_OK = 1,
+#define XML_STATUS_OK XML_STATUS_OK
+  XML_STATUS_SUSPENDED = 2
+#define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED
+};
+
+enum XML_Error {
+  XML_ERROR_NONE,
+  XML_ERROR_NO_MEMORY,
+  XML_ERROR_SYNTAX,
+  XML_ERROR_NO_ELEMENTS,
+  XML_ERROR_INVALID_TOKEN,
+  XML_ERROR_UNCLOSED_TOKEN,
+  XML_ERROR_PARTIAL_CHAR,
+  XML_ERROR_TAG_MISMATCH,
+  XML_ERROR_DUPLICATE_ATTRIBUTE,
+  XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+  XML_ERROR_PARAM_ENTITY_REF,
+  XML_ERROR_UNDEFINED_ENTITY,
+  XML_ERROR_RECURSIVE_ENTITY_REF,
+  XML_ERROR_ASYNC_ENTITY,
+  XML_ERROR_BAD_CHAR_REF,
+  XML_ERROR_BINARY_ENTITY_REF,
+  XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+  XML_ERROR_MISPLACED_XML_PI,
+  XML_ERROR_UNKNOWN_ENCODING,
+  XML_ERROR_INCORRECT_ENCODING,
+  XML_ERROR_UNCLOSED_CDATA_SECTION,
+  XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+  XML_ERROR_NOT_STANDALONE,
+  XML_ERROR_UNEXPECTED_STATE,
+  XML_ERROR_ENTITY_DECLARED_IN_PE,
+  XML_ERROR_FEATURE_REQUIRES_XML_DTD,
+  XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING,
+  /* Added in 1.95.7. */
+  XML_ERROR_UNBOUND_PREFIX,
+  /* Added in 1.95.8. */
+  XML_ERROR_UNDECLARING_PREFIX,
+  XML_ERROR_INCOMPLETE_PE,
+  XML_ERROR_XML_DECL,
+  XML_ERROR_TEXT_DECL,
+  XML_ERROR_PUBLICID,
+  XML_ERROR_SUSPENDED,
+  XML_ERROR_NOT_SUSPENDED,
+  XML_ERROR_ABORTED,
+  XML_ERROR_FINISHED,
+  XML_ERROR_SUSPEND_PE,
+  /* Added in 2.0. */
+  XML_ERROR_RESERVED_PREFIX_XML,
+  XML_ERROR_RESERVED_PREFIX_XMLNS,
+  XML_ERROR_RESERVED_NAMESPACE_URI,
+  /* Added in 2.2.1. */
+  XML_ERROR_INVALID_ARGUMENT
+};
+
+enum XML_Content_Type {
+  XML_CTYPE_EMPTY = 1,
+  XML_CTYPE_ANY,
+  XML_CTYPE_MIXED,
+  XML_CTYPE_NAME,
+  XML_CTYPE_CHOICE,
+  XML_CTYPE_SEQ
+};
+
+enum XML_Content_Quant {
+  XML_CQUANT_NONE,
+  XML_CQUANT_OPT,
+  XML_CQUANT_REP,
+  XML_CQUANT_PLUS
+};
+
+/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+   XML_CQUANT_NONE, and the other fields will be zero or NULL.
+   If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+   numchildren will contain number of elements that may be mixed in
+   and children point to an array of XML_Content cells that will be
+   all of XML_CTYPE_NAME type with no quantification.
+
+   If type == XML_CTYPE_NAME, then the name points to the name, and
+   the numchildren field will be zero and children will be NULL. The
+   quant fields indicates any quantifiers placed on the name.
+
+   CHOICE and SEQ will have name NULL, the number of children in
+   numchildren and children will point, recursively, to an array
+   of XML_Content cells.
+
+   The EMPTY, ANY, and MIXED types will only occur at top level.
+*/
+
+typedef struct XML_cp XML_Content;
+
+struct XML_cp {
+  enum XML_Content_Type         type;
+  enum XML_Content_Quant        quant;
+  XML_Char *                    name;
+  unsigned int                  numchildren;
+  XML_Content *                 children;
+};
+
+
+/* This is called for an element declaration. See above for
+   description of the model argument. It's the caller's responsibility
+   to free model when finished with it.
+*/
+typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
+                                                const XML_Char *name,
+                                                XML_Content *model);
+
+XMLPARSEAPI(void)
+XML_SetElementDeclHandler(XML_Parser parser,
+                          XML_ElementDeclHandler eldecl);
+
+/* The Attlist declaration handler is called for *each* attribute. So
+   a single Attlist declaration with multiple attributes declared will
+   generate multiple calls to this handler. The "default" parameter
+   may be NULL in the case of the "#IMPLIED" or "#REQUIRED"
+   keyword. The "isrequired" parameter will be true and the default
+   value will be NULL in the case of "#REQUIRED". If "isrequired" is
+   true and default is non-NULL, then this is a "#FIXED" default.
+*/
+typedef void (XMLCALL *XML_AttlistDeclHandler) (
+                                    void            *userData,
+                                    const XML_Char  *elname,
+                                    const XML_Char  *attname,
+                                    const XML_Char  *att_type,
+                                    const XML_Char  *dflt,
+                                    int              isrequired);
+
+XMLPARSEAPI(void)
+XML_SetAttlistDeclHandler(XML_Parser parser,
+                          XML_AttlistDeclHandler attdecl);
+
+/* The XML declaration handler is called for *both* XML declarations
+   and text declarations. The way to distinguish is that the version
+   parameter will be NULL for text declarations. The encoding
+   parameter may be NULL for XML declarations. The standalone
+   parameter will be -1, 0, or 1 indicating respectively that there
+   was no standalone parameter in the declaration, that it was given
+   as no, or that it was given as yes.
+*/
+typedef void (XMLCALL *XML_XmlDeclHandler) (void           *userData,
+                                            const XML_Char *version,
+                                            const XML_Char *encoding,
+                                            int             standalone);
+
+XMLPARSEAPI(void)
+XML_SetXmlDeclHandler(XML_Parser parser,
+                      XML_XmlDeclHandler xmldecl);
+
+
+typedef struct {
+  void *(*malloc_fcn)(size_t size);
+  void *(*realloc_fcn)(void *ptr, size_t size);
+  void (*free_fcn)(void *ptr);
+} XML_Memory_Handling_Suite;
+
+/* Constructs a new parser; encoding is the encoding specified by the
+   external protocol or NULL if there is none specified.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor.  Element type
+   names and attribute names that belong to a namespace will be
+   expanded; unprefixed attribute names are never expanded; unprefixed
+   element type names are expanded only if there is a default
+   namespace. The expanded name is the concatenation of the namespace
+   URI, the namespace separator character, and the local part of the
+   name.  If the namespace separator is '\0' then the namespace URI
+   and the local part will be concatenated without any separator.
+   It is a programming error to use the separator '\0' with namespace
+   triplets (see XML_SetReturnNSTriplet).
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* Constructs a new parser using the memory management suite referred to
+   by memsuite. If memsuite is NULL, then use the standard library memory
+   suite. If namespaceSeparator is non-NULL it creates a parser with
+   namespace processing as described above. The character pointed at
+   will serve as the namespace separator.
+
+   All further memory operations used for the created parser will come from
+   the given suite.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate_MM(const XML_Char *encoding,
+                    const XML_Memory_Handling_Suite *memsuite,
+                    const XML_Char *namespaceSeparator);
+
+/* Prepare a parser object to be re-used.  This is particularly
+   valuable when memory allocation overhead is disproportionately high,
+   such as when a large number of small documnents need to be parsed.
+   All handlers are cleared from the parser, except for the
+   unknownEncodingHandler. The parser's external state is re-initialized
+   except for the values of ns and ns_triplets.
+
+   Added in Expat 1.95.3.
+*/
+XMLPARSEAPI(XML_Bool)
+XML_ParserReset(XML_Parser parser, const XML_Char *encoding);
+
+/* atts is array of name/value pairs, terminated by 0;
+   names and values are 0 terminated.
+*/
+typedef void (XMLCALL *XML_StartElementHandler) (void *userData,
+                                                 const XML_Char *name,
+                                                 const XML_Char **atts);
+
+typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
+                                               const XML_Char *name);
+
+
+/* s is not 0 terminated. */
+typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData,
+                                                  const XML_Char *s,
+                                                  int len);
+
+/* target and data are 0 terminated */
+typedef void (XMLCALL *XML_ProcessingInstructionHandler) (
+                                                void *userData,
+                                                const XML_Char *target,
+                                                const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (XMLCALL *XML_CommentHandler) (void *userData,
+                                            const XML_Char *data);
+
+typedef void (XMLCALL *XML_StartCdataSectionHandler) (void *userData);
+typedef void (XMLCALL *XML_EndCdataSectionHandler) (void *userData);
+
+/* This is called for any characters in the XML document for which
+   there is no applicable handler.  This includes both characters that
+   are part of markup which is of a kind that is not reported
+   (comments, markup declarations), or characters that are part of a
+   construct which could be reported but for which no handler has been
+   supplied. The characters are passed exactly as they were in the XML
+   document except that they will be encoded in UTF-8 or UTF-16.
+   Line boundaries are not normalized. Note that a byte order mark
+   character is not passed to the default handler. There are no
+   guarantees about how characters are divided between calls to the
+   default handler: for example, a comment might be split between
+   multiple calls.
+*/
+typedef void (XMLCALL *XML_DefaultHandler) (void *userData,
+                                            const XML_Char *s,
+                                            int len);
+
+/* This is called for the start of the DOCTYPE declaration, before
+   any DTD or internal subset is parsed.
+*/
+typedef void (XMLCALL *XML_StartDoctypeDeclHandler) (
+                                            void *userData,
+                                            const XML_Char *doctypeName,
+                                            const XML_Char *sysid,
+                                            const XML_Char *pubid,
+                                            int has_internal_subset);
+
+/* This is called for the start of the DOCTYPE declaration when the
+   closing > is encountered, but after processing any external
+   subset.
+*/
+typedef void (XMLCALL *XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for entity declarations. The is_parameter_entity
+   argument will be non-zero if the entity is a parameter entity, zero
+   otherwise.
+
+   For internal entities (<!ENTITY foo "bar">), value will
+   be non-NULL and systemId, publicID, and notationName will be NULL.
+   The value string is NOT nul-terminated; the length is provided in
+   the value_length argument. Since it is legal to have zero-length
+   values, do not use this argument to test for internal entities.
+
+   For external entities, value will be NULL and systemId will be
+   non-NULL. The publicId argument will be NULL unless a public
+   identifier was provided. The notationName argument will have a
+   non-NULL value only for unparsed entity declarations.
+
+   Note that is_parameter_entity can't be changed to XML_Bool, since
+   that would break binary compatibility.
+*/
+typedef void (XMLCALL *XML_EntityDeclHandler) (
+                              void *userData,
+                              const XML_Char *entityName,
+                              int is_parameter_entity,
+                              const XML_Char *value,
+                              int value_length,
+                              const XML_Char *base,
+                              const XML_Char *systemId,
+                              const XML_Char *publicId,
+                              const XML_Char *notationName);
+
+XMLPARSEAPI(void)
+XML_SetEntityDeclHandler(XML_Parser parser,
+                         XML_EntityDeclHandler handler);
+
+/* OBSOLETE -- OBSOLETE -- OBSOLETE
+   This handler has been superseded by the EntityDeclHandler above.
+   It is provided here for backward compatibility.
+
+   This is called for a declaration of an unparsed (NDATA) entity.
+   The base argument is whatever was set by XML_SetBase. The
+   entityName, systemId and notationName arguments will never be
+   NULL. The other arguments may be.
+*/
+typedef void (XMLCALL *XML_UnparsedEntityDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *entityName,
+                                    const XML_Char *base,
+                                    const XML_Char *systemId,
+                                    const XML_Char *publicId,
+                                    const XML_Char *notationName);
+
+/* This is called for a declaration of notation.  The base argument is
+   whatever was set by XML_SetBase. The notationName will never be
+   NULL.  The other arguments can be.
+*/
+typedef void (XMLCALL *XML_NotationDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *notationName,
+                                    const XML_Char *base,
+                                    const XML_Char *systemId,
+                                    const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+   each namespace declaration. The call to the start and end element
+   handlers occur between the calls to the start and end namespace
+   declaration handlers. For an xmlns attribute, prefix will be
+   NULL.  For an xmlns="" attribute, uri will be NULL.
+*/
+typedef void (XMLCALL *XML_StartNamespaceDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *prefix,
+                                    const XML_Char *uri);
+
+typedef void (XMLCALL *XML_EndNamespaceDeclHandler) (
+                                    void *userData,
+                                    const XML_Char *prefix);
+
+/* This is called if the document is not standalone, that is, it has an
+   external subset or a reference to a parameter entity, but does not
+   have standalone="yes". If this handler returns XML_STATUS_ERROR,
+   then processing will not continue, and the parser will return a
+   XML_ERROR_NOT_STANDALONE error.
+   If parameter entity parsing is enabled, then in addition to the
+   conditions above this handler will only be called if the referenced
+   entity was actually read.
+*/
+typedef int (XMLCALL *XML_NotStandaloneHandler) (void *userData);
+
+/* This is called for a reference to an external parsed general
+   entity.  The referenced entity is not automatically parsed.  The
+   application can parse it immediately or later using
+   XML_ExternalEntityParserCreate.
+
+   The parser argument is the parser parsing the entity containing the
+   reference; it can be passed as the parser argument to
+   XML_ExternalEntityParserCreate.  The systemId argument is the
+   system identifier as specified in the entity declaration; it will
+   not be NULL.
+
+   The base argument is the system identifier that should be used as
+   the base for resolving systemId if systemId was relative; this is
+   set by XML_SetBase; it may be NULL.
+
+   The publicId argument is the public identifier as specified in the
+   entity declaration, or NULL if none was specified; the whitespace
+   in the public identifier will have been normalized as required by
+   the XML spec.
+
+   The context argument specifies the parsing context in the format
+   expected by the context argument to XML_ExternalEntityParserCreate;
+   context is valid only until the handler returns, so if the
+   referenced entity is to be parsed later, it must be copied.
+   context is NULL only when the entity is a parameter entity.
+
+   The handler should return XML_STATUS_ERROR if processing should not
+   continue because of a fatal error in the handling of the external
+   entity.  In this case the calling parser will return an
+   XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+
+   Note that unlike other handlers the first argument is the parser,
+   not userData.
+*/
+typedef int (XMLCALL *XML_ExternalEntityRefHandler) (
+                                    XML_Parser parser,
+                                    const XML_Char *context,
+                                    const XML_Char *base,
+                                    const XML_Char *systemId,
+                                    const XML_Char *publicId);
+
+/* This is called in two situations:
+   1) An entity reference is encountered for which no declaration
+      has been read *and* this is not an error.
+   2) An internal entity reference is read, but not expanded, because
+      XML_SetDefaultHandler has been called.
+   Note: skipped parameter entities in declarations and skipped general
+         entities in attribute values cannot be reported, because
+         the event would be out of sync with the reporting of the
+         declarations or attribute values
+*/
+typedef void (XMLCALL *XML_SkippedEntityHandler) (
+                                    void *userData,
+                                    const XML_Char *entityName,
+                                    int is_parameter_entity);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler to
+   provide information to the parser about encodings that are unknown
+   to the parser.
+
+   The map[b] member gives information about byte sequences whose
+   first byte is b.
+
+   If map[b] is c where c is >= 0, then b by itself encodes the
+   Unicode scalar value c.
+
+   If map[b] is -1, then the byte sequence is malformed.
+
+   If map[b] is -n, where n >= 2, then b is the first byte of an
+   n-byte sequence that encodes a single Unicode scalar value.
+
+   The data member will be passed as the first argument to the convert
+   function.
+
+   The convert function is used to convert multibyte sequences; s will
+   point to a n-byte sequence where map[(unsigned char)*s] == -n.  The
+   convert function must return the Unicode scalar value represented
+   by this byte sequence or -1 if the byte sequence is malformed.
+
+   The convert function may be NULL if the encoding is a single-byte
+   encoding, that is if map[b] >= -1 for all bytes b.
+
+   When the parser is finished with the encoding, then if release is
+   not NULL, it will call release passing it the data member; once
+   release has been called, the convert function will not be called
+   again.
+
+   Expat places certain restrictions on the encodings that are supported
+   using this mechanism.
+
+   1. Every ASCII character that can appear in a well-formed XML document,
+      other than the characters
+
+      $@\^`{}~
+
+      must be represented by a single byte, and that byte must be the
+      same byte that represents that character in ASCII.
+
+   2. No character may require more than 4 bytes to encode.
+
+   3. All characters encoded must have Unicode scalar values <=
+      0xFFFF, (i.e., characters that would be encoded by surrogates in
+      UTF-16 are  not allowed).  Note that this restriction doesn't
+      apply to the built-in support for UTF-8 and UTF-16.
+
+   4. No Unicode character may be encoded by more than one distinct
+      sequence of bytes.
+*/
+typedef struct {
+  int map[256];
+  void *data;
+  int (XMLCALL *convert)(void *data, const char *s);
+  void (XMLCALL *release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+
+   The encodingHandlerData argument is that which was passed as the
+   second argument to XML_SetUnknownEncodingHandler.
+
+   The name argument gives the name of the encoding as specified in
+   the encoding declaration.
+
+   If the callback can provide information about the encoding, it must
+   fill in the XML_Encoding structure, and return XML_STATUS_OK.
+   Otherwise it must return XML_STATUS_ERROR.
+
+   If info does not describe a suitable encoding, then the parser will
+   return an XML_UNKNOWN_ENCODING error.
+*/
+typedef int (XMLCALL *XML_UnknownEncodingHandler) (
+                                    void *encodingHandlerData,
+                                    const XML_Char *name,
+                                    XML_Encoding *info);
+
+XMLPARSEAPI(void)
+XML_SetElementHandler(XML_Parser parser,
+                      XML_StartElementHandler start,
+                      XML_EndElementHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartElementHandler(XML_Parser parser,
+                           XML_StartElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetEndElementHandler(XML_Parser parser,
+                         XML_EndElementHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCharacterDataHandler(XML_Parser parser,
+                            XML_CharacterDataHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+                                    XML_ProcessingInstructionHandler handler);
+XMLPARSEAPI(void)
+XML_SetCommentHandler(XML_Parser parser,
+                      XML_CommentHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCdataSectionHandler(XML_Parser parser,
+                           XML_StartCdataSectionHandler start,
+                           XML_EndCdataSectionHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+                                XML_StartCdataSectionHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+                              XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+   internal entities. These entity references will be passed to the
+   default handler, or to the skipped entity handler, if one is set.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandler(XML_Parser parser,
+                      XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of
+   internal entities.  The entity reference will not be passed to the
+   default handler.
+*/
+XMLPARSEAPI(void)
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+                            XML_DefaultHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+                          XML_StartDoctypeDeclHandler start,
+                          XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+                               XML_StartDoctypeDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+                             XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+                                 XML_UnparsedEntityDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNotationDeclHandler(XML_Parser parser,
+                           XML_NotationDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+                            XML_StartNamespaceDeclHandler start,
+                            XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+                                 XML_StartNamespaceDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+                               XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetNotStandaloneHandler(XML_Parser parser,
+                            XML_NotStandaloneHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+                                XML_ExternalEntityRefHandler handler);
+
+/* If a non-NULL value for arg is specified here, then it will be
+   passed as the first argument to the external entity ref handler
+   instead of the parser object.
+*/
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandlerArg(XML_Parser parser,
+                                   void *arg);
+
+XMLPARSEAPI(void)
+XML_SetSkippedEntityHandler(XML_Parser parser,
+                            XML_SkippedEntityHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+                              XML_UnknownEncodingHandler handler,
+                              void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end
+   element, processing instruction or character data.  It causes the
+   corresponding markup to be passed to the default handler.
+*/
+XMLPARSEAPI(void)
+XML_DefaultCurrent(XML_Parser parser);
+
+/* If do_nst is non-zero, and namespace processing is in effect, and
+   a name has a prefix (i.e. an explicit namespace qualifier) then
+   that name is returned as a triplet in a single string separated by
+   the separator character specified when the parser was created: URI
+   + sep + local_name + sep + prefix.
+
+   If do_nst is zero, then namespace information is returned in the
+   default manner (URI + sep + local_name) whether or not the name
+   has a prefix.
+
+   Note: Calling XML_SetReturnNSTriplet after XML_Parse or
+     XML_ParseBuffer has no effect.
+*/
+
+XMLPARSEAPI(void)
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst);
+
+/* This value is passed as the userData argument to callbacks. */
+XMLPARSEAPI(void)
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or NULL. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument to
+   XML_ParserCreate. On success XML_SetEncoding returns non-zero,
+   zero otherwise.
+   Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer
+     has no effect and returns XML_STATUS_ERROR.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed as the
+   first argument to callbacks instead of userData.  The userData will
+   still be accessible using XML_GetUserData.
+*/
+XMLPARSEAPI(void)
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* If useDTD == XML_TRUE is passed to this function, then the parser
+   will assume that there is an external subset, even if none is
+   specified in the document. In such a case the parser will call the
+   externalEntityRefHandler with a value of NULL for the systemId
+   argument (the publicId and context arguments will be NULL as well).
+   Note: For the purpose of checking WFC: Entity Declared, passing
+     useDTD == XML_TRUE will make the parser behave as if the document
+     had a DTD with an external subset.
+   Note: If this function is called, then this must be done before
+     the first call to XML_Parse or XML_ParseBuffer, since it will
+     have no effect after that.  Returns
+     XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING.
+   Note: If the document does not have a DOCTYPE declaration at all,
+     then startDoctypeDeclHandler and endDoctypeDeclHandler will not
+     be called, despite an external subset being parsed.
+   Note: If XML_DTD is not defined when Expat is compiled, returns
+     XML_ERROR_FEATURE_REQUIRES_XML_DTD.
+   Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
+
+
+/* Sets the base to be used for resolving relative URIs in system
+   identifiers in declarations.  Resolving relative identifiers is
+   left to the application: this value will be passed through as the
+   base argument to the XML_ExternalEntityRefHandler,
+   XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base
+   argument will be copied.  Returns XML_STATUS_ERROR if out of memory,
+   XML_STATUS_OK otherwise.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+XMLPARSEAPI(const XML_Char *)
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+   to the XML_StartElementHandler that were specified in the start-tag
+   rather than defaulted. Each attribute/value pair counts as 2; thus
+   this correspondds to an index into the atts array passed to the
+   XML_StartElementHandler.  Returns -1 if parser == NULL.
+*/
+XMLPARSEAPI(int)
+XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+   XML_StartElementHandler, or -1 if there is no ID attribute or
+   parser == NULL.  Each attribute/value pair counts as 2; thus this
+   correspondds to an index into the atts array passed to the
+   XML_StartElementHandler.
+*/
+XMLPARSEAPI(int)
+XML_GetIdAttributeIndex(XML_Parser parser);
+
+#ifdef XML_ATTR_INFO
+/* Source file byte offsets for the start and end of attribute names and values.
+   The value indices are exclusive of surrounding quotes; thus in a UTF-8 source
+   file an attribute value of "blah" will yield:
+   info->valueEnd - info->valueStart = 4 bytes.
+*/
+typedef struct {
+  XML_Index  nameStart;  /* Offset to beginning of the attribute name. */
+  XML_Index  nameEnd;    /* Offset after the attribute name's last byte. */
+  XML_Index  valueStart; /* Offset to beginning of the attribute value. */
+  XML_Index  valueEnd;   /* Offset after the attribute value's last byte. */
+} XML_AttrInfo;
+
+/* Returns an array of XML_AttrInfo structures for the attribute/value pairs
+   passed in last call to the XML_StartElementHandler that were specified
+   in the start-tag rather than defaulted. Each attribute/value pair counts
+   as 1; thus the number of entries in the array is
+   XML_GetSpecifiedAttributeCount(parser) / 2.
+*/
+XMLPARSEAPI(const XML_AttrInfo *)
+XML_GetAttributeInfo(XML_Parser parser);
+#endif
+
+/* Parses some input. Returns XML_STATUS_ERROR if a fatal error is
+   detected.  The last call to XML_Parse must have isFinal true; len
+   may be zero for this call (or any other).
+
+   Though the return values for these functions has always been
+   described as a Boolean value, the implementation, at least for the
+   1.95.x series, has always returned exactly one of the XML_Status
+   values.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+XMLPARSEAPI(void *)
+XML_GetBuffer(XML_Parser parser, int len);
+
+XMLPARSEAPI(enum XML_Status)
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return.
+   Must be called from within a call-back handler, except when aborting
+   (resumable = 0) an already suspended parser. Some call-backs may
+   still follow because they would otherwise get lost. Examples:
+   - endElementHandler() for empty elements when stopped in
+     startElementHandler(), 
+   - endNameSpaceDeclHandler() when stopped in endElementHandler(), 
+   and possibly others.
+
+   Can be called from most handlers, including DTD related call-backs,
+   except when parsing an external parameter entity and resumable != 0.
+   Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise.
+   Possible error codes: 
+   - XML_ERROR_SUSPENDED: when suspending an already suspended parser.
+   - XML_ERROR_FINISHED: when the parser has already finished.
+   - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE.
+
+   When resumable != 0 (true) then parsing is suspended, that is, 
+   XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. 
+   Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer()
+   return XML_STATUS_ERROR with error code XML_ERROR_ABORTED.
+
+   *Note*:
+   This will be applied to the current parser instance only, that is, if
+   there is a parent parser then it will continue parsing when the
+   externalEntityRefHandler() returns. It is up to the implementation of
+   the externalEntityRefHandler() to call XML_StopParser() on the parent
+   parser (recursively), if one wants to stop parsing altogether.
+
+   When suspended, parsing can be resumed by calling XML_ResumeParser(). 
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_StopParser(XML_Parser parser, XML_Bool resumable);
+
+/* Resumes parsing after it has been suspended with XML_StopParser().
+   Must not be called from within a handler call-back. Returns same
+   status codes as XML_Parse() or XML_ParseBuffer().
+   Additional error code XML_ERROR_NOT_SUSPENDED possible.   
+
+   *Note*:
+   This must be called on the most deeply nested child parser instance
+   first, and on its parent parser only after the child parser has finished,
+   to be applied recursively until the document entity's parser is restarted.
+   That is, the parent parser will not resume by itself and it is up to the
+   application to call XML_ResumeParser() on it at the appropriate moment.
+*/
+XMLPARSEAPI(enum XML_Status)
+XML_ResumeParser(XML_Parser parser);
+
+enum XML_Parsing {
+  XML_INITIALIZED,
+  XML_PARSING,
+  XML_FINISHED,
+  XML_SUSPENDED
+};
+
+typedef struct {
+  enum XML_Parsing parsing;
+  XML_Bool finalBuffer;
+} XML_ParsingStatus;
+
+/* Returns status of parser with respect to being initialized, parsing,
+   finished, or suspended and processing the final buffer.
+   XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus,
+   XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED
+*/
+XMLPARSEAPI(void)
+XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status);
+
+/* Creates an XML_Parser object that can parse an external general
+   entity; context is a '\0'-terminated string specifying the parse
+   context; encoding is a '\0'-terminated string giving the name of
+   the externally specified encoding, or NULL if there is no
+   externally specified encoding.  The context string consists of a
+   sequence of tokens separated by formfeeds (\f); a token consisting
+   of a name specifies that the general entity of the name is open; a
+   token of the form prefix=uri specifies the namespace for a
+   particular prefix; a token of the form =uri specifies the default
+   namespace.  This can be called at any point after the first call to
+   an ExternalEntityRefHandler so longer as the parser has not yet
+   been freed.  The new parser is completely independent and may
+   safely be used in a separate thread.  The handlers and userData are
+   initialized from the parser argument.  Returns NULL if out of memory.
+   Otherwise returns a new XML_Parser object.
+*/
+XMLPARSEAPI(XML_Parser)
+XML_ExternalEntityParserCreate(XML_Parser parser,
+                               const XML_Char *context,
+                               const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+  XML_PARAM_ENTITY_PARSING_NEVER,
+  XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+  XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+   subset). If parsing of parameter entities is enabled, then
+   references to external parameter entities (including the external
+   DTD subset) will be passed to the handler set with
+   XML_SetExternalEntityRefHandler.  The context passed will be 0.
+
+   Unlike external general entities, external parameter entities can
+   only be parsed synchronously.  If the external parameter entity is
+   to be parsed, it must be parsed during the call to the external
+   entity ref handler: the complete sequence of
+   XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and
+   XML_ParserFree calls must be made during this call.  After
+   XML_ExternalEntityParserCreate has been called to create the parser
+   for the external parameter entity (context must be 0 for this
+   call), it is illegal to make any calls on the old parser until
+   XML_ParserFree has been called on the newly created parser.
+   If the library has been compiled without support for parameter
+   entity parsing (ie without XML_DTD being defined), then
+   XML_SetParamEntityParsing will return 0 if parsing of parameter
+   entities is requested; otherwise it will return non-zero.
+   Note: If XML_SetParamEntityParsing is called after XML_Parse or
+      XML_ParseBuffer, then it has no effect and will always return 0.
+   Note: If parser == NULL, the function will do nothing and return 0.
+*/
+XMLPARSEAPI(int)
+XML_SetParamEntityParsing(XML_Parser parser,
+                          enum XML_ParamEntityParsing parsing);
+
+/* Sets the hash salt to use for internal hash calculations.
+   Helps in preventing DoS attacks based on predicting hash
+   function behavior. This must be called before parsing is started.
+   Returns 1 if successful, 0 when called after parsing has started.
+   Note: If parser == NULL, the function will do nothing and return 0.
+*/
+XMLPARSEAPI(int)
+XML_SetHashSalt(XML_Parser parser,
+                unsigned long hash_salt);
+
+/* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+   XML_GetErrorCode returns information about the error.
+*/
+XMLPARSEAPI(enum XML_Error)
+XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse
+   location.  They may be called from any callback called to report
+   some parse event; in this case the location is the location of the
+   first of the sequence of characters that generated the event.  When
+   called from callbacks generated by declarations in the document
+   prologue, the location identified isn't as neatly defined, but will
+   be within the relevant markup.  When called outside of the callback
+   functions, the position indicated will be just past the last parse
+   event (regardless of whether there was an associated callback).
+   
+   They may also be called after returning from a call to XML_Parse
+   or XML_ParseBuffer.  If the return value is XML_STATUS_ERROR then
+   the location is the location of the character at which the error
+   was detected; otherwise the location is the location of the last
+   parse event, as described above.
+
+   Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber
+   return 0 to indicate an error.
+   Note: XML_GetCurrentByteIndex returns -1 to indicate an error.
+*/
+XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser);
+XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+   Returns 0 if the event is in an internal entity.
+*/
+XMLPARSEAPI(int)
+XML_GetCurrentByteCount(XML_Parser parser);
+
+/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets
+   the integer pointed to by offset to the offset within this buffer
+   of the current parse position, and sets the integer pointed to by size
+   to the size of this buffer (the number of input bytes). Otherwise
+   returns a NULL pointer. Also returns a NULL pointer if a parse isn't
+   active.
+
+   NOTE: The character pointer returned should not be used outside
+   the handler that makes the call.
+*/
+XMLPARSEAPI(const char *)
+XML_GetInputContext(XML_Parser parser,
+                    int *offset,
+                    int *size);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber   XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex    XML_GetCurrentByteIndex
+
+/* Frees the content model passed to the element declaration handler */
+XMLPARSEAPI(void)
+XML_FreeContentModel(XML_Parser parser, XML_Content *model);
+
+/* Exposing the memory handling functions used in Expat */
+XMLPARSEAPI(void *)
+XML_ATTR_MALLOC
+XML_ATTR_ALLOC_SIZE(2)
+XML_MemMalloc(XML_Parser parser, size_t size);
+
+XMLPARSEAPI(void *)
+XML_ATTR_ALLOC_SIZE(3)
+XML_MemRealloc(XML_Parser parser, void *ptr, size_t size);
+
+XMLPARSEAPI(void)
+XML_MemFree(XML_Parser parser, void *ptr);
+
+/* Frees memory used by the parser. */
+XMLPARSEAPI(void)
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+XMLPARSEAPI(const XML_LChar *)
+XML_ErrorString(enum XML_Error code);
+
+/* Return a string containing the version number of this expat */
+XMLPARSEAPI(const XML_LChar *)
+XML_ExpatVersion(void);
+
+typedef struct {
+  int major;
+  int minor;
+  int micro;
+} XML_Expat_Version;
+
+/* Return an XML_Expat_Version structure containing numeric version
+   number information for this version of expat.
+*/
+XMLPARSEAPI(XML_Expat_Version)
+XML_ExpatVersionInfo(void);
+
+/* Added in Expat 1.95.5. */
+enum XML_FeatureEnum {
+  XML_FEATURE_END = 0,
+  XML_FEATURE_UNICODE,
+  XML_FEATURE_UNICODE_WCHAR_T,
+  XML_FEATURE_DTD,
+  XML_FEATURE_CONTEXT_BYTES,
+  XML_FEATURE_MIN_SIZE,
+  XML_FEATURE_SIZEOF_XML_CHAR,
+  XML_FEATURE_SIZEOF_XML_LCHAR,
+  XML_FEATURE_NS,
+  XML_FEATURE_LARGE_SIZE,
+  XML_FEATURE_ATTR_INFO
+  /* Additional features must be added to the end of this enum. */
+};
+
+typedef struct {
+  enum XML_FeatureEnum  feature;
+  const XML_LChar       *name;
+  long int              value;
+} XML_Feature;
+
+XMLPARSEAPI(const XML_Feature *)
+XML_GetFeatureList(void);
+
+
+/* Expat follows the semantic versioning convention.
+   See http://semver.org.
+*/
+#define XML_MAJOR_VERSION 2
+#define XML_MINOR_VERSION 2
+#define XML_MICRO_VERSION 7
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_INCLUDED */
diff --git a/Poco/XML/expat_external.h b/Poco/XML/expat_external.h
new file mode 100644
index 0000000..875225d
--- /dev/null
+++ b/Poco/XML/expat_external.h
@@ -0,0 +1,166 @@
+/*
+                            __  __            _
+                         ___\ \/ /_ __   __ _| |_
+                        / _ \\  /| '_ \ / _` | __|
+                       |  __//  \| |_) | (_| | |_
+                        \___/_/\_\ .__/ \__,_|\__|
+                                 |_| XML parser
+
+   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
+   Copyright (c) 2000-2017 Expat development team
+   Licensed under the MIT license:
+
+   Permission is  hereby granted,  free of charge,  to any  person obtaining
+   a  copy  of  this  software   and  associated  documentation  files  (the
+   "Software"),  to  deal in  the  Software  without restriction,  including
+   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
+   distribute, sublicense, and/or sell copies of the Software, and to permit
+   persons  to whom  the Software  is  furnished to  do so,  subject to  the
+   following conditions:
+
+   The above copyright  notice and this permission notice  shall be included
+   in all copies or substantial portions of the Software.
+
+   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 AND NONINFRINGEMENT. IN
+   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
+   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+   USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef Expat_External_INCLUDED
+#define Expat_External_INCLUDED 1
+
+/* External API definitions */
+
+#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
+# define XML_USE_MSC_EXTENSIONS 1
+#endif
+
+/* Expat tries very hard to make the API boundary very specifically
+   defined.  There are two macros defined to control this boundary;
+   each of these can be defined before including this header to
+   achieve some different behavior, but doing so it not recommended or
+   tested frequently.
+
+   XMLCALL    - The calling convention to use for all calls across the
+                "library boundary."  This will default to cdecl, and
+                try really hard to tell the compiler that's what we
+                want.
+
+   XMLIMPORT  - Whatever magic is needed to note that a function is
+                to be imported from a dynamically loaded library
+                (.dll, .so, or .sl, depending on your platform).
+
+   The XMLCALL macro was added in Expat 1.95.7.  The only one which is
+   expected to be directly useful in client code is XMLCALL.
+
+   Note that on at least some Unix versions, the Expat library must be
+   compiled with the cdecl calling convention as the default since
+   system headers may assume the cdecl convention.
+*/
+#ifndef XMLCALL
+# if defined(_MSC_VER)
+#  define XMLCALL __cdecl
+# elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER)
+#  define XMLCALL __attribute__((cdecl))
+# else
+/* For any platform which uses this definition and supports more than
+   one calling convention, we need to extend this definition to
+   declare the convention used on that platform, if it's possible to
+   do so.
+
+   If this is the case for your platform, please file a bug report
+   with information on how to identify your platform via the C
+   pre-processor and how to specify the same calling convention as the
+   platform's malloc() implementation.
+*/
+#  define XMLCALL
+# endif
+#endif  /* not defined XMLCALL */
+
+
+#if !defined(XML_STATIC) && !defined(XMLIMPORT)
+# ifndef XML_BUILDING_EXPAT
+/* using Expat from an application */
+
+#  ifdef XML_USE_MSC_EXTENSIONS
+#   define XMLIMPORT __declspec(dllimport)
+#  endif
+
+# endif
+#endif  /* not defined XML_STATIC */
+
+#ifndef XML_ENABLE_VISIBILITY
+# define XML_ENABLE_VISIBILITY 0
+#endif
+
+#if !defined(XMLIMPORT) && XML_ENABLE_VISIBILITY
+# define XMLIMPORT __attribute__ ((visibility ("default")))
+#endif
+
+/* If we didn't define it above, define it away: */
+#ifndef XMLIMPORT
+# define XMLIMPORT
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
+# define XML_ATTR_MALLOC __attribute__((__malloc__))
+#else
+# define XML_ATTR_MALLOC
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+# define XML_ATTR_ALLOC_SIZE(x)  __attribute__((__alloc_size__(x)))
+#else
+# define XML_ATTR_ALLOC_SIZE(x)
+#endif
+
+#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+# ifndef XML_UNICODE
+#  define XML_UNICODE
+# endif
+# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
+#  error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
+# endif
+#endif
+
+#ifdef XML_UNICODE     /* Information is UTF-16 encoded. */
+# ifdef XML_UNICODE_WCHAR_T
+typedef wchar_t XML_Char;
+typedef wchar_t XML_LChar;
+# else
+typedef unsigned short XML_Char;
+typedef char XML_LChar;
+# endif /* XML_UNICODE_WCHAR_T */
+#else                  /* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+#endif /* XML_UNICODE */
+
+#ifdef XML_LARGE_SIZE  /* Use large integers for file/stream positions. */
+# if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+typedef __int64 XML_Index; 
+typedef unsigned __int64 XML_Size;
+# else
+typedef long long XML_Index;
+typedef unsigned long long XML_Size;
+# endif
+#else
+typedef long XML_Index;
+typedef unsigned long XML_Size;
+#endif /* XML_LARGE_SIZE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not Expat_External_INCLUDED */
diff --git a/Poco/Zip/Add.h b/Poco/Zip/Add.h
new file mode 100644
index 0000000..016a57c
--- /dev/null
+++ b/Poco/Zip/Add.h
@@ -0,0 +1,51 @@
+//
+// Add.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  Add
+//
+// Definition of the Add class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Add_INCLUDED
+#define Zip_Add_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipOperation.h"
+#include "Poco/Zip/ZipCommon.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API Add: public ZipOperation
+	/// Operation Add adds a new file entry to an existing Zip File
+{
+public:
+	Add(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl);
+		/// Creates the Add.
+
+	void execute(Compress& c, std::istream& input);
+		/// Performs the add operation
+
+private:
+	const std::string _zipPath;
+	const std::string _localPath;
+	const ZipCommon::CompressionMethod _cm;
+	const ZipCommon::CompressionLevel _cl;
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Add_INCLUDED
diff --git a/Poco/Zip/AutoDetectStream.h b/Poco/Zip/AutoDetectStream.h
new file mode 100644
index 0000000..da14a74
--- /dev/null
+++ b/Poco/Zip/AutoDetectStream.h
@@ -0,0 +1,101 @@
+//
+// AutoDetectStream.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  AutoDetectStream
+//
+// Definition of the AutoDetectStream class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_AutoDetectStream_INCLUDED
+#define Zip_AutoDetectStream_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/BufferedStreamBuf.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API AutoDetectStreamBuf: public Poco::BufferedStreamBuf
+	/// AutoDetectStreamBuf automatically detects the end of a stream using the 
+	/// Data Descriptor signature.
+{
+public:
+	AutoDetectStreamBuf(std::istream& in, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start, bool needsZip64);
+		/// Creates the AutoDetectStream. 
+		
+	~AutoDetectStreamBuf();
+		/// Destroys the AutoDetectStream.
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE  = 1024
+	};
+
+	std::istream*   _pIstr;
+	bool            _eofDetected;
+	int             _matchCnt;
+	std::string     _prefix;
+	std::string     _postfix;
+	bool            _reposition;
+	Poco::UInt32    _start;
+	bool            _needsZip64;
+	Poco::UInt64    _length;
+};
+
+
+class Zip_API AutoDetectIOS: public virtual std::ios
+	/// The base class for AutoDetectInputStream and AutoDetectOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	AutoDetectIOS(std::istream& istr, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start, bool needsZip64);
+		/// Creates the basic stream and connects it
+		/// to the given input stream.
+
+	~AutoDetectIOS();
+		/// Destroys the stream.
+
+	AutoDetectStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	AutoDetectStreamBuf _buf;
+};
+
+
+class Zip_API AutoDetectInputStream: public AutoDetectIOS, public std::istream
+	/// AutoDetectInputStream automatically detects the end of a stream using the 
+	/// Data Descriptor signature.
+{
+public:
+	AutoDetectInputStream(std::istream& istr, const std::string& prefix = std::string(), const std::string& postfix = std::string(), bool reposition = false, Poco::UInt32 start = 0, bool needsZip64 = false);
+		/// Creates the AutoDetectInputStream and connects it to the underlying stream.
+
+	~AutoDetectInputStream();
+		/// Destroys the AutoDetectInputStream.
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_AutoDetectStream_INCLUDED
diff --git a/Poco/Zip/Compress.h b/Poco/Zip/Compress.h
new file mode 100644
index 0000000..b71418d
--- /dev/null
+++ b/Poco/Zip/Compress.h
@@ -0,0 +1,151 @@
+//
+// Compress.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  Compress
+//
+// Definition of the Compress class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Compress_INCLUDED
+#define Zip_Compress_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipArchive.h"
+#include "Poco/FIFOEvent.h"
+#include <istream>
+#include <ostream>
+#include <set>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API Compress
+	/// Compresses a directory or files as zip.
+{
+public:
+	Poco::FIFOEvent<const ZipLocalFileHeader> EDone;
+
+	Compress(std::ostream& out, bool seekableOut, bool forceZip64 = false);
+		/// seekableOut determines how we write the zip, setting it to true is recommended for local files (smaller zip file),
+		/// if you are compressing directly to a network, you MUST set it to false
+		/// If forceZip64 is set true then the file header is allocated with zip64 extension so that it can be updated after the file data is written
+		/// if seekableOut is true in case the compressed or uncompressed size exceeds 32 bits.
+
+	~Compress();
+
+	void addFile(std::istream& input, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM);
+		/// Adds a single file to the Zip File. fileName must not be a directory name.
+
+	void addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM);
+		/// Adds a single file to the Zip File. fileName must not be a directory name. The file must exist physically!
+
+	void addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt);
+		/// Adds a directory entry excluding all children to the Zip file, entryName must not be empty.
+
+	void addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM, bool excludeRoot = true, const Poco::Path& name = Poco::Path());
+		/// Adds a directory entry recursively to the zip file, set excludeRoot to false to exclude the parent directory.
+		/// If excludeRoot is true you can specify an empty name to add the files as relative files
+
+	void addRecursive(const Poco::Path& entry, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM, bool excludeRoot = true, const Poco::Path& name = Poco::Path());
+		/// Adds a directory entry recursively to the zip file, set excludeRoot to false to exclude the parent directory.
+		/// If excludeRoot is true you can specify an empty name to add the files as relative files
+
+	void setZipComment(const std::string& comment);
+		/// Sets the Zip file comment.
+
+	const std::string& getZipComment() const;
+		/// Returns the Zip file comment.
+		
+	ZipArchive close();
+		/// Finalizes the ZipArchive, closes it.
+
+	void setStoreExtensions(const std::set<std::string>& extensions);
+		/// Sets the file extensions for which the CM_STORE compression method
+		/// is used if CM_AUTO is specified in addFile() or addRecursive().
+		/// For all other extensions, CM_DEFLATE is used. This is used to avoid
+		/// double compression of already compressed file formats, which usually
+		/// leads to worse results. Extensions will be converted to lower case.
+		///
+		/// The default extensions are:
+		///   - gif
+		///   - jpg
+		///   - jpeg
+		///   - png
+		
+	const std::set<std::string>& getStoreExtensions() const;
+		/// Returns the file extensions for which the CM_STORE compression method
+		/// is used if CM_AUTO is specified in addFile() or addRecursive().
+		///
+		/// See setStoreExtensions() for more information.
+
+private:
+	enum
+	{
+		COMPRESS_CHUNK_SIZE = 8192
+	};
+
+	Compress(const Compress&);
+	Compress& operator=(const Compress&);
+
+	void addEntry(std::istream& input, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM);
+		/// Either adds a file or a single directory entry (excluding subchildren) to the Zip file. the compression level will be ignored
+		/// for directories.
+
+	void addFileRaw(std::istream& in, const ZipLocalFileHeader& hdr, const Poco::Path& fileName);
+		/// copys an already compressed ZipEntry from in
+
+private:
+	std::set<std::string>        _storeExtensions;
+	std::ostream&                _out;
+	bool                         _seekableOut;
+	bool						 _forceZip64;
+	ZipArchive::FileHeaders      _files;
+	ZipArchive::FileInfos        _infos;
+	ZipArchive::DirectoryInfos   _dirs;
+	ZipArchive::DirectoryInfos64 _dirs64;
+	Poco::UInt64				 _offset;
+    std::string                  _comment;
+
+	friend class Keep;
+	friend class Rename;
+};
+
+
+//
+// inlines
+//
+
+
+inline void Compress::setZipComment(const std::string& comment)
+{
+	_comment = comment;
+}
+
+
+inline const std::string& Compress::getZipComment() const
+{
+	return _comment;
+}
+
+
+inline const std::set<std::string>& Compress::getStoreExtensions() const
+{
+	return _storeExtensions;
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Compress_INCLUDED
diff --git a/Poco/Zip/Decompress.h b/Poco/Zip/Decompress.h
new file mode 100644
index 0000000..ca4ae29
--- /dev/null
+++ b/Poco/Zip/Decompress.h
@@ -0,0 +1,90 @@
+//
+// Decompress.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  Decompress
+//
+// Definition of the Decompress class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Decompress_INCLUDED
+#define Zip_Decompress_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ParseCallback.h"
+#include "Poco/Zip/ZipArchive.h"
+#include "Poco/Path.h"
+#include "Poco/FIFOEvent.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ZipArchive;
+
+
+class Zip_API Decompress: public ParseCallback
+	/// Decompress extracts files from zip files, can be used to extract single files or all files
+{
+public:
+	typedef std::map<std::string, Poco::Path> ZipMapping;
+		/// Maps key of FileInfo entries to their local decompressed representation
+	Poco::FIFOEvent<std::pair<const ZipLocalFileHeader, const std::string> > EError;
+		/// Thrown whenever an error is detected when handling a ZipLocalFileHeader entry. The string contains an error message
+	Poco::FIFOEvent<std::pair<const ZipLocalFileHeader, const Poco::Path> > EOk;
+		/// Thrown whenever a file was successfully decompressed
+
+	Decompress(std::istream& in, const Poco::Path& outputDir, bool flattenDirs = false, bool keepIncompleteFiles = false);
+		/// Creates the Decompress. Note that istream must be good and at the very beginning of the file!
+		/// Calling decompressAllFiles will cause the stream to be in state failed once the zip file is processed.
+		/// outputDir must be a directory. If it doesn't exist yet, it will be automatically created.
+		/// If flattenDirs is set to true, the directory structure of the zip file is not recreated. 
+		/// Instead, all files are extracted into one single directory.
+
+	~Decompress();
+		/// Destroys the Decompress.
+
+	ZipArchive decompressAllFiles();
+		/// Decompresses all files stored in the zip File. Can only be called once per Decompress object.
+		/// Use mapping to retrieve the location of the decompressed files
+
+	bool handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr);
+
+	const ZipMapping& mapping() const;
+		/// A ZipMapping stores as key the full name of the ZipFileInfo/ZipLocalFileHeader and as value the decompressed file
+		/// If for a ZipFileInfo no mapping exists, there was an error during decompression and the entry is considered to be corrupt
+
+private:
+	Decompress(const Decompress&);
+	Decompress& operator=(const Decompress&);
+
+	void onOk(const void*, std::pair<const ZipLocalFileHeader, const Poco::Path>& val);
+
+private:
+	std::istream& _in;
+	Poco::Path    _outDir;
+	bool          _flattenDirs;
+	bool          _keepIncompleteFiles;
+	ZipMapping    _mapping;
+};
+
+
+inline const Decompress::ZipMapping& Decompress::mapping() const
+{
+	return _mapping;
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Decompress_INCLUDED
diff --git a/Poco/Zip/Delete.h b/Poco/Zip/Delete.h
new file mode 100644
index 0000000..6672325
--- /dev/null
+++ b/Poco/Zip/Delete.h
@@ -0,0 +1,48 @@
+//
+// Delete.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  Delete
+//
+// Definition of the Delete class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Delete_INCLUDED
+#define Zip_Delete_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipOperation.h"
+#include "Poco/Zip/ZipLocalFileHeader.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API Delete: public ZipOperation
+	/// Delete Operation removes an entry from a Zip
+{
+public:
+	Delete(const ZipLocalFileHeader& hdr);
+		/// Creates the Delete.
+
+	void execute(Compress& c, std::istream& input);
+		/// Throws away the ZipEntry
+
+private:
+	const ZipLocalFileHeader _hdr;
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Delete_INCLUDED
diff --git a/Poco/Zip/Keep.h b/Poco/Zip/Keep.h
new file mode 100644
index 0000000..c20108e
--- /dev/null
+++ b/Poco/Zip/Keep.h
@@ -0,0 +1,49 @@
+//
+// Keep.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  Keep
+//
+// Definition of the Keep class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Keep_INCLUDED
+#define Zip_Keep_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipOperation.h"
+#include "Poco/Zip/ZipLocalFileHeader.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API Keep: public ZipOperation
+	/// Keep simply forwards the compressed data stream from the input ZipArchive
+	/// to the output zip archive
+{
+public:
+	Keep(const ZipLocalFileHeader& hdr);
+		/// Creates the Keep object.
+
+	void execute(Compress& c, std::istream& input);
+		///Adds a copy of the compressed input file to the ZipArchive
+
+private:
+	const ZipLocalFileHeader _hdr;
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Keep_INCLUDED
diff --git a/Poco/Zip/ParseCallback.h b/Poco/Zip/ParseCallback.h
new file mode 100644
index 0000000..c566d79
--- /dev/null
+++ b/Poco/Zip/ParseCallback.h
@@ -0,0 +1,54 @@
+//
+// ParseCallback.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ParseCallback
+//
+// Definition of the ParseCallback class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ParseCallback_INCLUDED
+#define Zip_ParseCallback_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ZipLocalFileHeader;
+
+
+class Zip_API ParseCallback
+	/// Interface for callbacks to handle ZipData
+{
+public:
+	ParseCallback();
+		/// Creates the ParseCallback.
+
+	virtual ~ParseCallback();
+		/// Destroys the ParseCallback.
+
+	virtual bool handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr) = 0;
+		/// Handles parsing of the data of a single Zip Entry. zipStream is guaranteed to be at the very first data byte.
+		/// Note that a callback class SHOULD consume all data inside a zip file, ie. after
+		/// processing the next 4 bytes point the next ZipLocalFileHeader or the ZipDirectory.
+		/// If it fails to do so, it must return false, otherwise true.
+
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ParseCallback_INCLUDED
diff --git a/Poco/Zip/PartialStream.h b/Poco/Zip/PartialStream.h
new file mode 100644
index 0000000..bdc9474
--- /dev/null
+++ b/Poco/Zip/PartialStream.h
@@ -0,0 +1,187 @@
+//
+// PartialStream.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  PartialStream
+//
+// Definition of the PartialStream class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_PartialStream_INCLUDED
+#define Zip_PartialStream_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/BufferedStreamBuf.h"
+#include "Poco/Buffer.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API PartialStreamBuf: public Poco::BufferedStreamBuf
+	/// A PartialStreamBuf is a class that limits one view on an inputstream to a selected view range
+{
+public:
+	PartialStreamBuf(std::istream& in, std::ios::pos_type start, std::ios::pos_type end, const std::string& prefix, const std::string& postfix, bool initStream);
+		/// Creates the PartialStream. 
+		/// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned
+		/// to position start
+
+	PartialStreamBuf(std::ostream& out, std::size_t start, std::size_t end, bool initStream);
+		/// Creates the PartialStream. 
+		/// If initStream is true the status of the stream will be cleared on the first access.
+		/// start and end acts as offset values for the written content. A start value greater than zero,
+		/// means that the first bytes are not written but discarded instead,
+		/// an end value not equal to zero means that the last end bytes are not written!
+		/// Examples:
+		///     start = 3; end = 1
+		///     write("hello", 5) -> "l"
+
+	~PartialStreamBuf();
+		/// Destroys the PartialStream.
+
+	void close();
+		/// Flushes a writing streambuf
+
+	Poco::UInt64 bytesWritten() const;
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum 
+	{
+		STREAM_BUFFER_SIZE  = 1024
+	};
+
+	bool           _initialized;
+	std::ios::pos_type  _start;
+	Poco::UInt64   _numBytes;
+	Poco::UInt64   _bytesWritten;
+	std::istream*  _pIstr;
+	std::ostream*  _pOstr;
+	std::string    _prefix;
+	std::string    _postfix;
+	std::size_t    _ignoreStart;
+	Poco::Buffer<char> _buffer;
+	Poco::UInt32   _bufferOffset;
+};
+
+
+inline Poco::UInt64 PartialStreamBuf::bytesWritten() const
+{
+	return _bytesWritten;
+}
+
+
+class Zip_API PartialIOS: public virtual std::ios
+	/// The base class for PartialInputStream and PartialOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	PartialIOS(std::istream& istr, std::ios::pos_type start, std::ios::pos_type end, const std::string& prefix, const std::string& postfix, bool initStream);
+		/// Creates the basic stream and connects it
+		/// to the given input stream.
+		/// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned
+		/// to position start
+
+	PartialIOS(std::ostream& ostr, std::size_t start, std::size_t end, bool initStream);
+		/// Creates the basic stream and connects it
+		/// to the given output stream.
+		/// If initStream is true the status of the stream will be cleared on the first access.
+		/// start and end acts as offset values for the written content. A start value greater than zero,
+		/// means that the first bytes are not written but discarded instead,
+		/// an end value not equal to zero means that the last end bytes are not written!
+		/// Examples:
+		///     start = 3; end = 1
+		///     write("hello", 5) -> "l"
+
+	~PartialIOS();
+		/// Destroys the stream.
+
+	PartialStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	PartialStreamBuf _buf;
+};
+
+
+class Zip_API PartialInputStream: public PartialIOS, public std::istream
+	/// This stream copies all characters read through it
+	/// to one or multiple output streams.
+{
+public:
+	PartialInputStream(std::istream& istr, std::ios::pos_type start, std::ios::pos_type end, bool initStream = true, const std::string& prefix = std::string(), const std::string& postfix = std::string());
+		/// Creates the PartialInputStream and connects it
+		/// to the given input stream. Bytes read are guaranteed to be in the range [start, end-1]
+		/// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned
+		/// to position start
+
+	~PartialInputStream();
+		/// Destroys the PartialInputStream.
+};
+
+
+class Zip_API PartialOutputStream: public PartialIOS, public std::ostream
+	/// This stream copies all characters written to it
+	/// to one or multiple output streams.
+{
+public:
+	PartialOutputStream(std::ostream& ostr, std::size_t start, std::size_t end, bool initStream = true);
+		/// Creates the PartialOutputStream and connects it
+		/// to the given output stream. Bytes written are guaranteed to be in the range [start, realEnd - end].
+		/// If initStream is true the status of the stream will be cleared on the first access.
+		/// start and end acts as offset values for the written content. A start value greater than zero,
+		/// means that the first bytes are not written but discarded instead,
+		/// an end value not equal to zero means that the last end bytes are not written!
+		/// Examples:
+		///     start = 3; end = 1
+		///     write("hello", 5) -> "l"
+		///     
+		///     start = 3; end = 0
+		///     write("hello", 5) -> "lo"
+
+	~PartialOutputStream();
+		/// Destroys the PartialOutputStream.
+
+	void close();
+		/// must be called for the stream to properly terminate it
+
+	Poco::UInt64 bytesWritten() const;
+		/// Returns the number of bytes actually forwarded to the inner ostream
+};
+
+
+inline void PartialOutputStream::close()
+{
+	flush();
+	_buf.close();
+}
+
+
+inline Poco::UInt64 PartialOutputStream::bytesWritten() const
+{
+	return _buf.bytesWritten();
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_PartialStream_INCLUDED
diff --git a/Poco/Zip/Rename.h b/Poco/Zip/Rename.h
new file mode 100644
index 0000000..487dc19
--- /dev/null
+++ b/Poco/Zip/Rename.h
@@ -0,0 +1,49 @@
+//
+// Rename.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  Rename
+//
+// Definition of the Rename class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Rename_INCLUDED
+#define Zip_Rename_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipOperation.h"
+#include "Poco/Zip/ZipLocalFileHeader.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API Rename: public ZipOperation
+	/// Renames an existing Zip Entry
+{
+public:
+	Rename(const ZipLocalFileHeader& hdr, const std::string& newZipEntryName);
+		/// Creates the Rename.
+
+	void execute(Compress& c, std::istream& input);
+		/// Performs the rename operation
+
+private:
+	const ZipLocalFileHeader _hdr;
+	const std::string _newZipEntryName;
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Rename_INCLUDED
diff --git a/Poco/Zip/Replace.h b/Poco/Zip/Replace.h
new file mode 100644
index 0000000..6ca558d
--- /dev/null
+++ b/Poco/Zip/Replace.h
@@ -0,0 +1,50 @@
+//
+// Replace.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  Replace
+//
+// Definition of the Replace class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Replace_INCLUDED
+#define Zip_Replace_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/Add.h"
+#include "Poco/Zip/Delete.h"
+#include "Poco/Zip/ZipOperation.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API Replace: public ZipOperation
+	/// Operation Replace replaces the content of an existing entry with a new one
+{
+public:
+	Replace(const ZipLocalFileHeader& hdr, const std::string& localPath);
+		/// Creates the Replace.
+
+	void execute(Compress& c, std::istream& input);
+		/// Performs the replace operation
+
+private:
+	Delete _del;
+	Add _add;
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_Replace_INCLUDED
diff --git a/Poco/Zip/SkipCallback.h b/Poco/Zip/SkipCallback.h
new file mode 100644
index 0000000..c4d63b0
--- /dev/null
+++ b/Poco/Zip/SkipCallback.h
@@ -0,0 +1,46 @@
+//
+// SkipCallback.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  SkipCallback
+//
+// Definition of the SkipCallback class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_SkipCallback_INCLUDED
+#define Zip_SkipCallback_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ParseCallback.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API SkipCallback: public ParseCallback
+	/// A SkipCallback simply skips over the data
+{
+public:
+	SkipCallback();
+		/// Creates the SkipCallback.
+
+	virtual ~SkipCallback();
+		/// Destroys the SkipCallback.
+
+	bool handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr);
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_SkipCallback_INCLUDED
diff --git a/Poco/Zip/Zip.h b/Poco/Zip/Zip.h
new file mode 100644
index 0000000..1f1d781
--- /dev/null
+++ b/Poco/Zip/Zip.h
@@ -0,0 +1,62 @@
+//
+// Zip.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  Zip
+//
+// Basic definitions for the Poco Zip library.
+// This file must be the first file included by every other Zip
+// header file.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_Zip_INCLUDED
+#define Zip_Zip_INCLUDED
+
+
+#include "Poco/Foundation.h"
+
+
+//
+// The following block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the Zip_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// Zip_API functions as being imported from a DLL, whereas this DLL sees symbols
+// defined with this macro as being exported.
+//
+#if defined(_WIN32) && defined(POCO_DLL)
+	#if defined(Zip_EXPORTS)
+		#define Zip_API __declspec(dllexport)
+	#else
+		#define Zip_API __declspec(dllimport)
+	#endif
+#endif
+
+
+#if !defined(Zip_API)
+	#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
+		#define Zip_API __attribute__ ((visibility ("default")))
+	#else
+		#define Zip_API
+	#endif
+#endif
+
+
+//
+// Automatically link Zip library.
+//
+#if defined(_MSC_VER)
+	#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Zip_EXPORTS)
+		#pragma comment(lib, "PocoZip" POCO_LIB_SUFFIX)
+	#endif
+#endif
+
+
+#endif // Zip_Zip_INCLUDED
diff --git a/Poco/Zip/ZipArchive.h b/Poco/Zip/ZipArchive.h
new file mode 100644
index 0000000..8951d59
--- /dev/null
+++ b/Poco/Zip/ZipArchive.h
@@ -0,0 +1,121 @@
+//
+// ZipArchive.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipArchive
+//
+// Definition of the ZipArchive class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipArchive_INCLUDED
+#define Zip_ZipArchive_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipLocalFileHeader.h"
+#include "Poco/Zip/ZipFileInfo.h"
+#include "Poco/Zip/ZipArchiveInfo.h"
+#include <istream>
+#include <map>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ParseCallback;
+class Compress;
+
+
+class Zip_API ZipArchive
+	/// A ZipArchive contains information on the content of a zip file
+{
+public:
+	typedef std::map<std::string, ZipLocalFileHeader> FileHeaders;
+	typedef std::map<std::string, ZipFileInfo> FileInfos;
+	typedef std::map<Poco::UInt16, ZipArchiveInfo> DirectoryInfos;
+	typedef std::map<Poco::UInt32, ZipArchiveInfo64> DirectoryInfos64;
+
+	ZipArchive(std::istream& in);
+		/// Creates the ZipArchive from a file. Note that the in stream will be in state failed after the constructor is finished
+
+	ZipArchive(std::istream& in, ParseCallback& callback);
+		/// Creates the ZipArchive from a file or network stream. Note that the in stream will be in state failed after the constructor is finished
+
+	~ZipArchive();
+		/// Destroys the ZipArchive.
+
+	FileInfos::const_iterator fileInfoBegin() const;
+
+	FileInfos::const_iterator fileInfoEnd() const;
+
+	FileHeaders::const_iterator findHeader(const std::string& fileName) const;
+
+	FileHeaders::const_iterator headerBegin() const;
+
+	FileHeaders::const_iterator headerEnd() const;
+
+	const std::string& getZipComment() const;
+
+private:
+	void parse(std::istream& in, ParseCallback& pc);
+
+	ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs, const DirectoryInfos64& dirs64 );
+
+private:
+	FileHeaders    _entries;
+		/// Info generated by parsing the data block of the zip file
+	FileInfos      _infos;
+		/// Info generated by parsing the directory block of the zip file
+	DirectoryInfos _disks;
+		/// Stores directory info for all found disks
+	DirectoryInfos64 _disks64;
+		/// Stores directory info for all found disks
+		
+	static const std::string EMPTY_COMMENT;
+
+	friend class Compress;
+};
+
+
+inline ZipArchive::FileInfos::const_iterator ZipArchive::fileInfoBegin() const
+{
+	return _infos.begin();
+}
+
+
+inline ZipArchive::FileInfos::const_iterator ZipArchive::fileInfoEnd() const
+{
+	return _infos.end();
+}
+
+
+inline ZipArchive::FileHeaders::const_iterator ZipArchive::findHeader(const std::string& fileName) const
+{
+	return _entries.find(fileName);
+}
+
+
+inline ZipArchive::FileHeaders::const_iterator ZipArchive::headerBegin() const
+{
+	return _entries.begin();
+}
+
+
+inline ZipArchive::FileHeaders::const_iterator ZipArchive::headerEnd() const
+{
+	return _entries.end();
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipArchive_INCLUDED
diff --git a/Poco/Zip/ZipArchiveInfo.h b/Poco/Zip/ZipArchiveInfo.h
new file mode 100644
index 0000000..3605e60
--- /dev/null
+++ b/Poco/Zip/ZipArchiveInfo.h
@@ -0,0 +1,405 @@
+//
+// ZipArchiveInfo.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipArchiveInfo
+//
+// Definition of the ZipArchiveInfo class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipArchiveInfo_INCLUDED
+#define Zip_ZipArchiveInfo_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipCommon.h"
+#include "Poco/Zip/ZipUtil.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API ZipArchiveInfo
+	/// A ZipArchiveInfo stores central directory info
+{
+public:
+	static const char HEADER[ZipCommon::HEADER_SIZE];
+
+	ZipArchiveInfo();
+		/// Default constructor, everything set to zero or empty
+
+	ZipArchiveInfo(std::istream& in, bool assumeHeaderRead);
+		/// Creates the ZipArchiveInfo by parsing the input stream.
+		/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
+
+	~ZipArchiveInfo();
+		/// Destroys the ZipArchiveInfo.
+
+	Poco::UInt16 getDiskNumber() const;
+		/// Get the number of the disk where this header can be found
+
+	Poco::UInt16 getFirstDiskForDirectoryHeader() const;
+		/// Returns the number of the disk that contains the start of the directory header
+
+	Poco::UInt16 getNumberOfEntries() const;
+		/// Returns the number of entries on this disk
+
+	Poco::UInt16 getTotalNumberOfEntries() const;
+		/// Returns the total number of entries on all disks
+
+	Poco::UInt32 getCentralDirectorySize() const;
+		/// Returns the size of the central directory in bytes
+
+	std::streamoff getHeaderOffset() const;
+		/// Returns the offset of the header in relation to the begin of this disk
+
+	const std::string& getZipComment() const;
+		/// Returns the (optional) Zip Comment
+
+	void setZipComment(const std::string& comment);
+		/// Sets the optional Zip comment.
+
+	void setNumberOfEntries(Poco::UInt16 val);
+		/// Sets the number of entries on this disk
+
+	void setTotalNumberOfEntries(Poco::UInt16 val);
+		/// Sets the total number of entries on all disks
+
+	void setCentralDirectorySize(Poco::UInt32 val);
+		/// Sets the size of the central directory in bytes
+
+	void setCentralDirectoryOffset(Poco::UInt32 val);
+		/// Sets the offset of the central directory from beginning of first disk
+
+	void setHeaderOffset(std::streamoff val);
+		/// Sets the offset of the header in relation to the begin of this disk
+
+	std::string createHeader() const;
+		/// Creates a header
+
+private:
+	void parse(std::istream& inp, bool assumeHeaderRead);
+
+	Poco::UInt16 getZipCommentSize() const;
+
+private:
+	enum
+	{
+		HEADER_POS = 0,
+		NUMBEROFTHISDISK_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
+		NUMBEROFTHISDISK_SIZE = 2,
+		NUMBEROFCENTRALDIRDISK_POS = NUMBEROFTHISDISK_POS + NUMBEROFTHISDISK_SIZE,
+		NUMBEROFCENTRALDIRDISK_SIZE = 2,
+		NUMENTRIESTHISDISK_POS = NUMBEROFCENTRALDIRDISK_POS + NUMBEROFCENTRALDIRDISK_SIZE,
+		NUMENTRIESTHISDISK_SIZE = 2,
+		TOTALNUMENTRIES_POS = NUMENTRIESTHISDISK_POS + NUMENTRIESTHISDISK_SIZE,
+		TOTALNUMENTRIES_SIZE = 2,
+		CENTRALDIRSIZE_POS = TOTALNUMENTRIES_POS + TOTALNUMENTRIES_SIZE,
+		CENTRALDIRSIZE_SIZE = 4,
+		CENTRALDIRSTARTOFFSET_POS = CENTRALDIRSIZE_POS + CENTRALDIRSIZE_SIZE,
+		CENTRALDIRSTARTOFFSET_SIZE = 4,
+		ZIPCOMMENT_LENGTH_POS = CENTRALDIRSTARTOFFSET_POS + CENTRALDIRSTARTOFFSET_SIZE,
+		ZIPCOMMENT_LENGTH_SIZE = 2,
+		FULLHEADER_SIZE = 22
+	};
+
+	char           _rawInfo[FULLHEADER_SIZE];
+	std::streamoff _startPos;
+	std::string    _comment;
+};
+
+
+class Zip_API ZipArchiveInfo64
+	/// A ZipArchiveInfo64 stores central directory info
+{
+public:
+	static const char HEADER[ZipCommon::HEADER_SIZE];
+	static const char LOCATOR_HEADER[ZipCommon::HEADER_SIZE];
+
+	ZipArchiveInfo64();
+		/// Default constructor, everything set to zero or empty
+
+	ZipArchiveInfo64(std::istream& in, bool assumeHeaderRead);
+		/// Creates the ZipArchiveInfo64 by parsing the input stream.
+		/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
+
+	~ZipArchiveInfo64();
+		/// Destroys the ZipArchiveInfo64.
+
+	void getVersionMadeBy(int& major, int& minor);	
+		/// The ZIP version used to create the file
+
+	void getRequiredVersion(int& major, int& minor);
+		/// The minimum version required to extract the data
+
+	Poco::UInt32 getDiskNumber() const;
+		/// Get the number of the disk where this header can be found
+
+	Poco::UInt32 getFirstDiskForDirectoryHeader() const;
+		/// Returns the number of the disk that contains the start of the directory header
+
+	Poco::UInt64 getNumberOfEntries() const;
+		/// Returns the number of entries on this disk
+
+	Poco::UInt64 getTotalNumberOfEntries() const;
+		/// Returns the total number of entries on all disks
+
+	Poco::UInt64 getCentralDirectorySize() const;
+		/// Returns the size of the central directory in bytes
+
+	std::streamoff getCentralDirectoryOffset() const;
+		/// Returns the offset of the central directory from beginning of first disk
+	
+	std::streamoff getHeaderOffset() const;
+		/// Returns the offset of the header in relation to the begin of this disk
+
+	void setNumberOfEntries(Poco::UInt64 val);
+		/// Sets the number of entries on this disk
+
+	void setTotalNumberOfEntries(Poco::UInt64 val);
+		/// Sets the total number of entries on all disks
+
+	void setCentralDirectorySize(Poco::UInt64 val);
+		/// Set the size of the central directory in bytes
+
+	void setCentralDirectoryOffset(Poco::UInt64 val);
+		/// Returns the offset of the central directory from beginning of first disk
+
+	void setHeaderOffset(std::streamoff val);
+		/// Sets the offset of the header in relation to the begin of this disk
+	
+	void setTotalNumberOfDisks(Poco::UInt32 val);
+		/// Sets the offset of the central directory from beginning of first disk
+
+	std::string createHeader() const;
+		/// Creates a header
+
+private:
+	void parse(std::istream& inp, bool assumeHeaderRead);
+	void setRequiredVersion(int major, int minor);
+
+private:
+	enum
+	{
+		HEADER_POS = 0,
+		RECORDSIZE_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
+		RECORDSIZE_SIZE = 8,
+		VERSIONMADEBY_POS = RECORDSIZE_POS + RECORDSIZE_SIZE,
+		VERSIONMADEBY_SIZE = 2,
+		VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
+		VERSION_NEEDED_SIZE = 2,
+		NUMBEROFTHISDISK_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
+		NUMBEROFTHISDISK_SIZE = 4,
+		NUMBEROFCENTRALDIRDISK_POS = NUMBEROFTHISDISK_POS + NUMBEROFTHISDISK_SIZE,
+		NUMBEROFCENTRALDIRDISK_SIZE = 4,
+		NUMENTRIESTHISDISK_POS = NUMBEROFCENTRALDIRDISK_POS + NUMBEROFCENTRALDIRDISK_SIZE,
+		NUMENTRIESTHISDISK_SIZE = 8,
+		TOTALNUMENTRIES_POS = NUMENTRIESTHISDISK_POS + NUMENTRIESTHISDISK_SIZE,
+		TOTALNUMENTRIES_SIZE = 8,
+		CENTRALDIRSIZE_POS = TOTALNUMENTRIES_POS + TOTALNUMENTRIES_SIZE,
+		CENTRALDIRSIZE_SIZE = 8,
+		CENTRALDIRSTARTOFFSET_POS = CENTRALDIRSIZE_POS + CENTRALDIRSIZE_SIZE,
+		CENTRALDIRSTARTOFFSET_SIZE = 8,
+		FULL_HEADER_SIZE = 56,
+
+		LOCATOR_HEADER_POS = 0,
+		NUMBEROFENDOFCENTRALDIRDISK_POS = LOCATOR_HEADER_POS + ZipCommon::HEADER_SIZE,
+		NUMBEROFENDOFCENTRALDIRDISK_SIZE = 4,
+		ENDOFCENTRALDIROFFSET_POS = NUMBEROFENDOFCENTRALDIRDISK_POS + NUMBEROFENDOFCENTRALDIRDISK_SIZE,
+		ENDOFCENTRALDIROFFSET_SIZE = 8,
+		TOTALNUMBEROFENDDISKS_POS = ENDOFCENTRALDIROFFSET_POS + ENDOFCENTRALDIROFFSET_SIZE,
+		TOTALNUMBEROFENDDISKS_SIZE = 4,
+			
+		FULL_LOCATOR_SIZE = 20
+	};
+
+	char           _rawInfo[FULL_HEADER_SIZE];
+	std::string     _extraField;
+	char            _locInfo[FULL_LOCATOR_SIZE];
+	std::streamoff _startPos;
+};
+
+
+//
+// inlines
+//
+
+
+inline Poco::UInt16 ZipArchiveInfo::getDiskNumber() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, NUMBEROFTHISDISK_POS);
+}
+
+
+inline Poco::UInt16 ZipArchiveInfo::getFirstDiskForDirectoryHeader() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, NUMBEROFCENTRALDIRDISK_POS);
+}
+
+
+inline Poco::UInt16 ZipArchiveInfo::getNumberOfEntries() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, NUMENTRIESTHISDISK_POS);
+}
+
+
+inline Poco::UInt16 ZipArchiveInfo::getTotalNumberOfEntries() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, TOTALNUMENTRIES_POS);
+}
+
+
+inline Poco::UInt32 ZipArchiveInfo::getCentralDirectorySize() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, CENTRALDIRSIZE_POS);
+}
+
+
+inline std::streamoff ZipArchiveInfo::getHeaderOffset() const
+{
+	return _startPos;
+}
+
+
+inline Poco::UInt16 ZipArchiveInfo::getZipCommentSize() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, ZIPCOMMENT_LENGTH_POS);
+}
+
+
+inline const std::string& ZipArchiveInfo::getZipComment() const
+{
+	return _comment;
+}
+
+
+inline void ZipArchiveInfo::setNumberOfEntries(Poco::UInt16 val)
+{
+	ZipUtil::set16BitValue(val, _rawInfo, NUMENTRIESTHISDISK_POS);
+}
+
+
+inline void ZipArchiveInfo::setTotalNumberOfEntries(Poco::UInt16 val)
+{
+	ZipUtil::set16BitValue(val, _rawInfo, TOTALNUMENTRIES_POS);
+}
+
+
+inline void ZipArchiveInfo::setCentralDirectorySize(Poco::UInt32 val)
+{
+	ZipUtil::set32BitValue(val, _rawInfo, CENTRALDIRSIZE_POS);
+}
+
+
+inline void ZipArchiveInfo::setCentralDirectoryOffset(Poco::UInt32 val)
+{
+	ZipUtil::set32BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS);
+}
+
+inline void ZipArchiveInfo::setHeaderOffset(std::streamoff val)
+{
+	_startPos = val;
+}
+
+
+inline Poco::UInt32 ZipArchiveInfo64::getDiskNumber() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, NUMBEROFTHISDISK_POS);
+}
+
+
+inline Poco::UInt32 ZipArchiveInfo64::getFirstDiskForDirectoryHeader() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, NUMBEROFCENTRALDIRDISK_POS);
+}
+
+
+inline Poco::UInt64 ZipArchiveInfo64::getNumberOfEntries() const
+{
+	return ZipUtil::get64BitValue(_rawInfo, NUMENTRIESTHISDISK_POS);
+}
+
+
+inline Poco::UInt64 ZipArchiveInfo64::getTotalNumberOfEntries() const
+{
+	return ZipUtil::get64BitValue(_rawInfo, TOTALNUMENTRIES_POS);
+}
+
+
+inline Poco::UInt64 ZipArchiveInfo64::getCentralDirectorySize() const
+{
+	return ZipUtil::get64BitValue(_rawInfo, CENTRALDIRSIZE_POS);
+}
+
+
+inline std::streamoff ZipArchiveInfo64::getCentralDirectoryOffset() const
+{
+	return _startPos;
+}
+
+
+inline std::streamoff ZipArchiveInfo64::getHeaderOffset() const
+{
+	return _startPos;
+}
+
+
+inline void ZipArchiveInfo64::setRequiredVersion(int major, int minor)
+{
+	poco_assert (minor < 10);
+	poco_assert (major < 24);
+	Poco::UInt8 val = static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor);
+	_rawInfo[VERSIONMADEBY_POS] = static_cast<char>(val);
+	_rawInfo[VERSION_NEEDED_POS] = static_cast<char>(val);
+}
+
+
+inline void ZipArchiveInfo64::setNumberOfEntries(Poco::UInt64 val)
+{
+	ZipUtil::set64BitValue(val, _rawInfo, NUMENTRIESTHISDISK_POS);
+}
+
+
+inline void ZipArchiveInfo64::setTotalNumberOfEntries(Poco::UInt64 val)
+{
+	ZipUtil::set64BitValue(val, _rawInfo, TOTALNUMENTRIES_POS);
+}
+
+
+inline void ZipArchiveInfo64::setCentralDirectorySize(Poco::UInt64 val)
+{
+	ZipUtil::set64BitValue(val, _rawInfo, CENTRALDIRSIZE_POS);
+}
+
+
+inline void ZipArchiveInfo64::setCentralDirectoryOffset(Poco::UInt64 val)
+{
+	ZipUtil::set64BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS);
+}
+
+
+inline void ZipArchiveInfo64::setHeaderOffset(std::streamoff val)
+{
+	_startPos = val;
+	ZipUtil::set64BitValue(val, _locInfo, ENDOFCENTRALDIROFFSET_POS);
+}
+
+
+inline void ZipArchiveInfo64::setTotalNumberOfDisks(Poco::UInt32 val)
+{
+	ZipUtil::set32BitValue(val, _locInfo, TOTALNUMBEROFENDDISKS_POS);
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipArchiveInfo_INCLUDED
diff --git a/Poco/Zip/ZipCommon.h b/Poco/Zip/ZipCommon.h
new file mode 100644
index 0000000..9fd45af
--- /dev/null
+++ b/Poco/Zip/ZipCommon.h
@@ -0,0 +1,104 @@
+//
+// ZipCommon.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipCommon
+//
+// Definition of the ZipCommon class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipCommon_INCLUDED
+#define Zip_ZipCommon_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API ZipCommon
+	/// Common enums used in the Zip project
+{
+public:
+	enum
+	{
+		HEADER_SIZE = 4
+	};
+
+	static const Poco::UInt16 ZIP64_EXTRA_ID	= 0x1;		  // Extra data id tag for Zip64 data (in extension for ZipLocalFileHeader and ZipFileInfo)
+	static const Poco::UInt16 ZIP64_MAGIC_SHORT = 0xFFFF;
+	static const Poco::UInt32 ZIP64_MAGIC		= 0xFFFFFFFF;
+
+	enum CompressionMethod
+	{
+		CM_STORE   = 0,
+		CM_SHRUNK  = 1,
+		CM_FACTOR1 = 2,
+		CM_FACTOR2 = 3,
+		CM_FACTOR3 = 4,
+		CM_FACTOR4 = 5,
+		CM_IMPLODE = 6,
+		CM_TOKENIZE= 7,
+		CM_DEFLATE = 8,
+		CM_ENHANCEDDEFLATE = 9,
+		CM_DATECOMPRIMPLODING = 10,
+		CM_UNUSED = 11,
+		CM_AUTO = 255 /// automatically select DM_DEFLATE or CM_STORE based on file type (extension)
+	};
+
+	enum CompressionLevel
+	{
+		CL_NORMAL    = 0,
+		CL_MAXIMUM   = 1,
+		CL_FAST      = 2,
+		CL_SUPERFAST = 3
+	};
+
+	enum HostSystem
+	{
+		HS_FAT = 0,  // + PKZIPW 2.50 VFAT, NTFS
+		HS_AMIGA = 1,
+		HS_VMS = 2,
+		HS_UNIX = 3,
+		HS_VM_CMS = 4,
+		HS_ATARI = 5,
+		HS_HPFS = 6,
+		HS_MACINTOSH = 7,
+		HS_ZSYSTEM = 8,
+		HS_CP_M = 9,
+		HS_TOPS20 = 10, // used by pkzip2.5 to indicate ntfs
+		HS_NTFS = 11,
+		HS_SMS_QDOS = 12,
+		HS_ACORN = 13,
+		HS_VFAT = 14,
+		HS_MVS = 15,
+		HS_BEOS = 16,
+		HS_TANDEM = 17,
+		HS_UNUSED = 18
+	};
+
+	enum FileType
+	{
+		FT_BINARY= 0,
+		FT_ASCII = 1
+	};
+
+	static bool isValidPath(const std::string& path);
+		/// Checks whether the given path is valid (does
+		/// not contain ".." path segments).
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipCommon_INCLUDED
diff --git a/Poco/Zip/ZipDataInfo.h b/Poco/Zip/ZipDataInfo.h
new file mode 100644
index 0000000..1d412b1
--- /dev/null
+++ b/Poco/Zip/ZipDataInfo.h
@@ -0,0 +1,248 @@
+//
+// ZipDataInfo.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipDataInfo
+//
+// Definition of the ZipDataInfo class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipDataInfo_INCLUDED
+#define Zip_ZipDataInfo_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipCommon.h"
+#include "Poco/Zip/ZipUtil.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API ZipDataInfo
+	/// A ZipDataInfo stores a Zip data descriptor
+{
+public:
+	static const char HEADER[ZipCommon::HEADER_SIZE];
+
+	ZipDataInfo();
+	/// Creates a header with all fields (except the header field) set to 0
+
+	ZipDataInfo(std::istream& in, bool assumeHeaderRead);
+		/// Creates the ZipDataInfo.
+
+	~ZipDataInfo();
+		/// Destroys the ZipDataInfo.
+
+	bool isValid() const;
+
+	Poco::UInt32 getCRC32() const;
+
+	void setCRC32(Poco::UInt32 crc);
+
+	Poco::UInt32 getCompressedSize() const;
+
+	void setCompressedSize(Poco::UInt32 size);
+
+	Poco::UInt32 getUncompressedSize() const;
+
+	void setUncompressedSize(Poco::UInt32 size);
+
+	static Poco::UInt32 getFullHeaderSize();
+
+	const char* getRawHeader() const;
+
+private:
+	enum
+	{
+		HEADER_POS = 0,
+		CRC32_POS  = HEADER_POS + ZipCommon::HEADER_SIZE,
+		CRC32_SIZE = 4,
+		COMPRESSED_POS = CRC32_POS + CRC32_SIZE,
+		COMPRESSED_SIZE = 4,
+		UNCOMPRESSED_POS = COMPRESSED_POS + COMPRESSED_SIZE,
+		UNCOMPRESSED_SIZE = 4,
+		FULLHEADER_SIZE = UNCOMPRESSED_POS + UNCOMPRESSED_SIZE
+	};
+
+	char _rawInfo[FULLHEADER_SIZE];
+	bool _valid;
+};
+
+
+class Zip_API ZipDataInfo64
+	/// A ZipDataInfo64 stores a Zip data descriptor for a Zip64 file
+{
+public:
+	static const char HEADER[ZipCommon::HEADER_SIZE];
+
+	ZipDataInfo64();
+	/// Creates a header with all fields (except the header field) set to 0
+
+	ZipDataInfo64(std::istream& in, bool assumeHeaderRead);
+		/// Creates the ZipDataInfo64.
+
+	~ZipDataInfo64();
+		/// Destroys the ZipDataInfo64.
+
+	bool isValid() const;
+
+	Poco::UInt32 getCRC32() const;
+
+	void setCRC32(Poco::UInt32 crc);
+
+	Poco::UInt64 getCompressedSize() const;
+
+	void setCompressedSize(Poco::UInt64 size);
+
+	Poco::UInt64 getUncompressedSize() const;
+
+	void setUncompressedSize(Poco::UInt64 size);
+
+	static Poco::UInt32 getFullHeaderSize();
+
+	const char* getRawHeader() const;
+
+private:
+	enum
+	{
+		HEADER_POS = 0,
+		CRC32_POS  = HEADER_POS + ZipCommon::HEADER_SIZE,
+		CRC32_SIZE = 4,
+		COMPRESSED_POS = CRC32_POS + CRC32_SIZE,
+		COMPRESSED_SIZE = 8,
+		UNCOMPRESSED_POS = COMPRESSED_POS + COMPRESSED_SIZE,
+		UNCOMPRESSED_SIZE = 8,
+		FULLHEADER_SIZE = UNCOMPRESSED_POS + UNCOMPRESSED_SIZE
+	};
+
+	char _rawInfo[FULLHEADER_SIZE];
+	bool _valid;
+};
+
+
+//
+// inlines
+//
+
+
+inline const char* ZipDataInfo::getRawHeader() const
+{
+	return _rawInfo;
+}
+
+
+inline bool ZipDataInfo::isValid() const
+{
+	return _valid;
+}
+
+
+inline Poco::UInt32 ZipDataInfo::getCRC32() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
+}
+
+
+inline void ZipDataInfo::setCRC32(Poco::UInt32 crc)
+{
+	return ZipUtil::set32BitValue(crc, _rawInfo, CRC32_POS);
+}
+
+
+inline Poco::UInt32 ZipDataInfo::getCompressedSize() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_POS);
+}
+
+
+inline void ZipDataInfo::setCompressedSize(Poco::UInt32 size)
+{
+	return ZipUtil::set32BitValue(size, _rawInfo, COMPRESSED_POS);
+}
+
+
+inline Poco::UInt32 ZipDataInfo::getUncompressedSize() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_POS);
+}
+
+
+inline void ZipDataInfo::setUncompressedSize(Poco::UInt32 size)
+{
+	return ZipUtil::set32BitValue(size, _rawInfo, UNCOMPRESSED_POS);
+}
+
+
+inline Poco::UInt32 ZipDataInfo::getFullHeaderSize()
+{
+	return FULLHEADER_SIZE;
+}
+
+
+inline const char* ZipDataInfo64::getRawHeader() const
+{
+	return _rawInfo;
+}
+
+
+inline bool ZipDataInfo64::isValid() const
+{
+	return _valid;
+}
+
+
+inline Poco::UInt32 ZipDataInfo64::getCRC32() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
+}
+
+
+inline void ZipDataInfo64::setCRC32(Poco::UInt32 crc)
+{
+	return ZipUtil::set32BitValue(crc, _rawInfo, CRC32_POS);
+}
+
+
+inline Poco::UInt64 ZipDataInfo64::getCompressedSize() const
+{
+	return ZipUtil::get64BitValue(_rawInfo, COMPRESSED_POS);
+}
+
+
+inline void ZipDataInfo64::setCompressedSize(Poco::UInt64 size)
+{
+	return ZipUtil::set64BitValue(size, _rawInfo, COMPRESSED_POS);
+}
+
+
+inline Poco::UInt64 ZipDataInfo64::getUncompressedSize() const
+{
+	return ZipUtil::get64BitValue(_rawInfo, UNCOMPRESSED_POS);
+}
+
+
+inline void ZipDataInfo64::setUncompressedSize(Poco::UInt64 size)
+{
+	return ZipUtil::set64BitValue(size, _rawInfo, UNCOMPRESSED_POS);
+}
+
+
+inline Poco::UInt32 ZipDataInfo64::getFullHeaderSize()
+{
+	return FULLHEADER_SIZE;
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipDataInfo_INCLUDED
diff --git a/Poco/Zip/ZipException.h b/Poco/Zip/ZipException.h
new file mode 100644
index 0000000..435c496
--- /dev/null
+++ b/Poco/Zip/ZipException.h
@@ -0,0 +1,36 @@
+//
+// ZipException.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipException
+//
+// Definition of the ZipException class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipException_INCLUDED
+#define Zip_ZipException_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+POCO_DECLARE_EXCEPTION(Zip_API, ZipException, Poco::RuntimeException)
+POCO_DECLARE_EXCEPTION(Zip_API, ZipManipulationException, ZipException)
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipException_INCLUDED
diff --git a/Poco/Zip/ZipFileInfo.h b/Poco/Zip/ZipFileInfo.h
new file mode 100644
index 0000000..2ea5073
--- /dev/null
+++ b/Poco/Zip/ZipFileInfo.h
@@ -0,0 +1,519 @@
+//
+// ZipFileInfo.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipFileInfo
+//
+// Definition of the ZipFileInfo class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipFileInfo_INCLUDED
+#define Zip_ZipFileInfo_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipCommon.h"
+#include "Poco/Zip/ZipUtil.h"
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ZipLocalFileHeader;
+
+
+class Zip_API ZipFileInfo
+	/// Stores a Zip directory entry of a file
+{
+public:
+	static const char HEADER[ZipCommon::HEADER_SIZE];
+
+	ZipFileInfo(const ZipLocalFileHeader& header);
+		/// Creates a ZipFileInfo from a ZipLocalFileHeader
+
+	ZipFileInfo(std::istream& in, bool assumeHeaderRead);
+		/// Creates the ZipFileInfo by parsing the input stream.
+		/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
+
+	~ZipFileInfo();
+		/// Destroys the ZipFileInfo.
+
+	ZipCommon::CompressionMethod getCompressionMethod() const;
+
+	bool isEncrypted() const;
+
+	const Poco::DateTime& lastModifiedAt() const;
+
+	Poco::UInt32 getCRC() const;
+
+	Poco::UInt32 getHeaderSize() const;
+		/// Returns the total size of the header including filename + other additional fields
+
+	Poco::UInt64 getCompressedSize() const;
+
+	Poco::UInt64 getUncompressedSize() const;
+
+	Poco::UInt64 getOffset() const;
+		/// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
+
+	const std::string& getFileName() const;
+
+	bool isFile() const;
+
+	bool isDirectory() const;
+
+	bool hasExtraField() const;
+
+	const std::string& getExtraField() const;
+
+	const std::string& getFileComment() const;
+
+	void getVersionMadeBy(int& major, int& minor) const;
+		/// The ZIP version used to create the file
+
+	void getRequiredVersion(int& major, int& minor) const;
+		/// The minimum version required to extract the data
+
+	ZipCommon::HostSystem getHostSystem() const;
+
+	Poco::UInt16 getDiskNumberStart() const;
+		/// The number of the disk on which this file begins (multidisk archives)
+
+	ZipCommon::FileType getFileType() const;
+		/// Binary or ASCII file?
+
+	std::string createHeader() const;
+
+	void setOffset(Poco::UInt64 val);
+
+	bool needsZip64() const;
+
+	void setZip64Data();
+
+private:
+
+	void setCRC(Poco::UInt32 val);
+
+	void setCompressedSize(Poco::UInt64 val);
+
+	void setUncompressedSize(Poco::UInt64 val);
+
+	void setCompressionMethod(ZipCommon::CompressionMethod cm);
+
+	void setCompressionLevel(ZipCommon::CompressionLevel cl);
+
+	void setRequiredVersion(int major, int minor);
+
+	void setHostSystem(ZipCommon::HostSystem hs);
+
+	void setLastModifiedAt(const Poco::DateTime& dt);
+
+	void setEncryption(bool val);
+
+	void setFileNameLength(Poco::UInt16 size);
+
+	void setFileName(const std::string& str);
+	
+	void setExternalFileAttributes(Poco::UInt32 attrs);
+
+	void parse(std::istream& in, bool assumeHeaderRead);
+
+	void parseDateTime();
+
+	Poco::UInt32 getCRCFromHeader() const;
+
+	Poco::UInt32 getCompressedSizeFromHeader() const;
+
+	Poco::UInt32 getUncompressedSizeFromHeader() const;
+
+	Poco::UInt32 getOffsetFromHeader() const;
+
+	Poco::UInt16 getFileNameLength() const;
+
+	Poco::UInt16 getExtraFieldLength() const;
+
+	Poco::UInt16 getFileCommentLength() const;
+
+	Poco::UInt32 getExternalFileAttributes() const;
+	
+	void setUnixAttributes();
+
+private:
+	enum
+	{
+		HEADER_POS = 0,
+		VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
+		VERSIONMADEBY_SIZE = 2,
+		VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
+		VERSION_NEEDED_SIZE = 2,
+		GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
+		GENERAL_PURPOSE_SIZE = 2,
+		COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE,
+		COMPR_METHOD_SIZE = 2,
+		LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE,
+		LASTMODFILETIME_SIZE = 2,
+		LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE,
+		LASTMODFILEDATE_SIZE = 2,
+		CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE,
+		CRC32_SIZE = 4,
+		COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
+		COMPRESSED_SIZE_SIZE = 4,
+		UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
+		UNCOMPRESSED_SIZE_SIZE = 4,
+		FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
+		FILENAME_LENGTH_SIZE = 2,
+		EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE,
+		EXTRAFIELD_LENGTH_SIZE = 2,
+		FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE,
+		FILECOMMENT_LENGTH_SIZE = 2,
+		DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE,
+		DISKNUMBERSTART_SIZE = 2,
+		INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE,
+		INTERNALFILE_ATTR_SIZE = 2,
+		EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE,
+		EXTERNALFILE_ATTR_SIZE = 4,
+		RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE,
+		RELATIVEOFFSETLOCALHEADER_SIZE = 4,
+		FULLHEADER_SIZE = 46,
+
+		EXTRA_DATA_TAG_SIZE = 2,
+		EXTRA_DATA_TAG_POS = 0,
+		EXTRA_DATA_SIZE_SIZE = 2,
+		EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE,
+		EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE,
+		EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8,
+		EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8,
+		EXTRA_DATA_OFFSET_SIZE = 8,
+		FULLEXTRA_DATA_SIZE = 28
+	};
+	
+	enum 
+	{
+		DEFAULT_UNIX_FILE_MODE = 0640,
+		DEFAULT_UNIX_DIR_MODE  = 0755
+	};
+
+	char           _rawInfo[FULLHEADER_SIZE];
+	Poco::UInt32   _crc32;
+	Poco::UInt64   _compressedSize;
+	Poco::UInt64   _uncompressedSize;
+	Poco::UInt64   _localHeaderOffset;
+	std::string    _fileName;
+	Poco::DateTime _lastModifiedAt;
+	std::string    _extraField;
+	std::string    _fileComment;
+};
+
+
+inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
+}
+
+
+inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS);
+}
+
+
+inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
+}
+
+inline Poco::UInt32 ZipFileInfo::getOffsetFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
+}
+
+
+inline void ZipFileInfo::parseDateTime()
+{
+	_lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
+}
+
+
+inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const
+{
+	return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS));
+}
+
+
+inline bool ZipFileInfo::isEncrypted() const
+{
+	// bit 0 indicates encryption
+	return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0);
+}
+
+
+inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const
+{
+	return _lastModifiedAt;
+}
+
+
+inline Poco::UInt64 ZipFileInfo::getOffset() const
+{
+	return _localHeaderOffset;
+}
+
+
+inline Poco::UInt32 ZipFileInfo::getCRC() const
+{
+	return _crc32;
+}
+
+
+inline Poco::UInt64 ZipFileInfo::getCompressedSize() const
+{
+	return _compressedSize;
+}
+
+
+inline Poco::UInt64 ZipFileInfo::getUncompressedSize() const
+{
+	return _uncompressedSize;
+}
+
+
+inline const std::string& ZipFileInfo::getFileName() const
+{
+	return _fileName;
+}
+
+
+inline bool ZipFileInfo::isFile() const
+{
+	return !isDirectory();
+}
+
+
+inline bool ZipFileInfo::isDirectory() const
+{
+	poco_assert_dbg(!_fileName.empty());
+	return getUncompressedSize() == 0 && _fileName[_fileName.length()-1] == '/';
+}
+
+
+inline Poco::UInt16 ZipFileInfo::getFileNameLength() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS);
+}
+
+
+inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS);
+}
+
+
+inline bool ZipFileInfo::hasExtraField() const
+{
+	return getExtraFieldLength() > 0;
+}
+
+
+inline const std::string& ZipFileInfo::getExtraField() const
+{
+	return _extraField;
+}
+
+
+inline const std::string& ZipFileInfo::getFileComment() const
+{
+	return _fileComment;
+}
+
+
+inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS);
+}
+
+
+inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor) const
+{
+	major = (_rawInfo[VERSIONMADEBY_POS]/10);
+	minor = (_rawInfo[VERSIONMADEBY_POS]%10);
+}
+
+
+inline void ZipFileInfo::getRequiredVersion(int& major, int& minor) const
+{
+	major = (_rawInfo[VERSION_NEEDED_POS]/10);
+	minor = (_rawInfo[VERSION_NEEDED_POS]%10);
+}
+
+
+inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const
+{
+	return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]);
+}
+
+
+inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const
+{
+	return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS);
+}
+
+
+inline ZipCommon::FileType ZipFileInfo::getFileType() const
+{
+	return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01);
+}
+
+
+inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const
+{
+	return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS);
+}
+
+
+inline Poco::UInt32 ZipFileInfo::getHeaderSize() const
+{
+	return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
+}
+
+
+inline bool ZipFileInfo::needsZip64() const
+{
+	return _localHeaderOffset >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC;
+}
+
+
+inline void ZipFileInfo::setZip64Data()
+{
+	if (needsZip64())
+	{
+		setRequiredVersion(4, 5);
+		char data[FULLEXTRA_DATA_SIZE];
+		ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS);
+		Poco::UInt16 pos = EXTRA_DATA_POS;
+		if (_uncompressedSize >= ZipCommon::ZIP64_MAGIC)
+		{
+			ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8;
+		}
+		if (_compressedSize >= ZipCommon::ZIP64_MAGIC)
+		{
+			ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8;
+		}
+		if (_localHeaderOffset >= ZipCommon::ZIP64_MAGIC)
+		{
+			ZipUtil::set64BitValue(_localHeaderOffset, data, pos); pos += 8;
+		}
+		ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS);
+		_extraField = std::string(data, pos);
+		ZipUtil::set16BitValue(pos, _rawInfo, EXTRAFIELD_LENGTH_POS);
+	}
+}
+
+
+inline void ZipFileInfo::setCRC(Poco::UInt32 val)
+{
+	_crc32 = val;
+	ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS);
+}
+
+
+inline void ZipFileInfo::setOffset(Poco::UInt64 val)
+{
+	_localHeaderOffset = val;
+	ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
+}
+
+
+inline void ZipFileInfo::setCompressedSize(Poco::UInt64 val)
+{
+	_compressedSize = val;
+	ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, COMPRESSED_SIZE_POS);
+}
+
+
+inline void ZipFileInfo::setUncompressedSize(Poco::UInt64 val)
+{
+	_uncompressedSize = val;
+	ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, UNCOMPRESSED_SIZE_POS);
+}
+
+
+inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm)
+{
+	ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS);
+}
+
+
+inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl)
+{
+	// bit 1 and 2 indicate the level
+	Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
+	val <<= 1; 
+	Poco::UInt16 mask = 0xfff9;
+	_rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val);
+}
+
+
+inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size)
+{
+	ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS);
+}
+
+
+inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs)
+{
+	_rawInfo[VERSIONMADEBY_POS + 1] = static_cast<char>(hs);
+	_rawInfo[VERSION_NEEDED_POS + 1] = static_cast<char>(hs);
+}
+
+
+inline void ZipFileInfo::setRequiredVersion(int major, int minor)
+{
+	poco_assert (minor < 10);
+	poco_assert (major < 24);
+	Poco::UInt8 val = static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor);
+	_rawInfo[VERSIONMADEBY_POS] = static_cast<char>(val);
+	_rawInfo[VERSION_NEEDED_POS] = static_cast<char>(val);
+}
+
+
+inline void ZipFileInfo::setLastModifiedAt(const Poco::DateTime& dt)
+{
+	_lastModifiedAt = dt;
+	ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
+}
+
+
+inline void ZipFileInfo::setEncryption(bool val)
+{
+	if (val)
+		_rawInfo[GENERAL_PURPOSE_POS] |= 0x01;
+	else
+		_rawInfo[GENERAL_PURPOSE_POS] &= 0xfe;
+}
+
+
+inline void ZipFileInfo::setFileName(const std::string& str)
+{
+	_fileName = str;
+	setFileNameLength(static_cast<Poco::UInt16>(str.size()));
+}
+
+
+inline void ZipFileInfo::setExternalFileAttributes(Poco::UInt32 attrs)
+{
+	ZipUtil::set32BitValue(attrs, _rawInfo, EXTERNALFILE_ATTR_POS);
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipFileInfo_INCLUDED
diff --git a/Poco/Zip/ZipLocalFileHeader.h b/Poco/Zip/ZipLocalFileHeader.h
new file mode 100644
index 0000000..48b07cd
--- /dev/null
+++ b/Poco/Zip/ZipLocalFileHeader.h
@@ -0,0 +1,513 @@
+//
+// ZipLocalFileHeader.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipLocalFileHeader
+//
+// Definition of the ZipLocalFileHeader class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipLocalFileHeader_INCLUDED
+#define Zip_ZipLocalFileHeader_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipUtil.h"
+#include "Poco/Zip/ZipCommon.h"
+#include "Poco/DateTime.h"
+#include "Poco/Path.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ParseCallback;
+
+
+class Zip_API ZipLocalFileHeader
+	/// Stores a Zip local file header
+{
+public:
+	static const char HEADER[ZipCommon::HEADER_SIZE];
+
+	ZipLocalFileHeader(const Poco::Path& fileName, const Poco::DateTime& lastModifiedAt, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl, bool forceZip64 = false);
+		/// Creates a zip file header from an absoluteFile. fileName is the name of the file in the zip, outputIsSeekable determines if we write
+		/// CRC and file sizes to the LocalFileHeader or after data compression into a ZipDataInfo
+		/// If forceZip64 is set true then the file header is allocated with zip64 extension.
+
+	ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback);
+		/// Creates the ZipLocalFileHeader by parsing the input stream.
+		/// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
+		/// If skipOverDataBlock is true we position the stream after the data block (either at the next FileHeader or the Directory Entry)
+
+	virtual ~ZipLocalFileHeader();
+		/// Destroys the ZipLocalFileHeader.
+
+	ZipCommon::HostSystem getHostSystem() const;
+
+	int getMajorVersionNumber() const;
+
+	int getMinorVersionNumber() const;
+
+	void getRequiredVersion(int& major, int& minor);
+		/// The minimum version required to extract the data
+
+	Poco::UInt32 getHeaderSize() const;
+		/// Returns the total size of the header including filename + extra field size
+
+	void setStartPos(std::streamoff start);
+		/// Sets the start position to start and the end position to start+compressedSize
+
+	std::streamoff getStartPos() const;
+		/// Returns the position of the first byte of the header in the file stream
+
+	std::streamoff getEndPos() const;
+		/// Points past the last byte of the file entry (ie. either the first byte of the next header, or the directory)
+
+	std::streamoff getDataStartPos() const;
+		/// Returns the streamoffset for the very first byte of data. Will be equal to DataEndPos if no data present
+
+	std::streamoff getDataEndPos() const;
+
+	ZipCommon::CompressionMethod getCompressionMethod() const;
+
+	ZipCommon::CompressionLevel getCompressionLevel() const;
+	/// Returns the compression level used. Only valid when the compression method is CM_DEFLATE
+
+	bool isEncrypted() const;
+
+	bool hasSupportedCompressionMethod() const;
+
+	const Poco::DateTime& lastModifiedAt() const;
+
+	Poco::UInt32 getCRC() const;
+
+	Poco::UInt64 getCompressedSize() const;
+
+	Poco::UInt64 getUncompressedSize() const;
+
+	void setCRC(Poco::UInt32 val);
+
+	void setCompressedSize(Poco::UInt64 val);
+
+	void setUncompressedSize(Poco::UInt64 val);
+
+	const std::string& getFileName() const;
+
+	bool isFile() const;
+
+	bool isDirectory() const;
+
+	bool hasExtraField() const;
+
+	const std::string& getExtraField() const;
+
+	bool hasData() const;
+
+	bool searchCRCAndSizesAfterData() const;
+
+	void setSearchCRCAndSizesAfterData(bool val);
+
+	void setFileName(const std::string& fileName, bool isDirectory);
+
+	bool needsZip64() const;
+
+	void setZip64Data();
+
+	std::string createHeader() const;
+		/// Creates a header
+
+private:
+	void parse(std::istream& inp, bool assumeHeaderRead);
+
+	void parseDateTime();
+
+	void init(const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl);
+
+	Poco::UInt16 getFileNameLength() const;
+
+	Poco::UInt16 getExtraFieldLength() const;
+
+	Poco::UInt32 getCRCFromHeader() const;
+
+	Poco::UInt32 getCompressedSizeFromHeader() const;
+
+	Poco::UInt32 getUncompressedSizeFromHeader() const;
+
+	void setRequiredVersion(int major, int minor);
+
+	void setHostSystem(ZipCommon::HostSystem hs);
+
+	void setLastModifiedAt(const Poco::DateTime& dt);
+
+	void setEncryption(bool val);
+
+	void setFileNameLength(Poco::UInt16 size);
+
+	void setExtraFieldSize(Poco::UInt16 size);
+
+	void setCompressionMethod(ZipCommon::CompressionMethod cm);
+
+	void setCompressionLevel(ZipCommon::CompressionLevel cl);
+
+private:
+	enum
+	{
+		HEADER_POS = 0,
+		VERSION_SIZE = 2,
+		VERSION_POS = HEADER_POS+ZipCommon::HEADER_SIZE,
+		GENERAL_PURPOSE_SIZE = 2,
+		GENERAL_PURPOSE_POS = VERSION_POS + VERSION_SIZE,
+		COMPR_METHOD_SIZE = 2,
+		COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE,
+		LASTMODEFILETIME_SIZE = 2,
+		LASTMODEFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE,
+		LASTMODEFILEDATE_SIZE = 2,
+		LASTMODEFILEDATE_POS = LASTMODEFILETIME_POS + LASTMODEFILETIME_SIZE,
+		CRC32_SIZE = 4,
+		CRC32_POS = LASTMODEFILEDATE_POS + LASTMODEFILEDATE_SIZE,
+		COMPRESSED_SIZE_SIZE = 4,
+		COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
+		UNCOMPRESSED_SIZE_SIZE = 4,
+		UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
+		FILE_LENGTH_SIZE = 2,
+		FILE_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
+		EXTRA_FIELD_LENGTH = 2,
+		EXTRA_FIELD_POS = FILE_LENGTH_POS + FILE_LENGTH_SIZE,
+		FULLHEADER_SIZE = 30,
+
+		EXTRA_DATA_TAG_SIZE = 2,
+		EXTRA_DATA_TAG_POS = 0,
+		EXTRA_DATA_SIZE_SIZE = 2,
+		EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE,
+		EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE,
+		EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8,
+		EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8,
+		FULLEXTRA_DATA_SIZE = 20
+	};
+
+	bool		   _forceZip64;
+	char           _rawHeader[FULLHEADER_SIZE];
+	std::streamoff _startPos;
+	std::streamoff _endPos;
+	std::string    _fileName;
+	Poco::DateTime _lastModifiedAt;
+	std::string    _extraField;
+	Poco::UInt32   _crc32;
+	Poco::UInt64   _compressedSize;
+	Poco::UInt64   _uncompressedSize;
+
+	friend class ZipStreamBuf;
+};
+
+
+inline void ZipLocalFileHeader::setFileNameLength(Poco::UInt16 size)
+{
+	ZipUtil::set16BitValue(size, _rawHeader, FILE_LENGTH_POS);
+}
+
+
+inline void ZipLocalFileHeader::setExtraFieldSize(Poco::UInt16 size)
+{
+	ZipUtil::set16BitValue(size, _rawHeader, EXTRA_FIELD_POS);
+}
+
+
+inline ZipCommon::HostSystem ZipLocalFileHeader::getHostSystem() const
+{
+	return static_cast<ZipCommon::HostSystem>(_rawHeader[VERSION_POS + 1]);
+}
+
+
+inline void ZipLocalFileHeader::setHostSystem(ZipCommon::HostSystem hs)
+{
+	_rawHeader[VERSION_POS + 1] = static_cast<char>(hs);
+}
+
+
+inline int ZipLocalFileHeader::getMajorVersionNumber() const
+{
+	return (_rawHeader[VERSION_POS]/10);
+}
+
+
+inline int ZipLocalFileHeader::getMinorVersionNumber() const
+{
+	return (_rawHeader[VERSION_POS]%10);
+}
+
+
+inline void ZipLocalFileHeader::getRequiredVersion(int& major, int& minor)
+{
+	major = getMajorVersionNumber();
+	minor = getMinorVersionNumber();
+}
+
+
+inline bool ZipLocalFileHeader::needsZip64() const
+{
+	return _forceZip64 || _startPos >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC;
+}
+
+
+inline void ZipLocalFileHeader::setZip64Data()
+{
+	setRequiredVersion(4, 5);
+	char data[FULLEXTRA_DATA_SIZE];
+	ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS);
+	Poco::UInt16 pos = EXTRA_DATA_POS;
+	ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8;
+	ZipUtil::set32BitValue(ZipCommon::ZIP64_MAGIC, _rawHeader, UNCOMPRESSED_SIZE_POS);
+	ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8;
+	ZipUtil::set32BitValue(ZipCommon::ZIP64_MAGIC, _rawHeader, COMPRESSED_SIZE_POS);
+	ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS);
+	_extraField = std::string(data, pos);
+	ZipUtil::set16BitValue(pos, _rawHeader, EXTRA_FIELD_POS);
+}
+
+
+inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor)
+{
+	poco_assert (minor < 10);
+	poco_assert (major < 24);
+	_rawHeader[VERSION_POS] = static_cast<char>(static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor));
+}
+
+
+inline Poco::UInt16 ZipLocalFileHeader::getFileNameLength() const
+{
+	return ZipUtil::get16BitValue(_rawHeader, FILE_LENGTH_POS);
+}
+
+
+inline Poco::UInt16 ZipLocalFileHeader::getExtraFieldLength() const
+{
+	return ZipUtil::get16BitValue(_rawHeader, EXTRA_FIELD_POS);
+}
+
+
+inline Poco::UInt32 ZipLocalFileHeader::getHeaderSize() const
+{
+	return FULLHEADER_SIZE+getExtraFieldLength()+getFileNameLength();
+}
+
+
+inline std::streamoff ZipLocalFileHeader::getStartPos() const
+{
+	return _startPos;
+}
+
+
+inline void ZipLocalFileHeader::setStartPos(std::streamoff start)
+{
+	_startPos = start;
+	_endPos = start + getHeaderSize()+static_cast<std::streamoff>(getCompressedSize());
+}
+
+
+inline std::streamoff ZipLocalFileHeader::getEndPos() const
+{
+	return _endPos;
+}
+
+
+inline void ZipLocalFileHeader::parseDateTime()
+{
+	_lastModifiedAt = ZipUtil::parseDateTime(_rawHeader, LASTMODEFILETIME_POS, LASTMODEFILEDATE_POS);
+}
+
+
+inline void ZipLocalFileHeader::setLastModifiedAt(const Poco::DateTime& dt)
+{
+	_lastModifiedAt = dt;
+	ZipUtil::setDateTime(dt, _rawHeader, LASTMODEFILETIME_POS, LASTMODEFILEDATE_POS);
+}
+
+
+inline ZipCommon::CompressionMethod ZipLocalFileHeader::getCompressionMethod() const
+{
+	return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS));
+}
+
+
+inline ZipCommon::CompressionLevel ZipLocalFileHeader::getCompressionLevel() const
+{
+	// bit 1 and 2 indicate the level
+	return static_cast<ZipCommon::CompressionLevel>((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS)>>1) & 0x0003);
+}
+
+
+inline void ZipLocalFileHeader::setCompressionMethod(ZipCommon::CompressionMethod cm)
+{
+	ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawHeader, COMPR_METHOD_POS);
+}
+
+
+inline void ZipLocalFileHeader::setCompressionLevel(ZipCommon::CompressionLevel cl)
+{
+	// bit 1 and 2 indicate the level
+	Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
+	val <<= 1;
+	Poco::UInt16 mask = 0xfff9;
+	_rawHeader[GENERAL_PURPOSE_POS] = ((_rawHeader[GENERAL_PURPOSE_POS] & mask) | val);
+}
+
+
+inline bool ZipLocalFileHeader::isEncrypted() const
+{
+	// bit 0 indicates encryption
+	return ((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS) & 0x0001) != 0);
+}
+
+
+inline bool ZipLocalFileHeader::hasSupportedCompressionMethod() const
+{
+	ZipCommon::CompressionMethod method = getCompressionMethod();
+	return method == ZipCommon::CM_DEFLATE || method == ZipCommon::CM_STORE;
+}
+
+
+inline void ZipLocalFileHeader::setEncryption(bool val)
+{
+	if (val)
+		_rawHeader[GENERAL_PURPOSE_POS] |= 0x01;
+	else
+		_rawHeader[GENERAL_PURPOSE_POS] &= 0xfe;
+}
+
+
+inline void ZipLocalFileHeader::setSearchCRCAndSizesAfterData(bool val)
+{
+	//set bit 3 of general purpose reg
+	if (val)
+		_rawHeader[GENERAL_PURPOSE_POS] |= 0x08;
+	else
+		_rawHeader[GENERAL_PURPOSE_POS] &= 0xf7;
+}
+
+
+inline const Poco::DateTime& ZipLocalFileHeader::lastModifiedAt() const
+{
+	return _lastModifiedAt;
+}
+
+
+inline Poco::UInt32 ZipLocalFileHeader::getCRC() const
+{
+	return _crc32;
+}
+
+
+inline Poco::UInt64 ZipLocalFileHeader::getCompressedSize() const
+{
+	return _compressedSize;
+}
+
+
+inline Poco::UInt64 ZipLocalFileHeader::getUncompressedSize() const
+{
+	return _uncompressedSize;
+}
+
+
+inline void ZipLocalFileHeader::setCRC(Poco::UInt32 val)
+{
+	_crc32 = val;
+	ZipUtil::set32BitValue(val, _rawHeader, CRC32_POS);
+}
+
+
+inline void ZipLocalFileHeader::setCompressedSize(Poco::UInt64 val)
+{
+	_compressedSize = val;
+	ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawHeader, COMPRESSED_SIZE_POS);
+}
+
+
+inline void ZipLocalFileHeader::setUncompressedSize(Poco::UInt64 val)
+{
+	_uncompressedSize = val;
+	ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawHeader, UNCOMPRESSED_SIZE_POS);
+}
+
+
+inline Poco::UInt32 ZipLocalFileHeader::getCRCFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawHeader, CRC32_POS);
+}
+
+
+inline Poco::UInt32 ZipLocalFileHeader::getCompressedSizeFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawHeader, COMPRESSED_SIZE_POS);
+}
+
+
+inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSizeFromHeader() const
+{
+	return ZipUtil::get32BitValue(_rawHeader, UNCOMPRESSED_SIZE_POS);
+}
+
+
+inline const std::string& ZipLocalFileHeader::getFileName() const
+{
+	return _fileName;
+}
+
+
+inline bool ZipLocalFileHeader::isFile() const
+{
+	return !isDirectory();
+}
+
+
+inline bool ZipLocalFileHeader::isDirectory() const
+{
+	poco_assert_dbg(!_fileName.empty());
+	return getUncompressedSize() == 0 && _fileName[_fileName.length()-1] == '/';
+}
+
+
+inline bool ZipLocalFileHeader::hasExtraField() const
+{
+	return getExtraFieldLength() > 0;
+}
+
+
+inline const std::string& ZipLocalFileHeader::getExtraField() const
+{
+	return _extraField;
+}
+
+
+inline bool ZipLocalFileHeader::hasData() const
+{
+	return (getCompressedSize() > 0);
+}
+
+
+inline std::streamoff ZipLocalFileHeader::getDataStartPos() const
+{
+	return getStartPos() + getHeaderSize();
+}
+
+
+inline std::streamoff ZipLocalFileHeader::getDataEndPos() const
+{
+	return getDataStartPos()+static_cast<std::streamoff>(getCompressedSize());
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipLocalFileHeader_INCLUDED
diff --git a/Poco/Zip/ZipManipulator.h b/Poco/Zip/ZipManipulator.h
new file mode 100644
index 0000000..0e7e6e0
--- /dev/null
+++ b/Poco/Zip/ZipManipulator.h
@@ -0,0 +1,109 @@
+//
+// ZipManipulator.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  ZipManipulator
+//
+// Definition of the ZipManipulator class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipManipulator_INCLUDED
+#define Zip_ZipManipulator_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipArchive.h"
+#include "Poco/Zip/ZipCommon.h"
+#include "Poco/Zip/ZipOperation.h"
+#include "Poco/FIFOEvent.h"
+#include "Poco/SharedPtr.h"
+#include <map>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ZipArchive;
+
+
+class Zip_API ZipManipulator
+	/// ZipManipulator allows to add/remove/update files inside zip files
+{
+public:
+	Poco::FIFOEvent<const ZipLocalFileHeader> EDone;
+		// Fired for each entry once commit is invoked
+
+	ZipManipulator(const std::string& zipFile, bool backupOriginalFile);
+		/// Creates the ZipManipulator.
+
+	virtual ~ZipManipulator();
+		/// Destroys the ZipManipulator.
+
+	void deleteFile(const std::string& zipPath);
+		/// Removes the given file from the Zip archive.
+
+	void replaceFile(const std::string& zipPath, const std::string& localPath);
+		/// Replaces the contents of the file in the archive with the contents
+		/// from the file given by localPath.
+
+	void renameFile(const std::string& zipPath, const std::string& newZipPath);
+		/// Renames the file in the archive to newZipPath
+
+	void addFile(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM);
+		/// Adds a file to the zip file.
+
+	ZipArchive commit();
+		/// Commits all changes and re-creates the Zip File with the changes applied. 
+		/// Returns the ZipArchive for the newly created archive
+		///
+		/// Changes will be first written to a temporary file, 
+		/// then the originalfile will be either deleted or renamed to .bak,
+		/// then, the temp file will be renamed to the original zip file name.
+
+	const ZipArchive& originalArchive() const;
+		/// Returns the original archive information
+
+private:
+	const ZipLocalFileHeader& getForChange(const std::string& zipPath) const;
+		/// Searches for the entry given by the zipPath.
+		/// Throws an exception if the entry does not exist
+		/// or if an entry already exists in the Changeslist
+
+	void addOperation(const std::string& zipPath, ZipOperation::Ptr ptrOp);
+		/// Adds the operation to the changes list. Throws an exception if an
+		/// entry for the zipPath already exists
+
+	void onEDone(const void* pSender, const ZipLocalFileHeader& hdr);
+		/// Forwards the event to the EDone event
+
+	ZipArchive compress(const std::string& outFile);
+		/// Compresses the new file to outFile
+
+private:
+	typedef std::map<std::string, ZipOperation::Ptr> Changes;
+
+	const std::string _zipFile;
+	bool              _backupOriginalFile;
+	Changes           _changes;
+	Poco::SharedPtr<ZipArchive>        _in;
+};
+
+
+inline const ZipArchive& ZipManipulator::originalArchive() const
+{
+	return *_in;
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipManipulator_INCLUDED
diff --git a/Poco/Zip/ZipOperation.h b/Poco/Zip/ZipOperation.h
new file mode 100644
index 0000000..8825ff5
--- /dev/null
+++ b/Poco/Zip/ZipOperation.h
@@ -0,0 +1,56 @@
+//
+// ZipOperation.h
+//
+// Library: Zip
+// Package: Manipulation
+// Module:  ZipOperation
+//
+// Definition of the ZipOperation class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipOperation_INCLUDED
+#define Zip_ZipOperation_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/RefCountedObject.h"
+#include "Poco/AutoPtr.h"
+#include <ostream>
+#include <istream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Compress;
+
+
+class Zip_API ZipOperation: public Poco::RefCountedObject
+	/// Abstract super class for operations on individual zip entries
+{
+public:
+	typedef Poco::AutoPtr<ZipOperation> Ptr;
+
+	ZipOperation();
+		/// Creates the ZipOperation.
+
+	virtual void execute(Compress& c, std::istream& input) = 0;
+		/// Executes the operation
+
+protected:
+	virtual ~ZipOperation();
+		/// Destroys the ZipOperation.
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipOperation_INCLUDED
diff --git a/Poco/Zip/ZipStream.h b/Poco/Zip/ZipStream.h
new file mode 100644
index 0000000..bd26daa
--- /dev/null
+++ b/Poco/Zip/ZipStream.h
@@ -0,0 +1,149 @@
+//
+// ZipStream.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipStream
+//
+// Definition of the ZipStream class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipStream_INCLUDED
+#define Zip_ZipStream_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/PartialStream.h"
+#include "Poco/SharedPtr.h"
+#include "Poco/BufferedStreamBuf.h"
+#include "Poco/Checksum.h"
+#include <istream>
+#include <ostream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class ZipArchive;
+class ZipLocalFileHeader;
+
+
+class Zip_API ZipStreamBuf: public Poco::BufferedStreamBuf
+	/// ZipStreamBuf is used to decompress single files from a Zip file.
+{
+public:
+	ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition);
+		/// Creates the ZipStreamBuf. Set reposition to false, if you do on-the-fly decompression.
+	
+	ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition);
+		/// Creates the ZipStreamBuf. Set reposition to false, if you do on-the-fly compression.
+
+	virtual ~ZipStreamBuf();
+		/// Destroys the ZipStreamBuf.
+
+	void close(Poco::UInt64& extraDataSize);
+		/// Informs a writing outputstream that writing is done for this stream
+
+	bool crcValid() const;
+		/// Call this method once all bytes were read from the input stream to determine if the CRC is valid
+
+protected:
+	int readFromDevice(char* buffer, std::streamsize length);
+
+	int writeToDevice(const char* buffer, std::streamsize length);
+
+private:
+	enum
+	{
+		STREAM_BUFFER_SIZE = 1024
+	};
+
+	typedef Poco::SharedPtr<std::istream> PtrIStream;
+	typedef Poco::SharedPtr<std::ostream> PtrOStream;
+	std::istream*  _pIstr;
+	std::ostream*  _pOstr;
+	PtrIStream     _ptrBuf;
+	PtrOStream     _ptrOBuf;
+	PtrIStream     _ptrHelper;
+	Poco::SharedPtr<PartialOutputStream> _ptrOHelper;
+	Poco::Checksum _crc32;
+	Poco::UInt32   _expectedCrc32;
+	bool           _checkCRC;
+		/// Note: we do not check crc if we decompress a streaming zip file and the crc is stored in the directory header
+	Poco::UInt64   _bytesWritten;
+	ZipLocalFileHeader* _pHeader;
+};
+
+
+class Zip_API ZipIOS: public virtual std::ios
+	/// The base class for ZipInputStream and ZipOutputStream.
+	///
+	/// This class is needed to ensure the correct initialization
+	/// order of the stream buffer and base classes.
+{
+public:
+	ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition);
+		/// Creates the basic stream and connects it
+		/// to the given input stream.
+
+	ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition);
+		/// Creates the basic stream and connects it
+		/// to the given output stream.
+
+	~ZipIOS();
+		/// Destroys the stream.
+
+	ZipStreamBuf* rdbuf();
+		/// Returns a pointer to the underlying streambuf.
+
+protected:
+	ZipStreamBuf _buf;
+};
+
+
+class Zip_API ZipInputStream: public ZipIOS, public std::istream
+	/// This stream copies all characters read through it
+	/// to one or multiple output streams.
+{
+public:
+	ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition = true);
+		/// Creates the ZipInputStream and connects it
+		/// to the given input stream.
+
+	~ZipInputStream();
+		/// Destroys the ZipInputStream.
+
+	bool crcValid() const;
+		/// Call this method once all bytes were read from the input stream to determine if the CRC is valid
+};
+
+
+
+class Zip_API ZipOutputStream: public ZipIOS, public std::ostream
+	/// This stream compresses all characters written through it
+	/// to one output stream.
+{
+public:
+	ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput);
+		/// Creates the ZipOutputStream and connects it
+		/// to the given output stream.
+
+	~ZipOutputStream();
+		/// Destroys the ZipOutputStream.
+
+	void close(Poco::UInt64& extraDataSize);
+		/// Must be called for ZipOutputStreams!
+};
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipStream_INCLUDED
diff --git a/Poco/Zip/ZipUtil.h b/Poco/Zip/ZipUtil.h
new file mode 100644
index 0000000..6ac74ad
--- /dev/null
+++ b/Poco/Zip/ZipUtil.h
@@ -0,0 +1,126 @@
+//
+// ZipUtil.h
+//
+// Library: Zip
+// Package: Zip
+// Module:  ZipUtil
+//
+// Definition of the ZipUtil class.
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier:	BSL-1.0
+//
+
+
+#ifndef Zip_ZipUtil_INCLUDED
+#define Zip_ZipUtil_INCLUDED
+
+
+#include "Poco/Zip/Zip.h"
+#include "Poco/Zip/ZipCommon.h"
+#include "Poco/DateTime.h"
+#include "Poco/Path.h"
+#include <istream>
+
+
+namespace Poco {
+namespace Zip {
+
+
+class Zip_API ZipUtil
+	/// A utility class used for parsing header information inside of zip files
+{
+public:
+	static Poco::UInt16 get16BitValue(const char* pVal, const Poco::UInt32 pos);
+
+	static Poco::UInt32 get32BitValue(const char* pVal, const Poco::UInt32 pos);
+
+	static Poco::UInt64 get64BitValue(const char* pVal, const Poco::UInt32 pos);
+	
+	static void set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos);
+
+	static void set32BitValue(const Poco::UInt32 val, char* pVal, const Poco::UInt32 pos);
+
+	static void set64BitValue(const Poco::UInt64 val, char* pVal, const Poco::UInt32 pos);
+
+	static Poco::DateTime parseDateTime(const char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos);
+
+	static void setDateTime(const Poco::DateTime& dt, char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos);
+
+	static std::string fakeZLibInitString(ZipCommon::CompressionLevel cl);
+
+	static void sync(std::istream& in);
+		/// Searches the next valid header in the input stream, stops right before it
+
+	static void syncDataDescriptor(std::istream& in, bool force64);
+		/// Searches the next data descriptor
+
+	static void verifyZipEntryFileName(const std::string& zipPath);
+		/// Verifies that the name of the ZipEntry is a valid path
+
+	static std::string validZipEntryFileName(const Poco::Path& entry);
+
+private:
+	ZipUtil();
+	~ZipUtil();
+	ZipUtil(const ZipUtil&);
+	ZipUtil& operator=(const ZipUtil&);
+};
+
+
+inline Poco::UInt16 ZipUtil::get16BitValue(const char* pVal, const Poco::UInt32 pos)
+{
+	return static_cast<Poco::UInt16>((unsigned char)pVal[pos])+ (static_cast<Poco::UInt16>((unsigned char)pVal[pos+1]) << 8);
+}
+
+
+inline Poco::UInt32 ZipUtil::get32BitValue(const char* pVal, const Poco::UInt32 pos)
+{
+	return static_cast<Poco::UInt32>((unsigned char)pVal[pos])+ (static_cast<Poco::UInt32>((unsigned char)pVal[pos+1]) << 8)+
+		(static_cast<Poco::UInt32>((unsigned char)pVal[pos+2]) << 16) + (static_cast<Poco::UInt32>((unsigned char)pVal[pos+3]) << 24);
+}
+
+
+inline Poco::UInt64 ZipUtil::get64BitValue(const char* pVal, const Poco::UInt32 pos)
+{
+	Poco::UInt64 val = ZipUtil::get32BitValue(pVal, pos+4);
+	val = (val << 32) | ZipUtil::get32BitValue(pVal, pos);
+	return val;
+}
+
+
+inline void ZipUtil::set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos)
+{
+	pVal[pos] = static_cast<char>(val);
+	pVal[pos+1] = static_cast<char>(val>>8);
+}
+
+
+inline void ZipUtil::set32BitValue(const Poco::UInt32 val, char* pVal, const Poco::UInt32 pos)
+{
+	pVal[pos] = static_cast<char>(val);
+	pVal[pos+1] = static_cast<char>(val>>8);
+	pVal[pos+2] = static_cast<char>(val>>16);
+	pVal[pos+3] = static_cast<char>(val>>24);
+}
+
+
+inline void ZipUtil::set64BitValue(const Poco::UInt64 val, char* pVal, const Poco::UInt32 pos)
+{
+	pVal[pos] = static_cast<char>(val);
+	pVal[pos+1] = static_cast<char>(val>>8);
+	pVal[pos+2] = static_cast<char>(val>>16);
+	pVal[pos+3] = static_cast<char>(val>>24);
+	pVal[pos+4] = static_cast<char>(val>>32);
+	pVal[pos+5] = static_cast<char>(val>>40);
+	pVal[pos+6] = static_cast<char>(val>>48);
+	pVal[pos+7] = static_cast<char>(val>>56);
+}
+
+
+} } // namespace Poco::Zip
+
+
+#endif // Zip_ZipUtil_INCLUDED
diff --git a/Poco/zconf.h b/Poco/zconf.h
new file mode 100644
index 0000000..4754e9a
--- /dev/null
+++ b/Poco/zconf.h
@@ -0,0 +1,536 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: //poco/1.4/Foundation/include/Poco/zconf.h#5 $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  define adler32_z             z_adler32_z
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define crc32_z               z_crc32_z
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateGetDictionary  z_deflateGetDictionary
+#  define deflateInit           z_deflateInit
+#  define deflateInit2          z_deflateInit2
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzfread               z_gzfread
+#    define gzfwrite              z_gzfwrite
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzvprintf             z_gzvprintf
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit       z_inflateBackInit
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCodesUsed      z_inflateCodesUsed
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetDictionary  z_inflateGetDictionary
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit           z_inflateInit
+#  define inflateInit2          z_inflateInit2
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateValidate       z_inflateValidate
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#    define uncompress2           z_uncompress2
+#  endif
+#  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
+#ifdef Z_SOLO
+   typedef unsigned long z_size_t;
+#else
+#  define z_longlong long long
+#  if defined(NO_SIZE_T)
+     typedef unsigned NO_SIZE_T z_size_t;
+#  elif defined(STDC)
+#    include <stddef.h>
+     typedef size_t z_size_t;
+#  else
+     typedef unsigned long z_size_t;
+#  endif
+#  undef z_longlong
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifndef _WIN32_WCE
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/Poco/zlib.h b/Poco/zlib.h
new file mode 100644
index 0000000..f09cdaf
--- /dev/null
+++ b/Poco/zlib.h
@@ -0,0 +1,1912 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.11, January 15th, 2017
+
+  Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.11"
+#define ZLIB_VERNUM 0x12b0
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 11
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip and raw deflate streams in
+  memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in the case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    z_const Bytef *next_in;     /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total number of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte will go here */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total number of bytes output so far */
+
+    z_const char *msg;  /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text
+                           for deflate, or the decoding state for inflate */
+    uLong   adler;      /* Adler-32 or CRC-32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.  In that case, zlib is thread-safe.  When zalloc and zfree are
+   Z_NULL on entry to the initialization function, they are set to internal
+   routines that use the standard library functions malloc() and free().
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use by the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field for deflate() */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Generate more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary.  Some output may be provided even if
+    flush is zero.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending. See deflatePending(),
+  which can be used if desired to determine whether or not there is more ouput
+  in that case.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed
+  codes block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space.  If deflate returns with Z_OK or Z_BUF_ERROR, this
+  function must be called again with Z_FINISH and more output space (updated
+  avail_out) but no more input data, until it returns with Z_STREAM_END or an
+  error.  After deflate has returned Z_STREAM_END, the only possible operations
+  on the stream are deflateReset or deflateEnd.
+
+    Z_FINISH can be used in the first deflate call after deflateInit if all the
+  compression is to be done in a single step.  In order to complete in one
+  call, avail_out must be at least the value returned by deflateBound (see
+  below).  Then deflate is guaranteed to return Z_STREAM_END.  If not enough
+  output space is provided, deflate will not return Z_STREAM_END, and it must
+  be called again as described above.
+
+    deflate() sets strm->adler to the Adler-32 checksum of all input read
+  so far (that is, total_in bytes).  If a gzip stream is being generated, then
+  strm->adler will be the CRC-32 checksum of the input read so far.  (See
+  deflateInit2 below.)
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  If in doubt, the data is
+  considered binary.  This field is only for information purposes and does not
+  affect the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL or the state was inadvertently written over
+  by the application), or Z_BUF_ERROR if no progress is possible (for example
+  avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not fatal, and
+  deflate() can be called again with more input and more output space to
+  continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  In the current version of inflate, the provided input is not
+   read or consumed.  The allocation of a sliding window will be deferred to
+   the first call of inflate (if the decompression does not complete on the
+   first call).  If zalloc and zfree are set to Z_NULL, inflateInit updates
+   them to use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression.
+   Actual decompression will be done by inflate().  So next_in, and avail_in,
+   next_out, and avail_out are unused and unchanged.  The current
+   implementation of inflateInit() does not process any header information --
+   that is deferred until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), then next_in and avail_in are updated
+    accordingly, and processing will resume at this point for the next call of
+    inflate().
+
+  - Generate more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  If the
+  caller of inflate() does not provide both available input and available
+  output space, it is possible that there will be no progress made.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  To assist in this, on return inflate() always sets strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.)  The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed Adler-32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained unless inflateGetHeader() is used.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  produced so far.  The CRC-32 is checked against the gzip trailer, as is the
+  uncompressed length, modulo 2^32.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value, in which case strm->msg points to a string with a more specific
+  error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL, or the state was inadvertently written over
+  by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+  if no progress was possible or if there was not enough room in the output
+  buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is to be attempted.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+   was inconsistent.
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     For the current implementation of deflate(), a windowBits value of 8 (a
+   window size of 256 bytes) is not supported.  As a result, a request for 8
+   will result in 9 (a 512-byte window).  In that case, providing 8 to
+   inflateInit2() will result in an error when the zlib header with 9 is
+   checked against the initialization of inflate().  The remedy is to not use 8
+   with deflateInit2() with this initialization, or at least in that case use 9
+   with inflateInit2().
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute a check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to the appropriate value,
+   if the operating system was determined at compile time.  If a gzip stream is
+   being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+     For raw deflate or gzip encoding, a request for a 256-byte window is
+   rejected as invalid, since only the zlib header provides a means of
+   transmitting the window size to the decompressor.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the Adler-32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The Adler-32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   Adler-32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by deflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If deflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     deflateGetDictionary() may return a length less than the window size, even
+   when more than the window size in input has been provided. It may return up
+   to 258 bytes less in that case, due to how zlib's implementation of deflate
+   manages the sliding window and lookahead for matches, where matches can be
+   up to 258 bytes long. If the application needs the last window-size bytes of
+   input, then that would need to be saved by the application outside of zlib.
+
+     deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit, but
+   does not free and reallocate the internal compression state.  The stream
+   will leave the compression level and any other attributes that may have been
+   set unchanged.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2().  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression approach (which is a function of the level) or the
+   strategy is changed, and if any input has been consumed in a previous
+   deflate() call, then the input available so far is compressed with the old
+   level and strategy using deflate(strm, Z_BLOCK).  There are three approaches
+   for the compression levels 0, 1..3, and 4..9 respectively.  The new level
+   and strategy will take effect at the next call of deflate().
+
+     If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+   not have enough output space to complete, then the parameter change will not
+   take effect.  In this case, deflateParams() can be called again with the
+   same parameters and more output space to try again.
+
+     In order to assure a change in the parameters on the first try, the
+   deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+   request until strm.avail_out is not zero, before calling deflateParams().
+   Then no more input data should be provided before the deflateParams() call.
+   If this is done, the old level and strategy will be applied to the data
+   compressed before deflateParams(), and the new level and strategy will be
+   applied to the the data compressed after deflateParams().
+
+     deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+   state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+   there was not enough output space to complete the compression of the
+   available input data before a change in the strategy or approach.  Note that
+   in the case of a Z_BUF_ERROR, the parameters are not changed.  A return
+   value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+   retried with more output space.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   CRC-32 instead of an Adler-32.  Unlike the gunzip utility and gzread() (see
+   below), inflate() will not automatically decode concatenated gzip streams.
+   inflate() will return Z_STREAM_END at the end of the gzip stream.  The state
+   would need to be reset to continue decoding a subsequent gzip stream.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the Adler-32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler-32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by inflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If inflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurrences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.  If the window size is changed, then the
+   memory allocated for the window is freed, and the window will be reallocated
+   by inflate() if needed.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above, or -65536 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *,
+                                z_const unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is potentially more efficient than
+   inflate() for file i/o applications, in that it avoids copying between the
+   output and the sliding window by simply making the window itself the output
+   buffer.  inflate() can be faster on modern CPUs when used with large
+   buffers.  inflateBack() trusts the application to not change the output
+   buffer passed by the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the default
+   behavior of inflate(), which expects a zlib header and trailer around the
+   deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero -- buf is ignored in that
+   case -- and inflateBack() will return a buffer error.  inflateBack() will
+   call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+   out() should return zero on success, or non-zero on failure.  If out()
+   returns non-zero, inflateBack() will return with an error.  Neither in() nor
+   out() are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.)  Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: ZLIB_DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed data.  compress() is equivalent to compress2() with a level
+   parameter of Z_DEFAULT_COMPRESSION.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed data.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed data.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest,   uLongf *destLen,
+                                    const Bytef *source, uLong *sourceLen));
+/*
+     Same as uncompress, except that sourceLen is a pointer, where the
+   length of the source is *sourceLen.  On return, *sourceLen is the number of
+   source bytes consumed.
+*/
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Three times that size in buffer space is allocated.  A larger buffer
+   size of, for example, 64K or 128K bytes will noticeably increase the speed
+   of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.  Previously provided
+   data is flushed before the parameter change.
+
+     gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+   opened for writing, Z_ERRNO if there is an error writing the flushed data,
+   or Z_MEM_ERROR if there is a memory allocation error.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.  If len is too large to fit in an int,
+   then nothing is read, -1 is returned, and the error state is set to
+   Z_STREAM_ERROR.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
+                                     gzFile file));
+/*
+     Read up to nitems items of size size from file to buf, otherwise operating
+   as gzread() does.  This duplicates the interface of stdio's fread(), with
+   size_t request and return types.  If the library defines size_t, then
+   z_size_t is identical to size_t.  If not, then z_size_t is an unsigned
+   integer type that can contain a pointer.
+
+     gzfread() returns the number of full items read of size size, or zero if
+   the end of the file was reached and a full item could not be read, or if
+   there was an error.  gzerror() must be consulted if zero is returned in
+   order to determine if there was an error.  If the multiplication of size and
+   nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+   is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+     In the event that the end of file is reached and only a partial item is
+   available at the end, i.e. the remaining uncompressed data length is not a
+   multiple of size, then the final partial item is nevetheless read into buf
+   and the end-of-file flag is set.  The length of the partial item read is not
+   provided, but could be inferred from the result of gztell().  This behavior
+   is the same as the behavior of fread() implementations in common libraries,
+   but it prevents the direct use of gzfread() to read a concurrently written
+   file, reseting and retrying on end-of-file, when size is not 1.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
+                                      z_size_t nitems, gzFile file));
+/*
+     gzfwrite() writes nitems items of size size from buf to file, duplicating
+   the interface of stdio's fwrite(), with size_t request and return types.  If
+   the library defines size_t, then z_size_t is identical to size_t.  If not,
+   then z_size_t is an unsigned integer type that can contain a pointer.
+
+     gzfwrite() returns the number of full items written of size size, or zero
+   if there was an error.  If the multiplication of size and nitems overflows,
+   i.e. the product does not fit in a z_size_t, then nothing is written, zero
+   is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or a negative zlib error code in case
+   of error.  The number of uncompressed bytes written is limited to 8191, or
+   one less than the buffer size given to gzbuffer().  The caller should assure
+   that this limit is not exceeded.  If it is exceeded, then gzprintf() will
+   return an error (0) with nothing written.  In this case, there may also be a
+   buffer overflow with unpredictable consequences, which is possible only if
+   zlib was compiled with the insecure functions sprintf() or vsprintf()
+   because the secure snprintf() or vsnprintf() functions were not available.
+   This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatenated gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
+                                    z_size_t len));
+/*
+     Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
+                                  z_size_t len));
+/*
+     Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#ifdef Z_PREFIX_SET
+#  define z_deflateInit(strm, level) \
+          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define z_inflateInit(strm) \
+          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define z_inflateInit2(strm, windowBits) \
+          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                        (int)sizeof(z_stream))
+#  define z_inflateBackInit(strm, windowBits, window) \
+          inflateBackInit_((strm), (windowBits), (window), \
+                           ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+#  define deflateInit(strm, level) \
+          deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define inflateInit(strm) \
+          inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+          deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                        (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#  define inflateInit2(strm, windowBits) \
+          inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                        (int)sizeof(z_stream))
+#  define inflateBackInit(strm, windowBits, window) \
+          inflateBackInit_((strm), (windowBits), (window), \
+                           ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+#  define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    define gzopen gzopen64
+#    define gzseek gzseek64
+#    define gztell gztell64
+#    define gzoffset gzoffset64
+#    define adler32_combine adler32_combine64
+#    define crc32_combine crc32_combine64
+#  endif
+#  ifndef Z_LARGE64
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateValidate OF((z_streamp, int));
+ZEXTERN unsigned long  ZEXPORT inflateCodesUsed OF ((z_streamp));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+                                                  const char *format,
+                                                  va_list va));
+#  endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/mosquitto.h b/mosquitto.h
new file mode 100644
index 0000000..a868f99
--- /dev/null
+++ b/mosquitto.h
@@ -0,0 +1,2994 @@
+/*
+Copyright (c) 2010-2019 Roger Light <roger@atchoo.org>
+
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+and Eclipse Distribution License v1.0 which accompany this distribution.
+
+The Eclipse Public License is available at
+   http://www.eclipse.org/legal/epl-v10.html
+and the Eclipse Distribution License is available at
+  http://www.eclipse.org/org/documents/edl-v10.php.
+
+Contributors:
+   Roger Light - initial implementation and documentation.
+*/
+
+#ifndef MOSQUITTO_H
+#define MOSQUITTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(WIN32) && !defined(WITH_BROKER) && !defined(LIBMOSQUITTO_STATIC)
+#	ifdef libmosquitto_EXPORTS
+#		define libmosq_EXPORT  __declspec(dllexport)
+#	else
+#		define libmosq_EXPORT  __declspec(dllimport)
+#	endif
+#else
+#	define libmosq_EXPORT
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#	ifndef __cplusplus
+#		define bool char
+#		define true 1
+#		define false 0
+#	endif
+#else
+#	ifndef __cplusplus
+#		include <stdbool.h>
+#	endif
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define LIBMOSQUITTO_MAJOR 1
+#define LIBMOSQUITTO_MINOR 6
+#define LIBMOSQUITTO_REVISION 7
+/* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */
+#define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION)
+
+/* Log types */
+#define MOSQ_LOG_NONE			0
+#define MOSQ_LOG_INFO			(1<<0)
+#define MOSQ_LOG_NOTICE			(1<<1)
+#define MOSQ_LOG_WARNING		(1<<2)
+#define MOSQ_LOG_ERR			(1<<3)
+#define MOSQ_LOG_DEBUG			(1<<4)
+#define MOSQ_LOG_SUBSCRIBE		(1<<5)
+#define MOSQ_LOG_UNSUBSCRIBE	(1<<6)
+#define MOSQ_LOG_WEBSOCKETS		(1<<7)
+#define MOSQ_LOG_INTERNAL		0x80000000
+#define MOSQ_LOG_ALL			0x7FFFFFFF
+
+/* Error values */
+enum mosq_err_t {
+	MOSQ_ERR_AUTH_CONTINUE = -4,
+	MOSQ_ERR_NO_SUBSCRIBERS = -3,
+	MOSQ_ERR_SUB_EXISTS = -2,
+	MOSQ_ERR_CONN_PENDING = -1,
+	MOSQ_ERR_SUCCESS = 0,
+	MOSQ_ERR_NOMEM = 1,
+	MOSQ_ERR_PROTOCOL = 2,
+	MOSQ_ERR_INVAL = 3,
+	MOSQ_ERR_NO_CONN = 4,
+	MOSQ_ERR_CONN_REFUSED = 5,
+	MOSQ_ERR_NOT_FOUND = 6,
+	MOSQ_ERR_CONN_LOST = 7,
+	MOSQ_ERR_TLS = 8,
+	MOSQ_ERR_PAYLOAD_SIZE = 9,
+	MOSQ_ERR_NOT_SUPPORTED = 10,
+	MOSQ_ERR_AUTH = 11,
+	MOSQ_ERR_ACL_DENIED = 12,
+	MOSQ_ERR_UNKNOWN = 13,
+	MOSQ_ERR_ERRNO = 14,
+	MOSQ_ERR_EAI = 15,
+	MOSQ_ERR_PROXY = 16,
+	MOSQ_ERR_PLUGIN_DEFER = 17,
+	MOSQ_ERR_MALFORMED_UTF8 = 18,
+	MOSQ_ERR_KEEPALIVE = 19,
+	MOSQ_ERR_LOOKUP = 20,
+	MOSQ_ERR_MALFORMED_PACKET = 21,
+	MOSQ_ERR_DUPLICATE_PROPERTY = 22,
+	MOSQ_ERR_TLS_HANDSHAKE = 23,
+	MOSQ_ERR_QOS_NOT_SUPPORTED = 24,
+	MOSQ_ERR_OVERSIZE_PACKET = 25,
+	MOSQ_ERR_OCSP = 26,
+};
+
+/* Option values */
+enum mosq_opt_t {
+	MOSQ_OPT_PROTOCOL_VERSION = 1,
+	MOSQ_OPT_SSL_CTX = 2,
+	MOSQ_OPT_SSL_CTX_WITH_DEFAULTS = 3,
+	MOSQ_OPT_RECEIVE_MAXIMUM = 4,
+	MOSQ_OPT_SEND_MAXIMUM = 5,
+	MOSQ_OPT_TLS_KEYFORM = 6,
+	MOSQ_OPT_TLS_ENGINE = 7,
+	MOSQ_OPT_TLS_ENGINE_KPASS_SHA1 = 8,
+	MOSQ_OPT_TLS_OCSP_REQUIRED = 9,
+	MOSQ_OPT_TLS_ALPN = 10,
+};
+
+
+/* MQTT specification restricts client ids to a maximum of 23 characters */
+#define MOSQ_MQTT_ID_MAX_LENGTH 23
+
+#define MQTT_PROTOCOL_V31 3
+#define MQTT_PROTOCOL_V311 4
+#define MQTT_PROTOCOL_V5 5
+
+struct mosquitto_message{
+	int mid;
+	char *topic;
+	void *payload;
+	int payloadlen;
+	int qos;
+	bool retain;
+};
+
+struct mosquitto;
+typedef struct mqtt5__property mosquitto_property;
+
+/*
+ * Topic: Threads
+ *	libmosquitto provides thread safe operation, with the exception of
+ *	<mosquitto_lib_init> which is not thread safe.
+ *
+ *	If your application uses threads you must use <mosquitto_threaded_set> to
+ *	tell the library this is the case, otherwise it makes some optimisations
+ *	for the single threaded case that may result in unexpected behaviour for
+ *	the multi threaded case.
+ */
+/***************************************************
+ * Important note
+ *
+ * The following functions that deal with network operations will return
+ * MOSQ_ERR_SUCCESS on success, but this does not mean that the operation has
+ * taken place. An attempt will be made to write the network data, but if the
+ * socket is not available for writing at that time then the packet will not be
+ * sent. To ensure the packet is sent, call mosquitto_loop() (which must also
+ * be called to process incoming network data).
+ * This is especially important when disconnecting a client that has a will. If
+ * the broker does not receive the DISCONNECT command, it will assume that the
+ * client has disconnected unexpectedly and send the will.
+ *
+ * mosquitto_connect()
+ * mosquitto_disconnect()
+ * mosquitto_subscribe()
+ * mosquitto_unsubscribe()
+ * mosquitto_publish()
+ ***************************************************/
+
+
+/* ======================================================================
+ *
+ * Section: Library version, init, and cleanup
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_lib_version
+ *
+ * Can be used to obtain version information for the mosquitto library.
+ * This allows the application to compare the library version against the
+ * version it was compiled against by using the LIBMOSQUITTO_MAJOR,
+ * LIBMOSQUITTO_MINOR and LIBMOSQUITTO_REVISION defines.
+ *
+ * Parameters:
+ *  major -    an integer pointer. If not NULL, the major version of the
+ *             library will be returned in this variable.
+ *  minor -    an integer pointer. If not NULL, the minor version of the
+ *             library will be returned in this variable.
+ *  revision - an integer pointer. If not NULL, the revision of the library will
+ *             be returned in this variable.
+ *
+ * Returns:
+ *	LIBMOSQUITTO_VERSION_NUMBER, which is a unique number based on the major,
+ *		minor and revision values.
+ * See Also:
+ * 	<mosquitto_lib_cleanup>, <mosquitto_lib_init>
+ */
+libmosq_EXPORT int mosquitto_lib_version(int *major, int *minor, int *revision);
+
+/*
+ * Function: mosquitto_lib_init
+ *
+ * Must be called before any other mosquitto functions.
+ *
+ * This function is *not* thread safe.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - always
+ *
+ * See Also:
+ * 	<mosquitto_lib_cleanup>, <mosquitto_lib_version>
+ */
+libmosq_EXPORT int mosquitto_lib_init(void);
+
+/*
+ * Function: mosquitto_lib_cleanup
+ *
+ * Call to free resources associated with the library.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - always
+ *
+ * See Also:
+ * 	<mosquitto_lib_init>, <mosquitto_lib_version>
+ */
+libmosq_EXPORT int mosquitto_lib_cleanup(void);
+
+
+/* ======================================================================
+ *
+ * Section: Client creation, destruction, and reinitialisation
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_new
+ *
+ * Create a new mosquitto client instance.
+ *
+ * Parameters:
+ * 	id -            String to use as the client id. If NULL, a random client id
+ * 	                will be generated. If id is NULL, clean_session must be true.
+ * 	clean_session - set to true to instruct the broker to clean all messages
+ *                  and subscriptions on disconnect, false to instruct it to
+ *                  keep them. See the man page mqtt(7) for more details.
+ *                  Note that a client will never discard its own outgoing
+ *                  messages on disconnect. Calling <mosquitto_connect> or
+ *                  <mosquitto_reconnect> will cause the messages to be resent.
+ *                  Use <mosquitto_reinitialise> to reset a client to its
+ *                  original state.
+ *                  Must be set to true if the id parameter is NULL.
+ * 	obj -           A user pointer that will be passed as an argument to any
+ *                  callbacks that are specified.
+ *
+ * Returns:
+ * 	Pointer to a struct mosquitto on success.
+ * 	NULL on failure. Interrogate errno to determine the cause for the failure:
+ *      - ENOMEM on out of memory.
+ *      - EINVAL on invalid input parameters.
+ *
+ * See Also:
+ * 	<mosquitto_reinitialise>, <mosquitto_destroy>, <mosquitto_user_data_set>
+ */
+libmosq_EXPORT struct mosquitto *mosquitto_new(const char *id, bool clean_session, void *obj);
+
+/*
+ * Function: mosquitto_destroy
+ *
+ * Use to free memory associated with a mosquitto client instance.
+ *
+ * Parameters:
+ * 	mosq - a struct mosquitto pointer to free.
+ *
+ * See Also:
+ * 	<mosquitto_new>, <mosquitto_reinitialise>
+ */
+libmosq_EXPORT void mosquitto_destroy(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_reinitialise
+ *
+ * This function allows an existing mosquitto client to be reused. Call on a
+ * mosquitto instance to close any open network connections, free memory
+ * and reinitialise the client with the new parameters. The end result is the
+ * same as the output of <mosquitto_new>.
+ *
+ * Parameters:
+ * 	mosq -          a valid mosquitto instance.
+ * 	id -            string to use as the client id. If NULL, a random client id
+ * 	                will be generated. If id is NULL, clean_session must be true.
+ * 	clean_session - set to true to instruct the broker to clean all messages
+ *                  and subscriptions on disconnect, false to instruct it to
+ *                  keep them. See the man page mqtt(7) for more details.
+ *                  Must be set to true if the id parameter is NULL.
+ * 	obj -           A user pointer that will be passed as an argument to any
+ *                  callbacks that are specified.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * See Also:
+ * 	<mosquitto_new>, <mosquitto_destroy>
+ */
+libmosq_EXPORT int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_session, void *obj);
+
+
+/* ======================================================================
+ *
+ * Section: Will
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_will_set
+ *
+ * Configure will information for a mosquitto instance. By default, clients do
+ * not have a will.  This must be called before calling <mosquitto_connect>.
+ *
+ * Parameters:
+ * 	mosq -       a valid mosquitto instance.
+ * 	topic -      the topic on which to publish the will.
+ * 	payloadlen - the size of the payload (bytes). Valid values are between 0 and
+ *               268,435,455.
+ * 	payload -    pointer to the data to send. If payloadlen > 0 this must be a
+ *               valid memory location.
+ * 	qos -        integer value 0, 1 or 2 indicating the Quality of Service to be
+ *               used for the will.
+ * 	retain -     set to true to make the will a retained message.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS -      on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_PAYLOAD_SIZE -   if payloadlen is too large.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8.
+ */
+libmosq_EXPORT int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
+
+/*
+ * Function: mosquitto_will_set_v5
+ *
+ * Configure will information for a mosquitto instance, with attached
+ * properties. By default, clients do not have a will.  This must be called
+ * before calling <mosquitto_connect>.
+ *
+ * Parameters:
+ * 	mosq -       a valid mosquitto instance.
+ * 	topic -      the topic on which to publish the will.
+ * 	payloadlen - the size of the payload (bytes). Valid values are between 0 and
+ *               268,435,455.
+ * 	payload -    pointer to the data to send. If payloadlen > 0 this must be a
+ *               valid memory location.
+ * 	qos -        integer value 0, 1 or 2 indicating the Quality of Service to be
+ *               used for the will.
+ * 	retain -     set to true to make the will a retained message.
+ * 	properties - list of MQTT 5 properties. Can be NULL. On success only, the
+ * 	             property list becomes the property of libmosquitto once this
+ * 	             function is called and will be freed by the library. The
+ * 	             property list must be freed by the application on error.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS -      on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_PAYLOAD_SIZE -   if payloadlen is too large.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8.
+ * 	MOSQ_ERR_NOT_SUPPORTED -  if properties is not NULL and the client is not
+ * 	                          using MQTT v5
+ * 	MOSQ_ERR_PROTOCOL -       if a property is invalid for use with wills.
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ */
+libmosq_EXPORT int mosquitto_will_set_v5(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain, mosquitto_property *properties);
+
+/*
+ * Function: mosquitto_will_clear
+ *
+ * Remove a previously configured will. This must be called before calling
+ * <mosquitto_connect>.
+ *
+ * Parameters:
+ * 	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_will_clear(struct mosquitto *mosq);
+
+
+/* ======================================================================
+ *
+ * Section: Username and password
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_username_pw_set
+ *
+ * Configure username and password for a mosquitton instance. This is only
+ * supported by brokers that implement the MQTT spec v3.1. By default, no
+ * username or password will be sent.
+ * If username is NULL, the password argument is ignored.
+ * This must be called before calling mosquitto_connect().
+ *
+ * This is must be called before calling <mosquitto_connect>.
+ *
+ * Parameters:
+ * 	mosq -     a valid mosquitto instance.
+ * 	username - the username to send as a string, or NULL to disable
+ *             authentication.
+ * 	password - the password to send as a string. Set to NULL when username is
+ * 	           valid in order to send just a username.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ */
+libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password);
+
+
+/* ======================================================================
+ *
+ * Section: Connecting, reconnecting, disconnecting
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_connect
+ *
+ * Connect to an MQTT broker.
+ *
+ * Parameters:
+ * 	mosq -      a valid mosquitto instance.
+ * 	host -      the hostname or ip address of the broker to connect to.
+ * 	port -      the network port to connect to. Usually 1883.
+ * 	keepalive - the number of seconds after which the broker should send a PING
+ *              message to the client if no other messages have been exchanged
+ *              in that time.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect_bind>, <mosquitto_connect_async>, <mosquitto_reconnect>, <mosquitto_disconnect>, <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_connect(struct mosquitto *mosq, const char *host, int port, int keepalive);
+
+/*
+ * Function: mosquitto_connect_bind
+ *
+ * Connect to an MQTT broker. This extends the functionality of
+ * <mosquitto_connect> by adding the bind_address parameter. Use this function
+ * if you need to restrict network communication over a particular interface.
+ *
+ * Parameters:
+ * 	mosq -         a valid mosquitto instance.
+ * 	host -         the hostname or ip address of the broker to connect to.
+ * 	port -         the network port to connect to. Usually 1883.
+ * 	keepalive -    the number of seconds after which the broker should send a PING
+ *                 message to the client if no other messages have been exchanged
+ *                 in that time.
+ *  bind_address - the hostname or ip address of the local network interface to
+ *                 bind to.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect>, <mosquitto_connect_async>, <mosquitto_connect_bind_async>
+ */
+libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address);
+
+/*
+ * Function: mosquitto_connect_bind_v5
+ *
+ * Connect to an MQTT broker. This extends the functionality of
+ * <mosquitto_connect> by adding the bind_address parameter. Use this function
+ * if you need to restrict network communication over a particular interface.
+ *
+ * Parameters:
+ * 	mosq -         a valid mosquitto instance.
+ * 	host -         the hostname or ip address of the broker to connect to.
+ * 	port -         the network port to connect to. Usually 1883.
+ * 	keepalive -    the number of seconds after which the broker should send a PING
+ *                 message to the client if no other messages have been exchanged
+ *                 in that time.
+ *  bind_address - the hostname or ip address of the local network interface to
+ *                 bind to.
+ *  properties - the MQTT 5 properties for the connect (not for the Will).
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ *	MOSQ_ERR_PROTOCOL - if any property is invalid for use with CONNECT.
+ *
+ * See Also:
+ * 	<mosquitto_connect>, <mosquitto_connect_async>, <mosquitto_connect_bind_async>
+ */
+libmosq_EXPORT int mosquitto_connect_bind_v5(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address, const mosquitto_property *properties);
+
+/*
+ * Function: mosquitto_connect_async
+ *
+ * Connect to an MQTT broker. This is a non-blocking call. If you use
+ * <mosquitto_connect_async> your client must use the threaded interface
+ * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use
+ * <mosquitto_connect> to connect the client.
+ *
+ * May be called before or after <mosquitto_loop_start>.
+ *
+ * Parameters:
+ * 	mosq -      a valid mosquitto instance.
+ * 	host -      the hostname or ip address of the broker to connect to.
+ * 	port -      the network port to connect to. Usually 1883.
+ * 	keepalive - the number of seconds after which the broker should send a PING
+ *              message to the client if no other messages have been exchanged
+ *              in that time.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect_bind_async>, <mosquitto_connect>, <mosquitto_reconnect>, <mosquitto_disconnect>, <mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_connect_async(struct mosquitto *mosq, const char *host, int port, int keepalive);
+
+/*
+ * Function: mosquitto_connect_bind_async
+ *
+ * Connect to an MQTT broker. This is a non-blocking call. If you use
+ * <mosquitto_connect_bind_async> your client must use the threaded interface
+ * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use
+ * <mosquitto_connect> to connect the client.
+ *
+ * This extends the functionality of <mosquitto_connect_async> by adding the
+ * bind_address parameter. Use this function if you need to restrict network
+ * communication over a particular interface.
+ *
+ * May be called before or after <mosquitto_loop_start>.
+ *
+ * Parameters:
+ * 	mosq -         a valid mosquitto instance.
+ * 	host -         the hostname or ip address of the broker to connect to.
+ * 	port -         the network port to connect to. Usually 1883.
+ * 	keepalive -    the number of seconds after which the broker should send a PING
+ *                 message to the client if no other messages have been exchanged
+ *                 in that time.
+ *  bind_address - the hostname or ip address of the local network interface to
+ *                 bind to.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect_async>, <mosquitto_connect>, <mosquitto_connect_bind>
+ */
+libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const char *host, int port, int keepalive, const char *bind_address);
+
+/*
+ * Function: mosquitto_connect_srv
+ *
+ * Connect to an MQTT broker. This is a non-blocking call. If you use
+ * <mosquitto_connect_async> your client must use the threaded interface
+ * <mosquitto_loop_start>. If you need to use <mosquitto_loop>, you must use
+ * <mosquitto_connect> to connect the client.
+ *
+ * This extends the functionality of <mosquitto_connect_async> by adding the
+ * bind_address parameter. Use this function if you need to restrict network
+ * communication over a particular interface.
+ *
+ * May be called before or after <mosquitto_loop_start>.
+ *
+ * Parameters:
+ * 	mosq -         a valid mosquitto instance.
+ * 	host -         the hostname or ip address of the broker to connect to.
+ * 	keepalive -    the number of seconds after which the broker should send a PING
+ *                 message to the client if no other messages have been exchanged
+ *                 in that time.
+ *  bind_address - the hostname or ip address of the local network interface to
+ *                 bind to.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect_async>, <mosquitto_connect>, <mosquitto_connect_bind>
+ */
+libmosq_EXPORT int mosquitto_connect_srv(struct mosquitto *mosq, const char *host, int keepalive, const char *bind_address);
+
+/*
+ * Function: mosquitto_reconnect
+ *
+ * Reconnect to a broker.
+ *
+ * This function provides an easy way of reconnecting to a broker after a
+ * connection has been lost. It uses the values that were provided in the
+ * <mosquitto_connect> call. It must not be called before
+ * <mosquitto_connect>.
+ *
+ * Parameters:
+ * 	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect>, <mosquitto_disconnect>, <mosquitto_reconnect_async>
+ */
+libmosq_EXPORT int mosquitto_reconnect(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_reconnect_async
+ *
+ * Reconnect to a broker. Non blocking version of <mosquitto_reconnect>.
+ *
+ * This function provides an easy way of reconnecting to a broker after a
+ * connection has been lost. It uses the values that were provided in the
+ * <mosquitto_connect> or <mosquitto_connect_async> calls. It must not be
+ * called before <mosquitto_connect>.
+ *
+ * Parameters:
+ * 	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_ERRNO -   if a system call returned an error. The variable errno
+ *                     contains the error code, even on Windows.
+ *                     Use strerror_r() where available or FormatMessage() on
+ *                     Windows.
+ *
+ * See Also:
+ * 	<mosquitto_connect>, <mosquitto_disconnect>
+ */
+libmosq_EXPORT int mosquitto_reconnect_async(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_disconnect
+ *
+ * Disconnect from the broker.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NO_CONN -  if the client isn't connected to a broker.
+ */
+libmosq_EXPORT int mosquitto_disconnect(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_disconnect_v5
+ *
+ * Disconnect from the broker, with attached MQTT properties.
+ *
+ * Use <mosquitto_property_add_*> to create a list of properties, then attach
+ * them to this publish. Properties need freeing with
+ * <mosquitto_property_free_all>.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	reason_code - the disconnect reason code.
+ * 	properties - a valid mosquitto_property list, or NULL.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NO_CONN -  if the client isn't connected to a broker.
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ *	MOSQ_ERR_PROTOCOL - if any property is invalid for use with DISCONNECT.
+ */
+libmosq_EXPORT int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosquitto_property *properties);
+
+
+/* ======================================================================
+ *
+ * Section: Publishing, subscribing, unsubscribing
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_publish
+ *
+ * Publish a message on a given topic.
+ *
+ * Parameters:
+ * 	mosq -       a valid mosquitto instance.
+ * 	mid -        pointer to an int. If not NULL, the function will set this
+ *               to the message id of this particular message. This can be then
+ *               used with the publish callback to determine when the message
+ *               has been sent.
+ *               Note that although the MQTT protocol doesn't use message ids
+ *               for messages with QoS=0, libmosquitto assigns them message ids
+ *               so they can be tracked with this parameter.
+ *  topic -      null terminated string of the topic to publish to.
+ * 	payloadlen - the size of the payload (bytes). Valid values are between 0 and
+ *               268,435,455.
+ * 	payload -    pointer to the data to send. If payloadlen > 0 this must be a
+ *               valid memory location.
+ * 	qos -        integer value 0, 1 or 2 indicating the Quality of Service to be
+ *               used for the message.
+ * 	retain -     set to true to make the message retained.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ *	MOSQ_ERR_PROTOCOL -       if there is a protocol error communicating with the
+ *                            broker.
+ * 	MOSQ_ERR_PAYLOAD_SIZE -   if payloadlen is too large.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *	MOSQ_ERR_QOS_NOT_SUPPORTED - if the QoS is greater than that supported by
+ *	                             the broker.
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ *
+ * See Also:
+ *	<mosquitto_max_inflight_messages_set>
+ */
+libmosq_EXPORT int mosquitto_publish(struct mosquitto *mosq, int *mid, const char *topic, int payloadlen, const void *payload, int qos, bool retain);
+
+
+/*
+ * Function: mosquitto_publish_v5
+ *
+ * Publish a message on a given topic, with attached MQTT properties.
+ *
+ * Use <mosquitto_property_add_*> to create a list of properties, then attach
+ * them to this publish. Properties need freeing with
+ * <mosquitto_property_free_all>.
+ *
+ * Requires the mosquitto instance to be connected with MQTT 5.
+ *
+ * Parameters:
+ * 	mosq -       a valid mosquitto instance.
+ * 	mid -        pointer to an int. If not NULL, the function will set this
+ *               to the message id of this particular message. This can be then
+ *               used with the publish callback to determine when the message
+ *               has been sent.
+ *               Note that although the MQTT protocol doesn't use message ids
+ *               for messages with QoS=0, libmosquitto assigns them message ids
+ *               so they can be tracked with this parameter.
+ *  topic -      null terminated string of the topic to publish to.
+ * 	payloadlen - the size of the payload (bytes). Valid values are between 0 and
+ *               268,435,455.
+ * 	payload -    pointer to the data to send. If payloadlen > 0 this must be a
+ *               valid memory location.
+ * 	qos -        integer value 0, 1 or 2 indicating the Quality of Service to be
+ *               used for the message.
+ * 	retain -     set to true to make the message retained.
+ * 	properties - a valid mosquitto_property list, or NULL.
+ *
+ * Returns:
+ * 	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ *	MOSQ_ERR_PROTOCOL -       if there is a protocol error communicating with the
+ *                            broker.
+ * 	MOSQ_ERR_PAYLOAD_SIZE -   if payloadlen is too large.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ *	MOSQ_ERR_PROTOCOL - if any property is invalid for use with PUBLISH.
+ *	MOSQ_ERR_QOS_NOT_SUPPORTED - if the QoS is greater than that supported by
+ *	                             the broker.
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_publish_v5(
+		struct mosquitto *mosq,
+		int *mid,
+		const char *topic,
+		int payloadlen,
+		const void *payload,
+		int qos,
+		bool retain,
+		const mosquitto_property *properties);
+
+
+/*
+ * Function: mosquitto_subscribe
+ *
+ * Subscribe to a topic.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	mid -  a pointer to an int. If not NULL, the function will set this to
+ *	       the message id of this particular message. This can be then used
+ *	       with the subscribe callback to determine when the message has been
+ *	       sent.
+ *	sub -  the subscription pattern.
+ *	qos -  the requested Quality of Service for this subscription.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_subscribe(struct mosquitto *mosq, int *mid, const char *sub, int qos);
+
+/*
+ * Function: mosquitto_subscribe_v5
+ *
+ * Subscribe to a topic, with attached MQTT properties.
+ *
+ * Use <mosquitto_property_add_*> to create a list of properties, then attach
+ * them to this subscribe. Properties need freeing with
+ * <mosquitto_property_free_all>.
+ *
+ * Requires the mosquitto instance to be connected with MQTT 5.
+ *
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	mid -  a pointer to an int. If not NULL, the function will set this to
+ *	       the message id of this particular message. This can be then used
+ *	       with the subscribe callback to determine when the message has been
+ *	       sent.
+ *	sub -  the subscription pattern.
+ *	qos -  the requested Quality of Service for this subscription.
+ *	options - options to apply to this subscription, OR'd together. Set to 0 to
+ *	          use the default options, otherwise choose from the list:
+ *	          MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client
+ *	                        publishes to a topic to which it is subscribed, the
+ *	                        broker will not publish the message back to the
+ *	                        client.
+ *	          MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages
+ *	                        published for this subscription will keep the
+ *	                        retain flag as was set by the publishing client.
+ *	                        The default behaviour without this option set has
+ *	                        the retain flag indicating whether a message is
+ *	                        fresh/stale.
+ *	          MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set,
+ *	                        pre-existing retained messages are sent as soon as
+ *	                        the subscription is made, even if the subscription
+ *	                        already exists. This is the default behaviour, so
+ *	                        it is not necessary to set this option.
+ *	          MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing
+ *	                        retained messages for this subscription will be
+ *	                        sent when the subscription is made, but only if the
+ *	                        subscription does not already exist.
+ *	          MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set,
+ *	                        pre-existing retained messages will never be sent
+ *	                        for this subscription.
+ * 	properties - a valid mosquitto_property list, or NULL.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ *	MOSQ_ERR_PROTOCOL - if any property is invalid for use with SUBSCRIBE.
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_subscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, int qos, int options, const mosquitto_property *properties);
+
+/*
+ * Function: mosquitto_subscribe_multiple
+ *
+ * Subscribe to multiple topics.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	mid -  a pointer to an int. If not NULL, the function will set this to
+ *	       the message id of this particular message. This can be then used
+ *	       with the subscribe callback to determine when the message has been
+ *	       sent.
+ *  sub_count - the count of subscriptions to be made
+ *	sub -  array of sub_count pointers, each pointing to a subscription string.
+ *	       The "char *const *const" datatype ensures that neither the array of
+ *	       pointers nor the strings that they point to are mutable. If you aren't
+ *	       familiar with this, just think of it as a safer "char **",
+ *	       equivalent to "const char *" for a simple string pointer.
+ *	qos -  the requested Quality of Service for each subscription.
+ *	options - options to apply to this subscription, OR'd together. This
+ *	          argument is not used for MQTT v3 susbcriptions. Set to 0 to use
+ *	          the default options, otherwise choose from the list:
+ *	       MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client
+ *	                     publishes to a topic to which it is subscribed, the
+ *	                     broker will not publish the message back to the
+ *	                     client.
+ *	       MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages
+ *	                     published for this subscription will keep the
+ *	                     retain flag as was set by the publishing client.
+ *	                     The default behaviour without this option set has
+ *	                     the retain flag indicating whether a message is
+ *	                     fresh/stale.
+ *	       MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set,
+ *	                     pre-existing retained messages are sent as soon as
+ *	                     the subscription is made, even if the subscription
+ *	                     already exists. This is the default behaviour, so
+ *	                     it is not necessary to set this option.
+ *	       MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing
+ *	                     retained messages for this subscription will be
+ *	                     sent when the subscription is made, but only if the
+ *	                     subscription does not already exist.
+ *	       MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set,
+ *	                     pre-existing retained messages will never be sent
+ *	                     for this subscription.
+ * 	properties - a valid mosquitto_property list, or NULL. Only used with MQTT
+ * 	             v5 clients.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if a topic is not valid UTF-8
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_subscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, int qos, int options, const mosquitto_property *properties);
+
+/*
+ * Function: mosquitto_unsubscribe
+ *
+ * Unsubscribe from a topic.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	mid -  a pointer to an int. If not NULL, the function will set this to
+ *	       the message id of this particular message. This can be then used
+ *	       with the unsubscribe callback to determine when the message has been
+ *	       sent.
+ *	sub -  the unsubscription pattern.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_unsubscribe(struct mosquitto *mosq, int *mid, const char *sub);
+
+/*
+ * Function: mosquitto_unsubscribe_v5
+ *
+ * Unsubscribe from a topic, with attached MQTT properties.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	mid -  a pointer to an int. If not NULL, the function will set this to
+ *	       the message id of this particular message. This can be then used
+ *	       with the unsubscribe callback to determine when the message has been
+ *	       sent.
+ *	sub -  the unsubscription pattern.
+ * 	properties - a valid mosquitto_property list, or NULL. Only used with MQTT
+ * 	             v5 clients.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ *	MOSQ_ERR_PROTOCOL - if any property is invalid for use with UNSUBSCRIBE.
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_unsubscribe_v5(struct mosquitto *mosq, int *mid, const char *sub, const mosquitto_property *properties);
+
+/*
+ * Function: mosquitto_unsubscribe_multiple
+ *
+ * Unsubscribe from multiple topics.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *	mid -  a pointer to an int. If not NULL, the function will set this to
+ *	       the message id of this particular message. This can be then used
+ *	       with the subscribe callback to determine when the message has been
+ *	       sent.
+ *  sub_count - the count of unsubscriptions to be made
+ *	sub -  array of sub_count pointers, each pointing to an unsubscription string.
+ *	       The "char *const *const" datatype ensures that neither the array of
+ *	       pointers nor the strings that they point to are mutable. If you aren't
+ *	       familiar with this, just think of it as a safer "char **",
+ *	       equivalent to "const char *" for a simple string pointer.
+ * 	properties - a valid mosquitto_property list, or NULL. Only used with MQTT
+ * 	             v5 clients.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success.
+ * 	MOSQ_ERR_INVAL -          if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -        if the client isn't connected to a broker.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if a topic is not valid UTF-8
+ *	MOSQ_ERR_OVERSIZE_PACKET - if the resulting packet would be larger than
+ *	                           supported by the broker.
+ */
+libmosq_EXPORT int mosquitto_unsubscribe_multiple(struct mosquitto *mosq, int *mid, int sub_count, char *const *const sub, const mosquitto_property *properties);
+
+
+/* ======================================================================
+ *
+ * Section: Struct mosquitto_message helper functions
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_message_copy
+ *
+ * Copy the contents of a mosquitto message to another message.
+ * Useful for preserving a message received in the on_message() callback.
+ *
+ * Parameters:
+ *	dst - a pointer to a valid mosquitto_message struct to copy to.
+ *	src - a pointer to a valid mosquitto_message struct to copy from.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * See Also:
+ * 	<mosquitto_message_free>
+ */
+libmosq_EXPORT int mosquitto_message_copy(struct mosquitto_message *dst, const struct mosquitto_message *src);
+
+/*
+ * Function: mosquitto_message_free
+ *
+ * Completely free a mosquitto_message struct.
+ *
+ * Parameters:
+ *	message - pointer to a mosquitto_message pointer to free.
+ *
+ * See Also:
+ * 	<mosquitto_message_copy>, <mosquitto_message_free_contents>
+ */
+libmosq_EXPORT void mosquitto_message_free(struct mosquitto_message **message);
+
+/*
+ * Function: mosquitto_message_free_contents
+ *
+ * Free a mosquitto_message struct contents, leaving the struct unaffected.
+ *
+ * Parameters:
+ *	message - pointer to a mosquitto_message struct to free its contents.
+ *
+ * See Also:
+ * 	<mosquitto_message_copy>, <mosquitto_message_free>
+ */
+libmosq_EXPORT void mosquitto_message_free_contents(struct mosquitto_message *message);
+
+
+/* ======================================================================
+ *
+ * Section: Network loop (managed by libmosquitto)
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_loop
+ *
+ * The main network loop for the client. You must call this frequently in order
+ * to keep communications between the client and broker working. If incoming
+ * data is present it will then be processed. Outgoing commands, from e.g.
+ * <mosquitto_publish>, are normally sent immediately that their function is
+ * called, but this is not always possible. <mosquitto_loop> will also attempt
+ * to send any remaining outgoing messages, which also includes commands that
+ * are part of the flow for messages with QoS>0.
+ *
+ * An alternative approach is to use <mosquitto_loop_start> to run the client
+ * loop in its own thread.
+ *
+ * This calls select() to monitor the client network socket. If you want to
+ * integrate mosquitto client operation with your own select() call, use
+ * <mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write> and
+ * <mosquitto_loop_misc>.
+ *
+ * Threads:
+ *
+ * Parameters:
+ *	mosq -        a valid mosquitto instance.
+ *	timeout -     Maximum number of milliseconds to wait for network activity
+ *	              in the select() call before timing out. Set to 0 for instant
+ *	              return.  Set negative to use the default of 1000ms.
+ *	max_packets - this parameter is currently unused and should be set to 1 for
+ *	              future compatibility.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -   on success.
+ * 	MOSQ_ERR_INVAL -     if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -     if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -   if the client isn't connected to a broker.
+ *  MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ *	MOSQ_ERR_PROTOCOL -  if there is a protocol error communicating with the
+ *                       broker.
+ * 	MOSQ_ERR_ERRNO -     if a system call returned an error. The variable errno
+ *                       contains the error code, even on Windows.
+ *                       Use strerror_r() where available or FormatMessage() on
+ *                       Windows.
+ * See Also:
+ *	<mosquitto_loop_forever>, <mosquitto_loop_start>, <mosquitto_loop_stop>
+ */
+libmosq_EXPORT int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets);
+
+/*
+ * Function: mosquitto_loop_forever
+ *
+ * This function call loop() for you in an infinite blocking loop. It is useful
+ * for the case where you only want to run the MQTT client loop in your
+ * program.
+ *
+ * It handles reconnecting in case server connection is lost. If you call
+ * mosquitto_disconnect() in a callback it will return.
+ *
+ * Parameters:
+ *  mosq - a valid mosquitto instance.
+ *	timeout -     Maximum number of milliseconds to wait for network activity
+ *	              in the select() call before timing out. Set to 0 for instant
+ *	              return.  Set negative to use the default of 1000ms.
+ *	max_packets - this parameter is currently unused and should be set to 1 for
+ *	              future compatibility.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -   on success.
+ * 	MOSQ_ERR_INVAL -     if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -     if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -   if the client isn't connected to a broker.
+ *  MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ *	MOSQ_ERR_PROTOCOL -  if there is a protocol error communicating with the
+ *                       broker.
+ * 	MOSQ_ERR_ERRNO -     if a system call returned an error. The variable errno
+ *                       contains the error code, even on Windows.
+ *                       Use strerror_r() where available or FormatMessage() on
+ *                       Windows.
+ *
+ * See Also:
+ *	<mosquitto_loop>, <mosquitto_loop_start>
+ */
+libmosq_EXPORT int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets);
+
+/*
+ * Function: mosquitto_loop_start
+ *
+ * This is part of the threaded client interface. Call this once to start a new
+ * thread to process network traffic. This provides an alternative to
+ * repeatedly calling <mosquitto_loop> yourself.
+ *
+ * Parameters:
+ *  mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -       on success.
+ * 	MOSQ_ERR_INVAL -         if the input parameters were invalid.
+ *	MOSQ_ERR_NOT_SUPPORTED - if thread support is not available.
+ *
+ * See Also:
+ *	<mosquitto_connect_async>, <mosquitto_loop>, <mosquitto_loop_forever>, <mosquitto_loop_stop>
+ */
+libmosq_EXPORT int mosquitto_loop_start(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_loop_stop
+ *
+ * This is part of the threaded client interface. Call this once to stop the
+ * network thread previously created with <mosquitto_loop_start>. This call
+ * will block until the network thread finishes. For the network thread to end,
+ * you must have previously called <mosquitto_disconnect> or have set the force
+ * parameter to true.
+ *
+ * Parameters:
+ *  mosq - a valid mosquitto instance.
+ *	force - set to true to force thread cancellation. If false,
+ *	        <mosquitto_disconnect> must have already been called.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -       on success.
+ * 	MOSQ_ERR_INVAL -         if the input parameters were invalid.
+ *	MOSQ_ERR_NOT_SUPPORTED - if thread support is not available.
+ *
+ * See Also:
+ *	<mosquitto_loop>, <mosquitto_loop_start>
+ */
+libmosq_EXPORT int mosquitto_loop_stop(struct mosquitto *mosq, bool force);
+
+
+/* ======================================================================
+ *
+ * Section: Network loop (for use in other event loops)
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_loop_read
+ *
+ * Carry out network read operations.
+ * This should only be used if you are not using mosquitto_loop() and are
+ * monitoring the client network socket for activity yourself.
+ *
+ * Parameters:
+ *	mosq -        a valid mosquitto instance.
+ *	max_packets - this parameter is currently unused and should be set to 1 for
+ *	              future compatibility.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -   on success.
+ * 	MOSQ_ERR_INVAL -     if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -     if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -   if the client isn't connected to a broker.
+ *  MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ *	MOSQ_ERR_PROTOCOL -  if there is a protocol error communicating with the
+ *                       broker.
+ * 	MOSQ_ERR_ERRNO -     if a system call returned an error. The variable errno
+ *                       contains the error code, even on Windows.
+ *                       Use strerror_r() where available or FormatMessage() on
+ *                       Windows.
+ *
+ * See Also:
+ *	<mosquitto_socket>, <mosquitto_loop_write>, <mosquitto_loop_misc>
+ */
+libmosq_EXPORT int mosquitto_loop_read(struct mosquitto *mosq, int max_packets);
+
+/*
+ * Function: mosquitto_loop_write
+ *
+ * Carry out network write operations.
+ * This should only be used if you are not using mosquitto_loop() and are
+ * monitoring the client network socket for activity yourself.
+ *
+ * Parameters:
+ *	mosq -        a valid mosquitto instance.
+ *	max_packets - this parameter is currently unused and should be set to 1 for
+ *	              future compatibility.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -   on success.
+ * 	MOSQ_ERR_INVAL -     if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -     if an out of memory condition occurred.
+ * 	MOSQ_ERR_NO_CONN -   if the client isn't connected to a broker.
+ *  MOSQ_ERR_CONN_LOST - if the connection to the broker was lost.
+ *	MOSQ_ERR_PROTOCOL -  if there is a protocol error communicating with the
+ *                       broker.
+ * 	MOSQ_ERR_ERRNO -     if a system call returned an error. The variable errno
+ *                       contains the error code, even on Windows.
+ *                       Use strerror_r() where available or FormatMessage() on
+ *                       Windows.
+ *
+ * See Also:
+ *	<mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_misc>, <mosquitto_want_write>
+ */
+libmosq_EXPORT int mosquitto_loop_write(struct mosquitto *mosq, int max_packets);
+
+/*
+ * Function: mosquitto_loop_misc
+ *
+ * Carry out miscellaneous operations required as part of the network loop.
+ * This should only be used if you are not using mosquitto_loop() and are
+ * monitoring the client network socket for activity yourself.
+ *
+ * This function deals with handling PINGs and checking whether messages need
+ * to be retried, so should be called fairly frequently.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -   on success.
+ * 	MOSQ_ERR_INVAL -     if the input parameters were invalid.
+ * 	MOSQ_ERR_NO_CONN -   if the client isn't connected to a broker.
+ *
+ * See Also:
+ *	<mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write>
+ */
+libmosq_EXPORT int mosquitto_loop_misc(struct mosquitto *mosq);
+
+
+/* ======================================================================
+ *
+ * Section: Network loop (helper functions)
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_socket
+ *
+ * Return the socket handle for a mosquitto instance. Useful if you want to
+ * include a mosquitto client in your own select() calls.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ *	The socket for the mosquitto client or -1 on failure.
+ */
+libmosq_EXPORT int mosquitto_socket(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_want_write
+ *
+ * Returns true if there is data ready to be written on the socket.
+ *
+ * Parameters:
+ *	mosq - a valid mosquitto instance.
+ *
+ * See Also:
+ *	<mosquitto_socket>, <mosquitto_loop_read>, <mosquitto_loop_write>
+ */
+libmosq_EXPORT bool mosquitto_want_write(struct mosquitto *mosq);
+
+/*
+ * Function: mosquitto_threaded_set
+ *
+ * Used to tell the library that your application is using threads, but not
+ * using <mosquitto_loop_start>. The library operates slightly differently when
+ * not in threaded mode in order to simplify its operation. If you are managing
+ * your own threads and do not use this function you will experience crashes
+ * due to race conditions.
+ *
+ * When using <mosquitto_loop_start>, this is set automatically.
+ *
+ * Parameters:
+ *  mosq -     a valid mosquitto instance.
+ *  threaded - true if your application is using threads, false otherwise.
+ */
+libmosq_EXPORT int mosquitto_threaded_set(struct mosquitto *mosq, bool threaded);
+
+
+/* ======================================================================
+ *
+ * Section: Client options
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_opts_set
+ *
+ * Used to set options for the client.
+ *
+ * This function is deprecated, the replacement <mosquitto_int_option> and
+ * <mosquitto_void_option> functions should be used instead.
+ *
+ * Parameters:
+ *	mosq -   a valid mosquitto instance.
+ *	option - the option to set.
+ *	value -  the option specific value.
+ *
+ * Options:
+ *	MOSQ_OPT_PROTOCOL_VERSION
+ *	          Value must be an int, set to either MQTT_PROTOCOL_V31 or
+ *	          MQTT_PROTOCOL_V311. Must be set before the client connects.
+ *	          Defaults to MQTT_PROTOCOL_V31.
+ *
+ *	MOSQ_OPT_SSL_CTX
+ *	          Pass an openssl SSL_CTX to be used when creating TLS connections
+ *	          rather than libmosquitto creating its own.  This must be called
+ *	          before connecting to have any effect. If you use this option, the
+ *	          onus is on you to ensure that you are using secure settings.
+ *	          Setting to NULL means that libmosquitto will use its own SSL_CTX
+ *	          if TLS is to be used.
+ *	          This option is only available for openssl 1.1.0 and higher.
+ *
+ *	MOSQ_OPT_SSL_CTX_WITH_DEFAULTS
+ *	          Value must be an int set to 1 or 0. If set to 1, then the user
+ *	          specified SSL_CTX passed in using MOSQ_OPT_SSL_CTX will have the
+ *	          default options applied to it. This means that you only need to
+ *	          change the values that are relevant to you. If you use this
+ *	          option then you must configure the TLS options as normal, i.e.
+ *	          you should use <mosquitto_tls_set> to configure the cafile/capath
+ *	          as a minimum.
+ *	          This option is only available for openssl 1.1.0 and higher.
+ */
+libmosq_EXPORT int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t option, void *value);
+
+/*
+ * Function: mosquitto_int_option
+ *
+ * Used to set integer options for the client.
+ *
+ * Parameters:
+ *	mosq -   a valid mosquitto instance.
+ *	option - the option to set.
+ *	value -  the option specific value.
+ *
+ * Options:
+ *	MOSQ_OPT_PROTOCOL_VERSION
+ *	          Value must be set to either MQTT_PROTOCOL_V31,
+ *	          MQTT_PROTOCOL_V311, or MQTT_PROTOCOL_V5. Must be set before the
+ *	          client connects.  Defaults to MQTT_PROTOCOL_V311.
+ *
+ *	MOSQ_OPT_RECEIVE_MAXIMUM
+ *	          Value can be set between 1 and 65535 inclusive, and represents
+ *	          the maximum number of incoming QoS 1 and QoS 2 messages that this
+ *	          client wants to process at once. Defaults to 20. This option is
+ *	          not valid for MQTT v3.1 or v3.1.1 clients.
+ *	          Note that if the MQTT_PROP_RECEIVE_MAXIMUM property is in the
+ *	          proplist passed to mosquitto_connect_v5(), then that property
+ *	          will override this option. Using this option is the recommended
+ *	          method however.
+ *
+ *	MOSQ_OPT_SEND_MAXIMUM
+ *	          Value can be set between 1 and 65535 inclusive, and represents
+ *	          the maximum number of outgoing QoS 1 and QoS 2 messages that this
+ *	          client will attempt to have "in flight" at once. Defaults to 20.
+ *	          This option is not valid for MQTT v3.1 or v3.1.1 clients.
+ *	          Note that if the broker being connected to sends a
+ *	          MQTT_PROP_RECEIVE_MAXIMUM property that has a lower value than
+ *	          this option, then the broker provided value will be used.
+ *
+ *	MOSQ_OPT_SSL_CTX_WITH_DEFAULTS
+ *	          If value is set to a non zero value, then the user specified
+ *	          SSL_CTX passed in using MOSQ_OPT_SSL_CTX will have the default
+ *	          options applied to it. This means that you only need to change
+ *	          the values that are relevant to you. If you use this option then
+ *	          you must configure the TLS options as normal, i.e.  you should
+ *	          use <mosquitto_tls_set> to configure the cafile/capath as a
+ *	          minimum.
+ *	          This option is only available for openssl 1.1.0 and higher.
+ *	MOSQ_OPT_TLS_OCSP_REQUIRED
+ *	          Set whether OCSP checking on TLS connections is required. Set to
+ *	          1 to enable checking, or 0 (the default) for no checking.
+ */
+libmosq_EXPORT int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t option, int value);
+
+
+/*
+ * Function: mosquitto_void_option
+ *
+ * Used to set void* options for the client.
+ *
+ * Parameters:
+ *	mosq -   a valid mosquitto instance.
+ *	option - the option to set.
+ *	value -  the option specific value.
+ *
+ * Options:
+ *	MOSQ_OPT_SSL_CTX
+ *	          Pass an openssl SSL_CTX to be used when creating TLS connections
+ *	          rather than libmosquitto creating its own.  This must be called
+ *	          before connecting to have any effect. If you use this option, the
+ *	          onus is on you to ensure that you are using secure settings.
+ *	          Setting to NULL means that libmosquitto will use its own SSL_CTX
+ *	          if TLS is to be used.
+ *	          This option is only available for openssl 1.1.0 and higher.
+ */
+libmosq_EXPORT int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value);
+
+
+/*
+ * Function: mosquitto_reconnect_delay_set
+ *
+ * Control the behaviour of the client when it has unexpectedly disconnected in
+ * <mosquitto_loop_forever> or after <mosquitto_loop_start>. The default
+ * behaviour if this function is not used is to repeatedly attempt to reconnect
+ * with a delay of 1 second until the connection succeeds.
+ *
+ * Use reconnect_delay parameter to change the delay between successive
+ * reconnection attempts. You may also enable exponential backoff of the time
+ * between reconnections by setting reconnect_exponential_backoff to true and
+ * set an upper bound on the delay with reconnect_delay_max.
+ *
+ * Example 1:
+ *	delay=2, delay_max=10, exponential_backoff=False
+ *	Delays would be: 2, 4, 6, 8, 10, 10, ...
+ *
+ * Example 2:
+ *	delay=3, delay_max=30, exponential_backoff=True
+ *	Delays would be: 3, 6, 12, 24, 30, 30, ...
+ *
+ * Parameters:
+ *  mosq -                          a valid mosquitto instance.
+ *  reconnect_delay -               the number of seconds to wait between
+ *                                  reconnects.
+ *  reconnect_delay_max -           the maximum number of seconds to wait
+ *                                  between reconnects.
+ *  reconnect_exponential_backoff - use exponential backoff between
+ *                                  reconnect attempts. Set to true to enable
+ *                                  exponential backoff.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
+
+/*
+ * Function: mosquitto_max_inflight_messages_set
+ *
+ * This function is deprected. Use the <mosquitto_int_option> function with the
+ * MOSQ_OPT_SEND_MAXIMUM option instead.
+ *
+ * Set the number of QoS 1 and 2 messages that can be "in flight" at one time.
+ * An in flight message is part way through its delivery flow. Attempts to send
+ * further messages with <mosquitto_publish> will result in the messages being
+ * queued until the number of in flight messages reduces.
+ *
+ * A higher number here results in greater message throughput, but if set
+ * higher than the maximum in flight messages on the broker may lead to
+ * delays in the messages being acknowledged.
+ *
+ * Set to 0 for no maximum.
+ *
+ * Parameters:
+ *  mosq -                  a valid mosquitto instance.
+ *  max_inflight_messages - the maximum number of inflight messages. Defaults
+ *                          to 20.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_max_inflight_messages_set(struct mosquitto *mosq, unsigned int max_inflight_messages);
+
+/*
+ * Function: mosquitto_message_retry_set
+ *
+ * This function now has no effect.
+ */
+libmosq_EXPORT void mosquitto_message_retry_set(struct mosquitto *mosq, unsigned int message_retry);
+
+/*
+ * Function: mosquitto_user_data_set
+ *
+ * When <mosquitto_new> is called, the pointer given as the "obj" parameter
+ * will be passed to the callbacks as user data. The <mosquitto_user_data_set>
+ * function allows this obj parameter to be updated at any time. This function
+ * will not modify the memory pointed to by the current user data pointer. If
+ * it is dynamically allocated memory you must free it yourself.
+ *
+ * Parameters:
+ *  mosq - a valid mosquitto instance.
+ * 	obj -  A user pointer that will be passed as an argument to any callbacks
+ * 	       that are specified.
+ */
+libmosq_EXPORT void mosquitto_user_data_set(struct mosquitto *mosq, void *obj);
+
+/* Function: mosquitto_userdata
+ *
+ * Retrieve the "userdata" variable for a mosquitto client.
+ *
+ * Parameters:
+ * 	mosq - a valid mosquitto instance.
+ *
+ * Returns:
+ *	A pointer to the userdata member variable.
+ */
+libmosq_EXPORT void *mosquitto_userdata(struct mosquitto *mosq);
+
+
+/* ======================================================================
+ *
+ * Section: TLS support
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_tls_set
+ *
+ * Configure the client for certificate based SSL/TLS support. Must be called
+ * before <mosquitto_connect>.
+ *
+ * Cannot be used in conjunction with <mosquitto_tls_psk_set>.
+ *
+ * Define the Certificate Authority certificates to be trusted (ie. the server
+ * certificate must be signed with one of these certificates) using cafile.
+ *
+ * If the server you are connecting to requires clients to provide a
+ * certificate, define certfile and keyfile with your client certificate and
+ * private key. If your private key is encrypted, provide a password callback
+ * function or you will have to enter the password at the command line.
+ *
+ * Parameters:
+ *  mosq -        a valid mosquitto instance.
+ *  cafile -      path to a file containing the PEM encoded trusted CA
+ *                certificate files. Either cafile or capath must not be NULL.
+ *  capath -      path to a directory containing the PEM encoded trusted CA
+ *                certificate files. See mosquitto.conf for more details on
+ *                configuring this directory. Either cafile or capath must not
+ *                be NULL.
+ *  certfile -    path to a file containing the PEM encoded certificate file
+ *                for this client. If NULL, keyfile must also be NULL and no
+ *                client certificate will be used.
+ *  keyfile -     path to a file containing the PEM encoded private key for
+ *                this client. If NULL, certfile must also be NULL and no
+ *                client certificate will be used.
+ *  pw_callback - if keyfile is encrypted, set pw_callback to allow your client
+ *                to pass the correct password for decryption. If set to NULL,
+ *                the password must be entered on the command line.
+ *                Your callback must write the password into "buf", which is
+ *                "size" bytes long. The return value must be the length of the
+ *                password. "userdata" will be set to the calling mosquitto
+ *                instance. The mosquitto userdata member variable can be
+ *                retrieved using <mosquitto_userdata>.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * See Also:
+ *	<mosquitto_tls_opts_set>, <mosquitto_tls_psk_set>,
+ *	<mosquitto_tls_insecure_set>, <mosquitto_userdata>
+ */
+libmosq_EXPORT int mosquitto_tls_set(struct mosquitto *mosq,
+		const char *cafile, const char *capath,
+		const char *certfile, const char *keyfile,
+		int (*pw_callback)(char *buf, int size, int rwflag, void *userdata));
+
+/*
+ * Function: mosquitto_tls_insecure_set
+ *
+ * Configure verification of the server hostname in the server certificate. If
+ * value is set to true, it is impossible to guarantee that the host you are
+ * connecting to is not impersonating your server. This can be useful in
+ * initial server testing, but makes it possible for a malicious third party to
+ * impersonate your server through DNS spoofing, for example.
+ * Do not use this function in a real system. Setting value to true makes the
+ * connection encryption pointless.
+ * Must be called before <mosquitto_connect>.
+ *
+ * Parameters:
+ *  mosq -  a valid mosquitto instance.
+ *  value - if set to false, the default, certificate hostname checking is
+ *          performed. If set to true, no hostname checking is performed and
+ *          the connection is insecure.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ *
+ * See Also:
+ *	<mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value);
+
+/*
+ * Function: mosquitto_tls_opts_set
+ *
+ * Set advanced SSL/TLS options. Must be called before <mosquitto_connect>.
+ *
+ * Parameters:
+ *  mosq -        a valid mosquitto instance.
+ *	cert_reqs -   an integer defining the verification requirements the client
+ *	              will impose on the server. This can be one of:
+ *	              * SSL_VERIFY_NONE (0): the server will not be verified in any way.
+ *	              * SSL_VERIFY_PEER (1): the server certificate will be verified
+ *	                and the connection aborted if the verification fails.
+ *	              The default and recommended value is SSL_VERIFY_PEER. Using
+ *	              SSL_VERIFY_NONE provides no security.
+ *	tls_version - the version of the SSL/TLS protocol to use as a string. If NULL,
+ *	              the default value is used. The default value and the
+ *	              available values depend on the version of openssl that the
+ *	              library was compiled against. For openssl >= 1.0.1, the
+ *	              available options are tlsv1.2, tlsv1.1 and tlsv1, with tlv1.2
+ *	              as the default. For openssl < 1.0.1, only tlsv1 is available.
+ *	ciphers -     a string describing the ciphers available for use. See the
+ *	              "openssl ciphers" tool for more information. If NULL, the
+ *	              default ciphers will be used.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * See Also:
+ *	<mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers);
+
+/*
+ * Function: mosquitto_tls_psk_set
+ *
+ * Configure the client for pre-shared-key based TLS support. Must be called
+ * before <mosquitto_connect>.
+ *
+ * Cannot be used in conjunction with <mosquitto_tls_set>.
+ *
+ * Parameters:
+ *  mosq -     a valid mosquitto instance.
+ *  psk -      the pre-shared-key in hex format with no leading "0x".
+ *  identity - the identity of this client. May be used as the username
+ *             depending on the server settings.
+ *	ciphers -  a string describing the PSK ciphers available for use. See the
+ *	           "openssl ciphers" tool for more information. If NULL, the
+ *	           default ciphers will be used.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ *
+ * See Also:
+ *	<mosquitto_tls_set>
+ */
+libmosq_EXPORT int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers);
+
+
+/* ======================================================================
+ *
+ * Section: Callbacks
+ *
+ * ====================================================================== */
+/*
+ * Function: mosquitto_connect_callback_set
+ *
+ * Set the connect callback. This is called when the broker sends a CONNACK
+ * message in response to a connection.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_connect - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, int rc)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj - the user data provided in <mosquitto_new>
+ *  rc -  the return code of the connection response, one of:
+ *
+ * * 0 - success
+ * * 1 - connection refused (unacceptable protocol version)
+ * * 2 - connection refused (identifier rejected)
+ * * 3 - connection refused (broker unavailable)
+ * * 4-255 - reserved for future use
+ */
+libmosq_EXPORT void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_connect_with_flags_callback_set
+ *
+ * Set the connect callback. This is called when the broker sends a CONNACK
+ * message in response to a connection.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_connect - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, int rc)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj - the user data provided in <mosquitto_new>
+ *  rc -  the return code of the connection response, one of:
+ *  flags - the connect flags.
+ *
+ * * 0 - success
+ * * 1 - connection refused (unacceptable protocol version)
+ * * 2 - connection refused (identifier rejected)
+ * * 3 - connection refused (broker unavailable)
+ * * 4-255 - reserved for future use
+ */
+libmosq_EXPORT void mosquitto_connect_with_flags_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int));
+
+/*
+ * Function: mosquitto_connect_v5_callback_set
+ *
+ * Set the connect callback. This is called when the broker sends a CONNACK
+ * message in response to a connection.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_connect - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, int rc)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj - the user data provided in <mosquitto_new>
+ *  rc -  the return code of the connection response, one of:
+ * * 0 - success
+ * * 1 - connection refused (unacceptable protocol version)
+ * * 2 - connection refused (identifier rejected)
+ * * 3 - connection refused (broker unavailable)
+ * * 4-255 - reserved for future use
+ *  flags - the connect flags.
+ *  props - list of MQTT 5 properties, or NULL
+ *
+ */
+libmosq_EXPORT void mosquitto_connect_v5_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int, int, const mosquitto_property *props));
+
+/*
+ * Function: mosquitto_disconnect_callback_set
+ *
+ * Set the disconnect callback. This is called when the broker has received the
+ * DISCONNECT command and has disconnected the client.
+ *
+ * Parameters:
+ *  mosq -          a valid mosquitto instance.
+ *  on_disconnect - a callback function in the following form:
+ *                  void callback(struct mosquitto *mosq, void *obj)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj -  the user data provided in <mosquitto_new>
+ *  rc -   integer value indicating the reason for the disconnect. A value of 0
+ *         means the client has called <mosquitto_disconnect>. Any other value
+ *         indicates that the disconnect is unexpected.
+ */
+libmosq_EXPORT void mosquitto_disconnect_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_disconnect_v5_callback_set
+ *
+ * Set the disconnect callback. This is called when the broker has received the
+ * DISCONNECT command and has disconnected the client.
+ *
+ * Parameters:
+ *  mosq -          a valid mosquitto instance.
+ *  on_disconnect - a callback function in the following form:
+ *                  void callback(struct mosquitto *mosq, void *obj)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj -  the user data provided in <mosquitto_new>
+ *  rc -   integer value indicating the reason for the disconnect. A value of 0
+ *         means the client has called <mosquitto_disconnect>. Any other value
+ *         indicates that the disconnect is unexpected.
+ *  props - list of MQTT 5 properties, or NULL
+ */
+libmosq_EXPORT void mosquitto_disconnect_v5_callback_set(struct mosquitto *mosq, void (*on_disconnect)(struct mosquitto *, void *, int, const mosquitto_property *));
+
+/*
+ * Function: mosquitto_publish_callback_set
+ *
+ * Set the publish callback. This is called when a message initiated with
+ * <mosquitto_publish> has been sent to the broker successfully.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_publish - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, int mid)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj -  the user data provided in <mosquitto_new>
+ *  mid -  the message id of the sent message.
+ */
+libmosq_EXPORT void mosquitto_publish_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_publish_v5_callback_set
+ *
+ * Set the publish callback. This is called when a message initiated with
+ * <mosquitto_publish> has been sent to the broker. This callback will be
+ * called both if the message is sent successfully, or if the broker responded
+ * with an error, which will be reflected in the reason_code parameter.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_publish - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, int mid)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj -  the user data provided in <mosquitto_new>
+ *  mid -  the message id of the sent message.
+ *  reason_code - the MQTT 5 reason code
+ *  props - list of MQTT 5 properties, or NULL
+ */
+libmosq_EXPORT void mosquitto_publish_v5_callback_set(struct mosquitto *mosq, void (*on_publish)(struct mosquitto *, void *, int, int, const mosquitto_property *));
+
+/*
+ * Function: mosquitto_message_callback_set
+ *
+ * Set the message callback. This is called when a message is received from the
+ * broker.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_message - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
+ *
+ * Callback Parameters:
+ *  mosq -    the mosquitto instance making the callback.
+ *  obj -     the user data provided in <mosquitto_new>
+ *  message - the message data. This variable and associated memory will be
+ *            freed by the library after the callback completes. The client
+ *            should make copies of any of the data it requires.
+ *
+ * See Also:
+ * 	<mosquitto_message_copy>
+ */
+libmosq_EXPORT void mosquitto_message_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *));
+
+/*
+ * Function: mosquitto_message_v5_callback_set
+ *
+ * Set the message callback. This is called when a message is received from the
+ * broker.
+ *
+ * Parameters:
+ *  mosq -       a valid mosquitto instance.
+ *  on_message - a callback function in the following form:
+ *               void callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
+ *
+ * Callback Parameters:
+ *  mosq -    the mosquitto instance making the callback.
+ *  obj -     the user data provided in <mosquitto_new>
+ *  message - the message data. This variable and associated memory will be
+ *            freed by the library after the callback completes. The client
+ *            should make copies of any of the data it requires.
+ *  props - list of MQTT 5 properties, or NULL
+ *
+ * See Also:
+ * 	<mosquitto_message_copy>
+ */
+libmosq_EXPORT void mosquitto_message_v5_callback_set(struct mosquitto *mosq, void (*on_message)(struct mosquitto *, void *, const struct mosquitto_message *, const mosquitto_property *));
+
+/*
+ * Function: mosquitto_subscribe_callback_set
+ *
+ * Set the subscribe callback. This is called when the broker responds to a
+ * subscription request.
+ *
+ * Parameters:
+ *  mosq -         a valid mosquitto instance.
+ *  on_subscribe - a callback function in the following form:
+ *                 void callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
+ *
+ * Callback Parameters:
+ *  mosq -        the mosquitto instance making the callback.
+ *  obj -         the user data provided in <mosquitto_new>
+ *  mid -         the message id of the subscribe message.
+ *  qos_count -   the number of granted subscriptions (size of granted_qos).
+ *  granted_qos - an array of integers indicating the granted QoS for each of
+ *                the subscriptions.
+ */
+libmosq_EXPORT void mosquitto_subscribe_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *));
+
+/*
+ * Function: mosquitto_subscribe_v5_callback_set
+ *
+ * Set the subscribe callback. This is called when the broker responds to a
+ * subscription request.
+ *
+ * Parameters:
+ *  mosq -         a valid mosquitto instance.
+ *  on_subscribe - a callback function in the following form:
+ *                 void callback(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
+ *
+ * Callback Parameters:
+ *  mosq -        the mosquitto instance making the callback.
+ *  obj -         the user data provided in <mosquitto_new>
+ *  mid -         the message id of the subscribe message.
+ *  qos_count -   the number of granted subscriptions (size of granted_qos).
+ *  granted_qos - an array of integers indicating the granted QoS for each of
+ *                the subscriptions.
+ *  props - list of MQTT 5 properties, or NULL
+ */
+libmosq_EXPORT void mosquitto_subscribe_v5_callback_set(struct mosquitto *mosq, void (*on_subscribe)(struct mosquitto *, void *, int, int, const int *, const mosquitto_property *));
+
+/*
+ * Function: mosquitto_unsubscribe_callback_set
+ *
+ * Set the unsubscribe callback. This is called when the broker responds to a
+ * unsubscription request.
+ *
+ * Parameters:
+ *  mosq -           a valid mosquitto instance.
+ *  on_unsubscribe - a callback function in the following form:
+ *                   void callback(struct mosquitto *mosq, void *obj, int mid)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj -  the user data provided in <mosquitto_new>
+ *  mid -  the message id of the unsubscribe message.
+ */
+libmosq_EXPORT void mosquitto_unsubscribe_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int));
+
+/*
+ * Function: mosquitto_unsubscribe_v5_callback_set
+ *
+ * Set the unsubscribe callback. This is called when the broker responds to a
+ * unsubscription request.
+ *
+ * Parameters:
+ *  mosq -           a valid mosquitto instance.
+ *  on_unsubscribe - a callback function in the following form:
+ *                   void callback(struct mosquitto *mosq, void *obj, int mid)
+ *
+ * Callback Parameters:
+ *  mosq - the mosquitto instance making the callback.
+ *  obj -  the user data provided in <mosquitto_new>
+ *  mid -  the message id of the unsubscribe message.
+ *  props - list of MQTT 5 properties, or NULL
+ */
+libmosq_EXPORT void mosquitto_unsubscribe_v5_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int, const mosquitto_property *));
+
+/*
+ * Function: mosquitto_log_callback_set
+ *
+ * Set the logging callback. This should be used if you want event logging
+ * information from the client library.
+ *
+ *  mosq -   a valid mosquitto instance.
+ *  on_log - a callback function in the following form:
+ *           void callback(struct mosquitto *mosq, void *obj, int level, const char *str)
+ *
+ * Callback Parameters:
+ *  mosq -  the mosquitto instance making the callback.
+ *  obj -   the user data provided in <mosquitto_new>
+ *  level - the log message level from the values:
+ *	        MOSQ_LOG_INFO
+ *	        MOSQ_LOG_NOTICE
+ *	        MOSQ_LOG_WARNING
+ *	        MOSQ_LOG_ERR
+ *	        MOSQ_LOG_DEBUG
+ *	str -   the message string.
+ */
+libmosq_EXPORT void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mosquitto *, void *, int, const char *));
+
+/*
+ * Function: mosquitto_string_option
+ *
+ * Used to set const char* options for the client.
+ *
+ * Parameters:
+ *	mosq -   a valid mosquitto instance.
+ *	option - the option to set.
+ *	value -  the option specific value.
+ *
+ * Options:
+ *	MOSQ_OPT_TLS_ENGINE
+ *	          Configure the client for TLS Engine support. Pass a TLS Engine ID
+ *	          to be used when creating TLS connections.
+ *	          Must be set before <mosquitto_connect>.
+ *	MOSQ_OPT_TLS_KEYFORM
+ *            Configure the client to treat the keyfile differently depending
+ *            on its type.  Must be set before <mosquitto_connect>.
+ *	          Set as either "pem" or "engine", to determine from where the
+ *	          private key for a TLS connection will be obtained. Defaults to
+ *	          "pem", a normal private key file.
+ *	MOSQ_OPT_TLS_KPASS_SHA1
+ *	          Where the TLS Engine requires the use of a password to be
+ *	          accessed, this option allows a hex encoded SHA1 hash of the
+ *	          private key password to be passed to the engine directly.
+ *	          Must be set before <mosquitto_connect>.
+ *	MOSQ_OPT_TLS_ALPN
+ *	          If the broker being connected to has multiple services available
+ *	          on a single TLS port, such as both MQTT and WebSockets, use this
+ *	          option to configure the ALPN option for the connection.
+ */
+libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value);
+
+
+/*
+ * Function: mosquitto_reconnect_delay_set
+ *
+ * Control the behaviour of the client when it has unexpectedly disconnected in
+ * <mosquitto_loop_forever> or after <mosquitto_loop_start>. The default
+ * behaviour if this function is not used is to repeatedly attempt to reconnect
+ * with a delay of 1 second until the connection succeeds.
+ *
+ * Use reconnect_delay parameter to change the delay between successive
+ * reconnection attempts. You may also enable exponential backoff of the time
+ * between reconnections by setting reconnect_exponential_backoff to true and
+ * set an upper bound on the delay with reconnect_delay_max.
+ *
+ * Example 1:
+ *	delay=2, delay_max=10, exponential_backoff=False
+ *	Delays would be: 2, 4, 6, 8, 10, 10, ...
+ *
+ * Example 2:
+ *	delay=3, delay_max=30, exponential_backoff=True
+ *	Delays would be: 3, 6, 12, 24, 30, 30, ...
+ *
+ * Parameters:
+ *  mosq -                          a valid mosquitto instance.
+ *  reconnect_delay -               the number of seconds to wait between
+ *                                  reconnects.
+ *  reconnect_delay_max -           the maximum number of seconds to wait
+ *                                  between reconnects.
+ *  reconnect_exponential_backoff - use exponential backoff between
+ *                                  reconnect attempts. Set to true to enable
+ *                                  exponential backoff.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success.
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ */
+libmosq_EXPORT int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
+
+
+/* =============================================================================
+ *
+ * Section: SOCKS5 proxy functions
+ *
+ * =============================================================================
+ */
+
+/*
+ * Function: mosquitto_socks5_set
+ *
+ * Configure the client to use a SOCKS5 proxy when connecting. Must be called
+ * before connecting. "None" and "username/password" authentication is
+ * supported.
+ *
+ * Parameters:
+ *   mosq - a valid mosquitto instance.
+ *   host - the SOCKS5 proxy host to connect to.
+ *   port - the SOCKS5 proxy port to use.
+ *   username - if not NULL, use this username when authenticating with the proxy.
+ *   password - if not NULL and username is not NULL, use this password when
+ *              authenticating with the proxy.
+ */
+libmosq_EXPORT int mosquitto_socks5_set(struct mosquitto *mosq, const char *host, int port, const char *username, const char *password);
+
+
+/* =============================================================================
+ *
+ * Section: Utility functions
+ *
+ * =============================================================================
+ */
+
+/*
+ * Function: mosquitto_strerror
+ *
+ * Call to obtain a const string description of a mosquitto error number.
+ *
+ * Parameters:
+ *	mosq_errno - a mosquitto error number.
+ *
+ * Returns:
+ *	A constant string describing the error.
+ */
+libmosq_EXPORT const char *mosquitto_strerror(int mosq_errno);
+
+/*
+ * Function: mosquitto_connack_string
+ *
+ * Call to obtain a const string description of an MQTT connection result.
+ *
+ * Parameters:
+ *	connack_code - an MQTT connection result.
+ *
+ * Returns:
+ *	A constant string describing the result.
+ */
+libmosq_EXPORT const char *mosquitto_connack_string(int connack_code);
+
+/*
+ * Function: mosquitto_reason_string
+ *
+ * Call to obtain a const string description of an MQTT reason code.
+ *
+ * Parameters:
+ *	reason_code - an MQTT reason code.
+ *
+ * Returns:
+ *	A constant string describing the reason.
+ */
+libmosq_EXPORT const char *mosquitto_reason_string(int reason_code);
+
+/* Function: mosquitto_string_to_command
+ *
+ * Take a string input representing an MQTT command and convert it to the
+ * libmosquitto integer representation.
+ *
+ * Parameters:
+ *   str - the string to parse.
+ *   cmd - pointer to an int, for the result.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - on an invalid input.
+ *
+ * Example:
+ *  mosquitto_string_to_command("CONNECT", &cmd);
+ *  // cmd == CMD_CONNECT
+ */
+libmosq_EXPORT int mosquitto_string_to_command(const char *str, int *cmd);
+
+/*
+ * Function: mosquitto_sub_topic_tokenise
+ *
+ * Tokenise a topic or subscription string into an array of strings
+ * representing the topic hierarchy.
+ *
+ * For example:
+ *
+ * subtopic: "a/deep/topic/hierarchy"
+ *
+ * Would result in:
+ *
+ * topics[0] = "a"
+ * topics[1] = "deep"
+ * topics[2] = "topic"
+ * topics[3] = "hierarchy"
+ *
+ * and:
+ *
+ * subtopic: "/a/deep/topic/hierarchy/"
+ *
+ * Would result in:
+ *
+ * topics[0] = NULL
+ * topics[1] = "a"
+ * topics[2] = "deep"
+ * topics[3] = "topic"
+ * topics[4] = "hierarchy"
+ *
+ * Parameters:
+ *	subtopic - the subscription/topic to tokenise
+ *	topics -   a pointer to store the array of strings
+ *	count -    an int pointer to store the number of items in the topics array.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS -        on success
+ * 	MOSQ_ERR_NOMEM -          if an out of memory condition occurred.
+ * 	MOSQ_ERR_MALFORMED_UTF8 - if the topic is not valid UTF-8
+ *
+ * Example:
+ *
+ * > char **topics;
+ * > int topic_count;
+ * > int i;
+ * >
+ * > mosquitto_sub_topic_tokenise("$SYS/broker/uptime", &topics, &topic_count);
+ * >
+ * > for(i=0; i<token_count; i++){
+ * >     printf("%d: %s\n", i, topics[i]);
+ * > }
+ *
+ * See Also:
+ *	<mosquitto_sub_topic_tokens_free>
+ */
+libmosq_EXPORT int mosquitto_sub_topic_tokenise(const char *subtopic, char ***topics, int *count);
+
+/*
+ * Function: mosquitto_sub_topic_tokens_free
+ *
+ * Free memory that was allocated in <mosquitto_sub_topic_tokenise>.
+ *
+ * Parameters:
+ *	topics - pointer to string array.
+ *	count - count of items in string array.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ *
+ * See Also:
+ *	<mosquitto_sub_topic_tokenise>
+ */
+libmosq_EXPORT int mosquitto_sub_topic_tokens_free(char ***topics, int count);
+
+/*
+ * Function: mosquitto_topic_matches_sub
+ * Function: mosquitto_topic_matches_sub2
+ *
+ * Check whether a topic matches a subscription.
+ *
+ * For example:
+ *
+ * foo/bar would match the subscription foo/# or +/bar
+ * non/matching would not match the subscription non/+/+
+ *
+ * Parameters:
+ *	sub - subscription string to check topic against.
+ *	sublen - length in bytes of sub string
+ *	topic - topic to check.
+ *	topiclen - length in bytes of topic string
+ *	result - bool pointer to hold result. Will be set to true if the topic
+ *	         matches the subscription.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ * 	MOSQ_ERR_INVAL -   if the input parameters were invalid.
+ * 	MOSQ_ERR_NOMEM -   if an out of memory condition occurred.
+ */
+libmosq_EXPORT int mosquitto_topic_matches_sub(const char *sub, const char *topic, bool *result);
+libmosq_EXPORT int mosquitto_topic_matches_sub2(const char *sub, size_t sublen, const char *topic, size_t topiclen, bool *result);
+
+/*
+ * Function: mosquitto_pub_topic_check
+ *
+ * Check whether a topic to be used for publishing is valid.
+ *
+ * This searches for + or # in a topic and checks its length.
+ *
+ * This check is already carried out in <mosquitto_publish> and
+ * <mosquitto_will_set>, there is no need to call it directly before them. It
+ * may be useful if you wish to check the validity of a topic in advance of
+ * making a connection for example.
+ *
+ * Parameters:
+ *   topic - the topic to check
+ *   topiclen - length of the topic in bytes
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS -        for a valid topic
+ *   MOSQ_ERR_INVAL -          if the topic contains a + or a #, or if it is too long.
+ * 	 MOSQ_ERR_MALFORMED_UTF8 - if sub or topic is not valid UTF-8
+ *
+ * See Also:
+ *   <mosquitto_sub_topic_check>
+ */
+libmosq_EXPORT int mosquitto_pub_topic_check(const char *topic);
+libmosq_EXPORT int mosquitto_pub_topic_check2(const char *topic, size_t topiclen);
+
+/*
+ * Function: mosquitto_sub_topic_check
+ *
+ * Check whether a topic to be used for subscribing is valid.
+ *
+ * This searches for + or # in a topic and checks that they aren't in invalid
+ * positions, such as with foo/#/bar, foo/+bar or foo/bar#, and checks its
+ * length.
+ *
+ * This check is already carried out in <mosquitto_subscribe> and
+ * <mosquitto_unsubscribe>, there is no need to call it directly before them.
+ * It may be useful if you wish to check the validity of a topic in advance of
+ * making a connection for example.
+ *
+ * Parameters:
+ *   topic - the topic to check
+ *   topiclen - the length in bytes of the topic
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS -        for a valid topic
+ *   MOSQ_ERR_INVAL -          if the topic contains a + or a # that is in an
+ *                             invalid position, or if it is too long.
+ * 	 MOSQ_ERR_MALFORMED_UTF8 - if topic is not valid UTF-8
+ *
+ * See Also:
+ *   <mosquitto_sub_topic_check>
+ */
+libmosq_EXPORT int mosquitto_sub_topic_check(const char *topic);
+libmosq_EXPORT int mosquitto_sub_topic_check2(const char *topic, size_t topiclen);
+
+
+struct libmosquitto_will {
+	char *topic;
+	void *payload;
+	int payloadlen;
+	int qos;
+	bool retain;
+};
+
+struct libmosquitto_auth {
+	char *username;
+	char *password;
+};
+
+struct libmosquitto_tls {
+	char *cafile;
+	char *capath;
+	char *certfile;
+	char *keyfile;
+	char *ciphers;
+	char *tls_version;
+	int (*pw_callback)(char *buf, int size, int rwflag, void *userdata);
+	int cert_reqs;
+};
+
+/*
+ * Function: mosquitto_subscribe_simple
+ *
+ * Helper function to make subscribing to a topic and retrieving some messages
+ * very straightforward.
+ *
+ * This connects to a broker, subscribes to a topic, waits for msg_count
+ * messages to be received, then returns after disconnecting cleanly.
+ *
+ * Parameters:
+ *   messages - pointer to a "struct mosquitto_message *". The received
+ *              messages will be returned here. On error, this will be set to
+ *              NULL.
+ *   msg_count - the number of messages to retrieve.
+ *   want_retained - if set to true, stale retained messages will be treated as
+ *                   normal messages with regards to msg_count. If set to
+ *                   false, they will be ignored.
+ *   topic - the subscription topic to use (wildcards are allowed).
+ *   qos - the qos to use for the subscription.
+ *   host - the broker to connect to.
+ *   port - the network port the broker is listening on.
+ *   client_id - the client id to use, or NULL if a random client id should be
+ *               generated.
+ *   keepalive - the MQTT keepalive value.
+ *   clean_session - the MQTT clean session flag.
+ *   username - the username string, or NULL for no username authentication.
+ *   password - the password string, or NULL for an empty password.
+ *   will - a libmosquitto_will struct containing will information, or NULL for
+ *          no will.
+ *   tls - a libmosquitto_tls struct containing TLS related parameters, or NULL
+ *         for no use of TLS.
+ *
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS - on success
+ *   >0 - on error.
+ */
+libmosq_EXPORT int mosquitto_subscribe_simple(
+		struct mosquitto_message **messages,
+		int msg_count,
+		bool want_retained,
+		const char *topic,
+		int qos,
+		const char *host,
+		int port,
+		const char *client_id,
+		int keepalive,
+		bool clean_session,
+		const char *username,
+		const char *password,
+		const struct libmosquitto_will *will,
+		const struct libmosquitto_tls *tls);
+
+
+/*
+ * Function: mosquitto_subscribe_callback
+ *
+ * Helper function to make subscribing to a topic and processing some messages
+ * very straightforward.
+ *
+ * This connects to a broker, subscribes to a topic, then passes received
+ * messages to a user provided callback. If the callback returns a 1, it then
+ * disconnects cleanly and returns.
+ *
+ * Parameters:
+ *   callback - a callback function in the following form:
+ *              int callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message)
+ *              Note that this is the same as the normal on_message callback,
+ *              except that it returns an int.
+ *   userdata - user provided pointer that will be passed to the callback.
+ *   topic - the subscription topic to use (wildcards are allowed).
+ *   qos - the qos to use for the subscription.
+ *   host - the broker to connect to.
+ *   port - the network port the broker is listening on.
+ *   client_id - the client id to use, or NULL if a random client id should be
+ *               generated.
+ *   keepalive - the MQTT keepalive value.
+ *   clean_session - the MQTT clean session flag.
+ *   username - the username string, or NULL for no username authentication.
+ *   password - the password string, or NULL for an empty password.
+ *   will - a libmosquitto_will struct containing will information, or NULL for
+ *          no will.
+ *   tls - a libmosquitto_tls struct containing TLS related parameters, or NULL
+ *         for no use of TLS.
+ *
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS - on success
+ *   >0 - on error.
+ */
+libmosq_EXPORT int mosquitto_subscribe_callback(
+		int (*callback)(struct mosquitto *, void *, const struct mosquitto_message *),
+		void *userdata,
+		const char *topic,
+		int qos,
+		const char *host,
+		int port,
+		const char *client_id,
+		int keepalive,
+		bool clean_session,
+		const char *username,
+		const char *password,
+		const struct libmosquitto_will *will,
+		const struct libmosquitto_tls *tls);
+
+
+/*
+ * Function: mosquitto_validate_utf8
+ *
+ * Helper function to validate whether a UTF-8 string is valid, according to
+ * the UTF-8 spec and the MQTT additions.
+ *
+ * Parameters:
+ *   str - a string to check
+ *   len - the length of the string in bytes
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS -        on success
+ *   MOSQ_ERR_INVAL -          if str is NULL or len<0 or len>65536
+ *   MOSQ_ERR_MALFORMED_UTF8 - if str is not valid UTF-8
+ */
+libmosq_EXPORT int mosquitto_validate_utf8(const char *str, int len);
+
+
+/* =============================================================================
+ *
+ * Section: Properties
+ *
+ * =============================================================================
+ */
+
+
+/*
+ * Function: mosquitto_property_add_byte
+ *
+ * Add a new byte property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - integer value for the new property
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_byte(&proplist, MQTT_PROP_PAYLOAD_FORMAT_IDENTIFIER, 1);
+ */
+libmosq_EXPORT int mosquitto_property_add_byte(mosquitto_property **proplist, int identifier, uint8_t value);
+
+/*
+ * Function: mosquitto_property_add_int16
+ *
+ * Add a new int16 property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_RECEIVE_MAXIMUM)
+ *	value - integer value for the new property
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_int16(&proplist, MQTT_PROP_RECEIVE_MAXIMUM, 1000);
+ */
+libmosq_EXPORT int mosquitto_property_add_int16(mosquitto_property **proplist, int identifier, uint16_t value);
+
+/*
+ * Function: mosquitto_property_add_int32
+ *
+ * Add a new int32 property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_MESSAGE_EXPIRY_INTERVAL)
+ *	value - integer value for the new property
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_int32(&proplist, MQTT_PROP_MESSAGE_EXPIRY_INTERVAL, 86400);
+ */
+libmosq_EXPORT int mosquitto_property_add_int32(mosquitto_property **proplist, int identifier, uint32_t value);
+
+/*
+ * Function: mosquitto_property_add_varint
+ *
+ * Add a new varint property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_SUBSCRIPTION_IDENTIFIER)
+ *	value - integer value for the new property
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_varint(&proplist, MQTT_PROP_SUBSCRIPTION_IDENTIFIER, 1);
+ */
+libmosq_EXPORT int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier, uint32_t value);
+
+/*
+ * Function: mosquitto_property_add_binary
+ *
+ * Add a new binary property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to the property data
+ *	len - length of property data in bytes
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_binary(&proplist, MQTT_PROP_AUTHENTICATION_DATA, auth_data, auth_data_len);
+ */
+libmosq_EXPORT int mosquitto_property_add_binary(mosquitto_property **proplist, int identifier, const void *value, uint16_t len);
+
+/*
+ * Function: mosquitto_property_add_string
+ *
+ * Add a new string property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_CONTENT_TYPE)
+ *	value - string value for the new property, must be UTF-8 and zero terminated
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, if value is NULL, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *	MOSQ_ERR_MALFORMED_UTF8 - value is not valid UTF-8.
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_string(&proplist, MQTT_PROP_CONTENT_TYPE, "application/json");
+ */
+libmosq_EXPORT int mosquitto_property_add_string(mosquitto_property **proplist, int identifier, const char *value);
+
+/*
+ * Function: mosquitto_property_add_string_pair
+ *
+ * Add a new string pair property to a property list.
+ *
+ * If *proplist == NULL, a new list will be created, otherwise the new property
+ * will be appended to the list.
+ *
+ * Parameters:
+ *	proplist - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_USER_PROPERTY)
+ *	name - string name for the new property, must be UTF-8 and zero terminated
+ *	value - string value for the new property, must be UTF-8 and zero terminated
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if identifier is invalid, if name or value is NULL, or if proplist is NULL
+ *	MOSQ_ERR_NOMEM - on out of memory
+ *	MOSQ_ERR_MALFORMED_UTF8 - if name or value are not valid UTF-8.
+ *
+ * Example:
+ *	mosquitto_property *proplist = NULL;
+ *	mosquitto_property_add_string_pair(&proplist, MQTT_PROP_USER_PROPERTY, "client", "mosquitto_pub");
+ */
+libmosq_EXPORT int mosquitto_property_add_string_pair(mosquitto_property **proplist, int identifier, const char *name, const char *value);
+
+/*
+ * Function: mosquitto_property_read_byte
+ *
+ * Attempt to read a byte property matching an identifier, from a property list
+ * or single property. This function can search for multiple entries of the
+ * same identifier by using the returned value and skip_first. Note however
+ * that it is forbidden for most properties to be duplicated.
+ *
+ * If the property is not found, *value will not be modified, so it is safe to
+ * pass a variable with a default value to be potentially overwritten:
+ *
+ * uint16_t keepalive = 60; // default value
+ * // Get value from property list, or keep default if not found.
+ * mosquitto_property_read_int16(proplist, MQTT_PROP_SERVER_KEEP_ALIVE, &keepalive, false);
+ *
+ * Parameters:
+ *	proplist - mosquitto_property pointer, the list of properties or single property
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to store the value, or NULL if the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL.
+ *
+ * Example:
+ *	// proplist is obtained from a callback
+ *	mosquitto_property *prop;
+ *	prop = mosquitto_property_read_byte(proplist, identifier, &value, false);
+ *	while(prop){
+ *		printf("value: %s\n", value);
+ *		prop = mosquitto_property_read_byte(prop, identifier, &value);
+ *	}
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_byte(
+		const mosquitto_property *proplist,
+		int identifier,
+		uint8_t *value,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_read_int16
+ *
+ * Read an int16 property value from a property.
+ *
+ * Parameters:
+ *	property - property to read
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to store the value, or NULL if the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL.
+ *
+ * Example:
+ *	See <mosquitto_property_read_byte>
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_int16(
+		const mosquitto_property *proplist,
+		int identifier,
+		uint16_t *value,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_read_int32
+ *
+ * Read an int32 property value from a property.
+ *
+ * Parameters:
+ *	property - pointer to mosquitto_property pointer, the list of properties
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to store the value, or NULL if the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL.
+ *
+ * Example:
+ *	See <mosquitto_property_read_byte>
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_int32(
+		const mosquitto_property *proplist,
+		int identifier,
+		uint32_t *value,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_read_varint
+ *
+ * Read a varint property value from a property.
+ *
+ * Parameters:
+ *	property - property to read
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to store the value, or NULL if the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL.
+ *
+ * Example:
+ *	See <mosquitto_property_read_byte>
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_varint(
+		const mosquitto_property *proplist,
+		int identifier,
+		uint32_t *value,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_read_binary
+ *
+ * Read a binary property value from a property.
+ *
+ * On success, value must be free()'d by the application.
+ *
+ * Parameters:
+ *	property - property to read
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to store the value, or NULL if the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred.
+ *
+ * Example:
+ *	See <mosquitto_property_read_byte>
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_binary(
+		const mosquitto_property *proplist,
+		int identifier,
+		void **value,
+		uint16_t *len,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_read_string
+ *
+ * Read a string property value from a property.
+ *
+ * On success, value must be free()'d by the application.
+ *
+ * Parameters:
+ *	property - property to read
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	value - pointer to char*, for the property data to be stored in, or NULL if
+ *	        the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred.
+ *
+ * Example:
+ *	See <mosquitto_property_read_byte>
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_string(
+		const mosquitto_property *proplist,
+		int identifier,
+		char **value,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_read_string_pair
+ *
+ * Read a string pair property value pair from a property.
+ *
+ * On success, name and value must be free()'d by the application.
+ *
+ * Parameters:
+ *	property - property to read
+ *	identifier - property identifier (e.g. MQTT_PROP_PAYLOAD_FORMAT_INDICATOR)
+ *	name - pointer to char* for the name property data to be stored in, or NULL
+ *	       if the name is not required.
+ *	value - pointer to char*, for the property data to be stored in, or NULL if
+ *	        the value is not required.
+ *	skip_first - boolean that indicates whether the first item in the list
+ *	             should be ignored or not. Should usually be set to false.
+ *
+ * Returns:
+ *	A valid property pointer if the property is found
+ *	NULL, if the property is not found, or proplist is NULL, or if an out of memory condition occurred.
+ *
+ * Example:
+ *	See <mosquitto_property_read_byte>
+ */
+libmosq_EXPORT const mosquitto_property *mosquitto_property_read_string_pair(
+		const mosquitto_property *proplist,
+		int identifier,
+		char **name,
+		char **value,
+		bool skip_first);
+
+/*
+ * Function: mosquitto_property_free_all
+ *
+ * Free all properties from a list of properties. Frees the list and sets *properties to NULL.
+ *
+ * Parameters:
+ *   properties - list of properties to free
+ *
+ * Example:
+ *   mosquitto_properties *properties = NULL;
+ *   // Add properties
+ *   mosquitto_property_free_all(&properties);
+ */
+libmosq_EXPORT void mosquitto_property_free_all(mosquitto_property **properties);
+
+/*
+ * Function: mosquitto_property_copy_all
+ *
+ * Parameters:
+ *    dest : pointer for new property list
+ *    src : property list
+ *
+ * Returns:
+ *    MOSQ_ERR_SUCCESS - on successful copy
+ *    MOSQ_ERR_INVAL - if dest is NULL
+ *    MOSQ_ERR_NOMEM - on out of memory (dest will be set to NULL)
+ */
+libmosq_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const mosquitto_property *src);
+
+/*
+ * Function: mosquitto_property_check_command
+ *
+ * Check whether a property identifier is valid for the given command.
+ *
+ * Parameters:
+ *   command - MQTT command (e.g. CMD_CONNECT)
+ *   identifier - MQTT property (e.g. MQTT_PROP_USER_PROPERTY)
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS - if the identifier is valid for command
+ *   MOSQ_ERR_PROTOCOL - if the identifier is not valid for use with command.
+ */
+libmosq_EXPORT int mosquitto_property_check_command(int command, int identifier);
+
+
+/*
+ * Function: mosquitto_property_check_all
+ *
+ * Check whether a list of properties are valid for a particular command,
+ * whether there are duplicates, and whether the values are valid where
+ * possible.
+ *
+ * Note that this function is used internally in the library whenever
+ * properties are passed to it, so in basic use this is not needed, but should
+ * be helpful to check property lists *before* the point of using them.
+ *
+ * Parameters:
+ *	command - MQTT command (e.g. CMD_CONNECT)
+ *	properties - list of MQTT properties to check.
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - if all properties are valid
+ *	MOSQ_ERR_DUPLICATE_PROPERTY - if a property is duplicated where it is forbidden.
+ *	MOSQ_ERR_PROTOCOL - if any property is invalid
+ */
+libmosq_EXPORT int mosquitto_property_check_all(int command, const mosquitto_property *properties);
+
+/* Function: mosquitto_string_to_property_info
+ *
+ * Parse a property name string and convert to a property identifier and data type.
+ * The property name is as defined in the MQTT specification, with - as a
+ * separator, for example: payload-format-indicator.
+ *
+ * Parameters:
+ *	propname - the string to parse
+ *	identifier - pointer to an int to receive the property identifier
+ *	type - pointer to an int to receive the property type
+ *
+ * Returns:
+ *	MOSQ_ERR_SUCCESS - on success
+ *	MOSQ_ERR_INVAL - if the string does not match a property
+ *
+ * Example:
+ *	mosquitto_string_to_property_info("response-topic", &id, &type);
+ *	// id == MQTT_PROP_RESPONSE_TOPIC
+ *	// type == MQTT_PROP_TYPE_STRING
+ */
+libmosq_EXPORT int mosquitto_string_to_property_info(const char *propname, int *identifier, int *type);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mosquitto_broker.h b/mosquitto_broker.h
new file mode 100644
index 0000000..f6f2cc8
--- /dev/null
+++ b/mosquitto_broker.h
@@ -0,0 +1,172 @@
+/*
+Copyright (c) 2009-2019 Roger Light <roger@atchoo.org>
+
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+and Eclipse Distribution License v1.0 which accompany this distribution.
+ 
+The Eclipse Public License is available at
+   http://www.eclipse.org/legal/epl-v10.html
+and the Eclipse Distribution License is available at
+  http://www.eclipse.org/org/documents/edl-v10.php.
+ 
+Contributors:
+   Roger Light - initial implementation and documentation.
+*/
+
+#ifndef MOSQUITTO_BROKER_H
+#define MOSQUITTO_BROKER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+struct mosquitto;
+
+enum mosquitto_protocol {
+	mp_mqtt,
+	mp_mqttsn,
+	mp_websockets
+};
+
+/* =========================================================================
+ *
+ * Utility Functions
+ *
+ * Use these functions from within your plugin.
+ *
+ * There are also very useful functions in libmosquitto.
+ *
+ * ========================================================================= */
+
+
+/*
+ * Function: mosquitto_log_printf
+ *
+ * Write a log message using the broker configured logging.
+ *
+ * Parameters:
+ * 	level -    Log message priority. Can currently be one of:
+ *
+ *             MOSQ_LOG_INFO
+ *             MOSQ_LOG_NOTICE
+ *             MOSQ_LOG_WARNING
+ *             MOSQ_LOG_ERR
+ *             MOSQ_LOG_DEBUG
+ *             MOSQ_LOG_SUBSCRIBE (not recommended for use by plugins)
+ *             MOSQ_LOG_UNSUBSCRIBE (not recommended for use by plugins)
+ *
+ *             These values are defined in mosquitto.h.
+ *
+ *	fmt, ... - printf style format and arguments.
+ */
+void mosquitto_log_printf(int level, const char *fmt, ...);
+
+
+/* =========================================================================
+ *
+ * Client Functions
+ *
+ * Use these functions to access client information.
+ *
+ * ========================================================================= */
+
+/*
+ * Function: mosquitto_client_address
+ *
+ * Retrieve the IP address of the client as a string.
+ */
+const char *mosquitto_client_address(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_clean_session
+ *
+ * Retrieve the clean session flag value for a client.
+ */
+bool mosquitto_client_clean_session(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_id
+ *
+ * Retrieve the client id associated with a client.
+ */
+const char *mosquitto_client_id(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_keepalive
+ *
+ * Retrieve the keepalive value for a client.
+ */
+int mosquitto_client_keepalive(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_certificate
+ *
+ * If TLS support is enabled, return the certificate provided by a client as an
+ * X509 pointer from openssl. If the client did not provide a certificate, then
+ * NULL will be returned. This function will only ever return a non-NULL value
+ * if the `require_certificate` option is set to true.
+ *
+ * If TLS is not supported, this function will always return NULL.
+ */
+void *mosquitto_client_certificate(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_protocol
+ *
+ * Retrieve the protocol with which the client has connected. Can be one of:
+ *
+ * mp_mqtt (MQTT over TCP)
+ * mp_mqttsn (MQTT-SN)
+ * mp_websockets (MQTT over Websockets)
+ */
+int mosquitto_client_protocol(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_sub_count
+ *
+ * Retrieve the number of subscriptions that have been made by a client.
+ */
+int mosquitto_client_sub_count(const struct mosquitto *client);
+
+
+/*
+ * Function: mosquitto_client_username
+ *
+ * Retrieve the username associated with a client.
+ */
+const char *mosquitto_client_username(const struct mosquitto *client);
+
+
+/* Function: mosquitto_set_username
+ *
+ * Set the username for a client.
+ *
+ * This removes and replaces the current username for a client and hence
+ * updates its access.
+ *
+ * username can be NULL, in which case the client will become anonymous, but
+ * must not be zero length.
+ *
+ * In the case of error, the client will be left with its original username.
+ *
+ * Returns:
+ *   MOSQ_ERR_SUCCESS - on success
+ *   MOSQ_ERR_INVAL - if client is NULL, or if username is zero length
+ *   MOSQ_ERR_NOMEM - on out of memory
+ */
+int mosquitto_set_username(struct mosquitto *client, const char *username);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mosquitto_plugin.h b/mosquitto_plugin.h
new file mode 100644
index 0000000..83e55eb
--- /dev/null
+++ b/mosquitto_plugin.h
@@ -0,0 +1,318 @@
+/*
+Copyright (c) 2012-2019 Roger Light <roger@atchoo.org>
+
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+and Eclipse Distribution License v1.0 which accompany this distribution.
+ 
+The Eclipse Public License is available at
+   http://www.eclipse.org/legal/epl-v10.html
+and the Eclipse Distribution License is available at
+  http://www.eclipse.org/org/documents/edl-v10.php.
+ 
+Contributors:
+   Roger Light - initial implementation and documentation.
+*/
+
+#ifndef MOSQUITTO_PLUGIN_H
+#define MOSQUITTO_PLUGIN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MOSQ_AUTH_PLUGIN_VERSION 4
+
+#define MOSQ_ACL_NONE 0x00
+#define MOSQ_ACL_READ 0x01
+#define MOSQ_ACL_WRITE 0x02
+#define MOSQ_ACL_SUBSCRIBE 0x04
+
+#include <stdbool.h>
+
+struct mosquitto;
+
+struct mosquitto_opt {
+	char *key;
+	char *value;
+};
+
+struct mosquitto_auth_opt {
+	char *key;
+	char *value;
+};
+
+struct mosquitto_acl_msg {
+	const char *topic;
+	const void *payload;
+	long payloadlen;
+	int qos;
+	bool retain;
+};
+
+/*
+ * To create an authentication plugin you must include this file then implement
+ * the functions listed in the "Plugin Functions" section below. The resulting
+ * code should then be compiled as a shared library. Using gcc this can be
+ * achieved as follows:
+ *
+ * gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -o plugin.so
+ *
+ * On Mac OS X:
+ *
+ * gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -undefined dynamic_lookup -o plugin.so
+ *
+ * Authentication plugins can implement one or both of authentication and
+ * access control. If your plugin does not wish to handle either of
+ * authentication or access control it should return MOSQ_ERR_PLUGIN_DEFER. In
+ * this case, the next plugin will handle it. If all plugins return
+ * MOSQ_ERR_PLUGIN_DEFER, the request will be denied.
+ *
+ * For each check, the following flow happens:
+ *
+ * * The default password file and/or acl file checks are made. If either one
+ *   of these is not defined, then they are considered to be deferred. If either
+ *   one accepts the check, no further checks are made. If an error occurs, the
+ *   check is denied
+ * * The first plugin does the check, if it returns anything other than
+ *   MOSQ_ERR_PLUGIN_DEFER, then the check returns immediately. If the plugin
+ *   returns MOSQ_ERR_PLUGIN_DEFER then the next plugin runs its check.
+ * * If the final plugin returns MOSQ_ERR_PLUGIN_DEFER, then access will be
+ *   denied.
+ */
+
+/* =========================================================================
+ *
+ * Helper Functions
+ *
+ * ========================================================================= */
+
+/* There are functions that are available for plugin developers to use in
+ * mosquitto_broker.h, including logging and accessor functions.
+ */
+
+
+/* =========================================================================
+ *
+ * Plugin Functions
+ *
+ * You must implement these functions in your plugin.
+ *
+ * ========================================================================= */
+
+/*
+ * Function: mosquitto_auth_plugin_version
+ *
+ * The broker will call this function immediately after loading the plugin to
+ * check it is a supported plugin version. Your code must simply return
+ * MOSQ_AUTH_PLUGIN_VERSION.
+ */
+int mosquitto_auth_plugin_version(void);
+
+
+/*
+ * Function: mosquitto_auth_plugin_init
+ *
+ * Called after the plugin has been loaded and <mosquitto_auth_plugin_version>
+ * has been called. This will only ever be called once and can be used to
+ * initialise the plugin.
+ *
+ * Parameters:
+ *
+ *	user_data :      The pointer set here will be passed to the other plugin
+ *	                 functions. Use to hold connection information for example.
+ *	opts :           Pointer to an array of struct mosquitto_opt, which
+ *	                 provides the plugin options defined in the configuration file.
+ *	opt_count :      The number of elements in the opts array.
+ *
+ * Return value:
+ *	Return 0 on success
+ *	Return >0 on failure.
+ */
+int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_opt *opts, int opt_count);
+
+
+/*
+ * Function: mosquitto_auth_plugin_cleanup
+ *
+ * Called when the broker is shutting down. This will only ever be called once
+ * per plugin.
+ * Note that <mosquitto_auth_security_cleanup> will be called directly before
+ * this function.
+ *
+ * Parameters:
+ *
+ *	user_data :      The pointer provided in <mosquitto_auth_plugin_init>.
+ *	opts :           Pointer to an array of struct mosquitto_opt, which
+ *	                 provides the plugin options defined in the configuration file.
+ *	opt_count :      The number of elements in the opts array.
+ *
+ * Return value:
+ *	Return 0 on success
+ *	Return >0 on failure.
+ */
+int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count);
+
+
+/*
+ * Function: mosquitto_auth_security_init
+ *
+ * This function is called in two scenarios:
+ *
+ * 1. When the broker starts up.
+ * 2. If the broker is requested to reload its configuration whilst running. In
+ *    this case, <mosquitto_auth_security_cleanup> will be called first, then
+ *    this function will be called.  In this situation, the reload parameter
+ *    will be true.
+ *
+ * Parameters:
+ *
+ *	user_data :      The pointer provided in <mosquitto_auth_plugin_init>.
+ *	opts :           Pointer to an array of struct mosquitto_opt, which
+ *	                 provides the plugin options defined in the configuration file.
+ *	opt_count :      The number of elements in the opts array.
+ *	reload :         If set to false, this is the first time the function has
+ *	                 been called. If true, the broker has received a signal
+ *	                 asking to reload its configuration.
+ *
+ * Return value:
+ *	Return 0 on success
+ *	Return >0 on failure.
+ */
+int mosquitto_auth_security_init(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload);
+
+
+/* 
+ * Function: mosquitto_auth_security_cleanup
+ *
+ * This function is called in two scenarios:
+ *
+ * 1. When the broker is shutting down.
+ * 2. If the broker is requested to reload its configuration whilst running. In
+ *    this case, this function will be called, followed by
+ *    <mosquitto_auth_security_init>. In this situation, the reload parameter
+ *    will be true.
+ *
+ * Parameters:
+ *
+ *	user_data :      The pointer provided in <mosquitto_auth_plugin_init>.
+ *	opts :           Pointer to an array of struct mosquitto_opt, which
+ *	                 provides the plugin options defined in the configuration file.
+ *	opt_count :      The number of elements in the opts array.
+ *	reload :         If set to false, this is the first time the function has
+ *	                 been called. If true, the broker has received a signal
+ *	                 asking to reload its configuration.
+ *
+ * Return value:
+ *	Return 0 on success
+ *	Return >0 on failure.
+ */
+int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload);
+
+
+/*
+ * Function: mosquitto_auth_acl_check
+ *
+ * Called by the broker when topic access must be checked. access will be one
+ * of:
+ *  MOSQ_ACL_SUBSCRIBE when a client is asking to subscribe to a topic string.
+ *                     This differs from MOSQ_ACL_READ in that it allows you to
+ *                     deny access to topic strings rather than by pattern. For
+ *                     example, you may use MOSQ_ACL_SUBSCRIBE to deny
+ *                     subscriptions to '#', but allow all topics in
+ *                     MOSQ_ACL_READ. This allows clients to subscribe to any
+ *                     topic they want, but not discover what topics are in use
+ *                     on the server.
+ *  MOSQ_ACL_READ      when a message is about to be sent to a client (i.e. whether
+ *                     it can read that topic or not).
+ *  MOSQ_ACL_WRITE     when a message has been received from a client (i.e. whether
+ *                     it can write to that topic or not).
+ *
+ * Return:
+ *	MOSQ_ERR_SUCCESS if access was granted.
+ *	MOSQ_ERR_ACL_DENIED if access was not granted.
+ *	MOSQ_ERR_UNKNOWN for an application specific error.
+ *	MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
+ */
+int mosquitto_auth_acl_check(void *user_data, int access, struct mosquitto *client, const struct mosquitto_acl_msg *msg);
+
+
+/*
+ * Function: mosquitto_auth_unpwd_check
+ *
+ * This function is OPTIONAL. Only include this function in your plugin if you
+ * are making basic username/password checks.
+ *
+ * Called by the broker when a username/password must be checked.
+ *
+ * Return:
+ *	MOSQ_ERR_SUCCESS if the user is authenticated.
+ *	MOSQ_ERR_AUTH if authentication failed.
+ *	MOSQ_ERR_UNKNOWN for an application specific error.
+ *	MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
+ */
+int mosquitto_auth_unpwd_check(void *user_data, struct mosquitto *client, const char *username, const char *password);
+
+
+/*
+ * Function: mosquitto_psk_key_get
+ *
+ * This function is OPTIONAL. Only include this function in your plugin if you
+ * are making TLS-PSK checks.
+ *
+ * Called by the broker when a client connects to a listener using TLS/PSK.
+ * This is used to retrieve the pre-shared-key associated with a client
+ * identity.
+ *
+ * Examine hint and identity to determine the required PSK (which must be a
+ * hexadecimal string with no leading "0x") and copy this string into key.
+ *
+ * Parameters:
+ *	user_data :   the pointer provided in <mosquitto_auth_plugin_init>.
+ *	hint :        the psk_hint for the listener the client is connecting to.
+ *	identity :    the identity string provided by the client
+ *	key :         a string where the hex PSK should be copied
+ *	max_key_len : the size of key
+ *
+ * Return value:
+ *	Return 0 on success.
+ *	Return >0 on failure.
+ *	Return MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
+ */
+int mosquitto_auth_psk_key_get(void *user_data, struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len);
+
+/*
+ * Function: mosquitto_auth_start
+ *
+ * This function is OPTIONAL. Only include this function in your plugin if you
+ * are making extended authentication checks.
+ *
+ * Parameters:
+ *	user_data :   the pointer provided in <mosquitto_auth_plugin_init>.
+ *	method : the authentication method
+ *	reauth : this is set to false if this is the first authentication attempt
+ *	         on a connection, set to true if the client is attempting to
+ *	         reauthenticate.
+ *	data_in : pointer to authentication data, or NULL
+ *	data_in_len : length of data_in, in bytes
+ *	data_out : if your plugin wishes to send authentication data back to the
+ *	           client, allocate some memory using malloc or friends and set
+ *	           data_out. The broker will free the memory after use.
+ *	data_out_len : Set the length of data_out in bytes.
+ *
+ * Return value:
+ *	Return MOSQ_ERR_SUCCESS if authentication was successful.
+ *	Return MOSQ_ERR_AUTH_CONTINUE if the authentication is a multi step process and can continue.
+ *	Return MOSQ_ERR_AUTH if authentication was valid but did not succeed.
+ *	Return any other relevant positive integer MOSQ_ERR_* to produce an error.
+ */
+int mosquitto_auth_start(void *user_data, struct mosquitto *client, const char *method, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
+
+int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/mosquittopp.h b/mosquittopp.h
new file mode 100644
index 0000000..d3f388c
--- /dev/null
+++ b/mosquittopp.h
@@ -0,0 +1,146 @@
+/*
+Copyright (c) 2010-2019 Roger Light <roger@atchoo.org>
+
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+and Eclipse Distribution License v1.0 which accompany this distribution.
+
+The Eclipse Public License is available at
+   http://www.eclipse.org/legal/epl-v10.html
+and the Eclipse Distribution License is available at
+  http://www.eclipse.org/org/documents/edl-v10.php.
+
+Contributors:
+   Roger Light - initial implementation and documentation.
+*/
+
+#ifndef MOSQUITTOPP_H
+#define MOSQUITTOPP_H
+
+#if defined(_WIN32) && !defined(LIBMOSQUITTO_STATIC)
+#	ifdef mosquittopp_EXPORTS
+#		define mosqpp_EXPORT  __declspec(dllexport)
+#	else
+#		define mosqpp_EXPORT  __declspec(dllimport)
+#	endif
+#else
+#	define mosqpp_EXPORT
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#  define DEPRECATED __attribute__ ((deprecated))
+#else
+#  define DEPRECATED
+#endif
+
+#include <cstdlib>
+#include <mosquitto.h>
+#include <time.h>
+
+namespace mosqpp {
+
+
+mosqpp_EXPORT const char * DEPRECATED strerror(int mosq_errno);
+mosqpp_EXPORT const char * DEPRECATED connack_string(int connack_code);
+mosqpp_EXPORT int DEPRECATED sub_topic_tokenise(const char *subtopic, char ***topics, int *count);
+mosqpp_EXPORT int DEPRECATED sub_topic_tokens_free(char ***topics, int count);
+mosqpp_EXPORT int DEPRECATED lib_version(int *major, int *minor, int *revision);
+mosqpp_EXPORT int DEPRECATED lib_init();
+mosqpp_EXPORT int DEPRECATED lib_cleanup();
+mosqpp_EXPORT int DEPRECATED topic_matches_sub(const char *sub, const char *topic, bool *result);
+mosqpp_EXPORT int DEPRECATED validate_utf8(const char *str, int len);
+mosqpp_EXPORT int DEPRECATED subscribe_simple(
+		struct mosquitto_message **messages,
+		int msg_count,
+		bool retained,
+		const char *topic,
+		int qos=0,
+		const char *host="localhost",
+		int port=1883,
+		const char *client_id=NULL,
+		int keepalive=60,
+		bool clean_session=true,
+		const char *username=NULL,
+		const char *password=NULL,
+		const struct libmosquitto_will *will=NULL,
+		const struct libmosquitto_tls *tls=NULL);
+
+mosqpp_EXPORT int DEPRECATED subscribe_callback(
+		int (*callback)(struct mosquitto *, void *, const struct mosquitto_message *),
+		void *userdata,
+		const char *topic,
+		int qos=0,
+		bool retained=true,
+		const char *host="localhost",
+		int port=1883,
+		const char *client_id=NULL,
+		int keepalive=60,
+		bool clean_session=true,
+		const char *username=NULL,
+		const char *password=NULL,
+		const struct libmosquitto_will *will=NULL,
+		const struct libmosquitto_tls *tls=NULL);
+
+/*
+ * Class: mosquittopp
+ *
+ * A mosquitto client class. This is a C++ wrapper class for the mosquitto C
+ * library. Please see mosquitto.h for details of the functions.
+ */
+class mosqpp_EXPORT DEPRECATED mosquittopp {
+	private:
+		struct mosquitto *m_mosq;
+	public:
+		DEPRECATED mosquittopp(const char *id=NULL, bool clean_session=true);
+		virtual ~mosquittopp();
+
+		int DEPRECATED reinitialise(const char *id, bool clean_session);
+		int DEPRECATED socket();
+		int DEPRECATED will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
+		int DEPRECATED will_clear();
+		int DEPRECATED username_pw_set(const char *username, const char *password=NULL);
+		int DEPRECATED connect(const char *host, int port=1883, int keepalive=60);
+		int DEPRECATED connect_async(const char *host, int port=1883, int keepalive=60);
+		int DEPRECATED connect(const char *host, int port, int keepalive, const char *bind_address);
+		int DEPRECATED connect_async(const char *host, int port, int keepalive, const char *bind_address);
+		int DEPRECATED reconnect();
+		int DEPRECATED reconnect_async();
+		int DEPRECATED disconnect();
+		int DEPRECATED publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
+		int DEPRECATED subscribe(int *mid, const char *sub, int qos=0);
+		int DEPRECATED unsubscribe(int *mid, const char *sub);
+		void DEPRECATED reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
+		int DEPRECATED max_inflight_messages_set(unsigned int max_inflight_messages);
+		void DEPRECATED message_retry_set(unsigned int message_retry);
+		void DEPRECATED user_data_set(void *userdata);
+		int DEPRECATED tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL);
+		int DEPRECATED tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
+		int DEPRECATED tls_insecure_set(bool value);
+		int DEPRECATED tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
+		int DEPRECATED opts_set(enum mosq_opt_t option, void *value);
+
+		int DEPRECATED loop(int timeout=-1, int max_packets=1);
+		int DEPRECATED loop_misc();
+		int DEPRECATED loop_read(int max_packets=1);
+		int DEPRECATED loop_write(int max_packets=1);
+		int DEPRECATED loop_forever(int timeout=-1, int max_packets=1);
+		int DEPRECATED loop_start();
+		int DEPRECATED loop_stop(bool force=false);
+		bool DEPRECATED want_write();
+		int DEPRECATED threaded_set(bool threaded=true);
+		int DEPRECATED socks5_set(const char *host, int port=1080, const char *username=NULL, const char *password=NULL);
+
+		// names in the functions commented to prevent unused parameter warning
+		virtual void on_connect(int /*rc*/) {return;}
+		virtual void on_connect_with_flags(int /*rc*/, int /*flags*/) {return;}
+		virtual void on_disconnect(int /*rc*/) {return;}
+		virtual void on_publish(int /*mid*/) {return;}
+		virtual void on_message(const struct mosquitto_message * /*message*/) {return;}
+		virtual void on_subscribe(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/) {return;}
+		virtual void on_unsubscribe(int /*mid*/) {return;}
+		virtual void on_log(int /*level*/, const char * /*str*/) {return;}
+		virtual void on_error() {return;}
+};
+
+}
+#endif
diff --git a/nlohmann/json.hpp b/nlohmann/json.hpp
new file mode 100644
index 0000000..06da815
--- /dev/null
+++ b/nlohmann/json.hpp
@@ -0,0 +1,22875 @@
+/*
+    __ _____ _____ _____
+ __|  |   __|     |   | |  JSON for Modern C++
+|  |  |__   |  |  | | | |  version 3.7.3
+|_____|_____|_____|_|___|  https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
+Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
+
+Permission is hereby  granted, free of charge, to any  person obtaining a copy
+of this software and associated  documentation files (the "Software"), to deal
+in the Software  without restriction, including without  limitation the rights
+to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
+copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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 AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
+AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
+LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef INCLUDE_NLOHMANN_JSON_HPP_
+#define INCLUDE_NLOHMANN_JSON_HPP_
+
+#define NLOHMANN_JSON_VERSION_MAJOR 3
+#define NLOHMANN_JSON_VERSION_MINOR 7
+#define NLOHMANN_JSON_VERSION_PATCH 3
+
+#include <algorithm> // all_of, find, for_each
+#include <cassert> // assert
+#include <ciso646> // and, not, or
+#include <cstddef> // nullptr_t, ptrdiff_t, size_t
+#include <functional> // hash, less
+#include <initializer_list> // initializer_list
+#include <iosfwd> // istream, ostream
+#include <iterator> // random_access_iterator_tag
+#include <memory> // unique_ptr
+#include <numeric> // accumulate
+#include <string> // string, stoi, to_string
+#include <utility> // declval, forward, move, pair, swap
+#include <vector> // vector
+
+// #include <nlohmann/adl_serializer.hpp>
+
+
+#include <utility>
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+
+#include <algorithm> // transform
+#include <array> // array
+#include <ciso646> // and, not
+#include <forward_list> // forward_list
+#include <iterator> // inserter, front_inserter, end
+#include <map> // map
+#include <string> // string
+#include <tuple> // tuple, make_tuple
+#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
+#include <unordered_map> // unordered_map
+#include <utility> // pair, declval
+#include <valarray> // valarray
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+
+#include <exception> // exception
+#include <stdexcept> // runtime_error
+#include <string> // to_string
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+
+#include <cstddef> // size_t
+
+namespace nlohmann
+{
+namespace detail
+{
+/// struct to capture the start position of the current token
+struct position_t
+{
+    /// the total number of characters read
+    std::size_t chars_read_total = 0;
+    /// the number of characters read in the current line
+    std::size_t chars_read_current_line = 0;
+    /// the number of lines read
+    std::size_t lines_read = 0;
+
+    /// conversion to size_t to preserve SAX interface
+    constexpr operator size_t() const
+    {
+        return chars_read_total;
+    }
+};
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+#include <utility> // pair
+// #include <nlohmann/thirdparty/hedley/hedley.hpp>
+/* Hedley - https://nemequ.github.io/hedley
+ * Created by Evan Nemerson <evan@nemerson.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to
+ * the public domain worldwide. This software is distributed without
+ * any warranty.
+ *
+ * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11)
+#if defined(JSON_HEDLEY_VERSION)
+    #undef JSON_HEDLEY_VERSION
+#endif
+#define JSON_HEDLEY_VERSION 11
+
+#if defined(JSON_HEDLEY_STRINGIFY_EX)
+    #undef JSON_HEDLEY_STRINGIFY_EX
+#endif
+#define JSON_HEDLEY_STRINGIFY_EX(x) #x
+
+#if defined(JSON_HEDLEY_STRINGIFY)
+    #undef JSON_HEDLEY_STRINGIFY
+#endif
+#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
+
+#if defined(JSON_HEDLEY_CONCAT_EX)
+    #undef JSON_HEDLEY_CONCAT_EX
+#endif
+#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
+
+#if defined(JSON_HEDLEY_CONCAT)
+    #undef JSON_HEDLEY_CONCAT
+#endif
+#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
+
+#if defined(JSON_HEDLEY_VERSION_ENCODE)
+    #undef JSON_HEDLEY_VERSION_ENCODE
+#endif
+#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
+    #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
+    #undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
+    #undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
+
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+    #undef JSON_HEDLEY_GNUC_VERSION
+#endif
+#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
+    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#elif defined(__GNUC__)
+    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
+    #undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION)
+    #undef JSON_HEDLEY_MSVC_VERSION
+#endif
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
+#elif defined(_MSC_FULL_VER)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
+#elif defined(_MSC_VER)
+    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
+    #undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#endif
+#if !defined(_MSC_VER)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
+#else
+    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+    #undef JSON_HEDLEY_INTEL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
+    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
+#elif defined(__INTEL_COMPILER)
+    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
+    #undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION)
+    #undef JSON_HEDLEY_PGI_VERSION
+#endif
+#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
+    #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
+    #undef JSON_HEDLEY_PGI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PGI_VERSION)
+    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+    #undef JSON_HEDLEY_SUNPRO_VERSION
+#endif
+#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
+#elif defined(__SUNPRO_C)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
+#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
+#elif defined(__SUNPRO_CC)
+    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
+    #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#endif
+#if defined(__EMSCRIPTEN__)
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
+    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION)
+    #undef JSON_HEDLEY_ARM_VERSION
+#endif
+#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
+#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
+    #undef JSON_HEDLEY_ARM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_ARM_VERSION)
+    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION)
+    #undef JSON_HEDLEY_IBM_VERSION
+#endif
+#if defined(__ibmxl__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
+#elif defined(__xlC__) && defined(__xlC_ver__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
+#elif defined(__xlC__)
+    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
+    #undef JSON_HEDLEY_IBM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IBM_VERSION)
+    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION)
+    #undef JSON_HEDLEY_TI_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__)
+    #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
+    #undef JSON_HEDLEY_TI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_VERSION)
+    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+    #undef JSON_HEDLEY_CRAY_VERSION
+#endif
+#if defined(_CRAYC)
+    #if defined(_RELEASE_PATCHLEVEL)
+        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
+    #else
+        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
+    #endif
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
+    #undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION)
+    #undef JSON_HEDLEY_IAR_VERSION
+#endif
+#if defined(__IAR_SYSTEMS_ICC__)
+    #if __VER__ > 1000
+        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
+    #else
+        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0)
+    #endif
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
+    #undef JSON_HEDLEY_IAR_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IAR_VERSION)
+    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+    #undef JSON_HEDLEY_TINYC_VERSION
+#endif
+#if defined(__TINYC__)
+    #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
+    #undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION)
+    #undef JSON_HEDLEY_DMC_VERSION
+#endif
+#if defined(__DMC__)
+    #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
+    #undef JSON_HEDLEY_DMC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_DMC_VERSION)
+    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+    #undef JSON_HEDLEY_COMPCERT_VERSION
+#endif
+#if defined(__COMPCERT_VERSION__)
+    #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
+    #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+    #undef JSON_HEDLEY_PELLES_VERSION
+#endif
+#if defined(__POCC__)
+    #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
+    #undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION)
+    #undef JSON_HEDLEY_GCC_VERSION
+#endif
+#if \
+    defined(JSON_HEDLEY_GNUC_VERSION) && \
+    !defined(__clang__) && \
+    !defined(JSON_HEDLEY_INTEL_VERSION) && \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_ARM_VERSION) && \
+    !defined(JSON_HEDLEY_TI_VERSION) && \
+    !defined(__COMPCERT__)
+    #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
+    #undef JSON_HEDLEY_GCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GCC_VERSION)
+    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#endif
+#if \
+    defined(__has_cpp_attribute) && \
+    defined(__cplusplus) && \
+    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
+    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#endif
+#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#elif \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
+    (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
+#else
+    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_BUILTIN)
+    #undef JSON_HEDLEY_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
+    #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
+    #undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_FEATURE)
+    #undef JSON_HEDLEY_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
+    #undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
+    #undef JSON_HEDLEY_GCC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_EXTENSION)
+    #undef JSON_HEDLEY_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
+    #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
+    #undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_WARNING)
+    #undef JSON_HEDLEY_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_HAS_WARNING(warning) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
+    #undef JSON_HEDLEY_GNUC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
+    #undef JSON_HEDLEY_GCC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
+   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#endif
+#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
+#  define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+    xpr \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#else
+#  define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
+#endif
+
+#if \
+    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+    defined(__clang__) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
+    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
+    #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
+#else
+    #define JSON_HEDLEY_PRAGMA(value)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
+    #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#endif
+#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
+    #undef JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+#if defined(__clang__)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
+    #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
+#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
+#elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_PUSH
+    #define JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
+#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
+#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
+#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
+    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#else
+    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+
+#if defined(JSON_HEDLEY_DEPRECATED)
+    #undef JSON_HEDLEY_DEPRECATED
+#endif
+#if defined(JSON_HEDLEY_DEPRECATED_FOR)
+    #undef JSON_HEDLEY_DEPRECATED_FOR
+#endif
+#if defined(__cplusplus) && (__cplusplus >= 201402L)
+    #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
+#elif \
+    JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0)
+    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
+#else
+    #define JSON_HEDLEY_DEPRECATED(since)
+    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
+#endif
+
+#if defined(JSON_HEDLEY_UNAVAILABLE)
+    #undef JSON_HEDLEY_UNAVAILABLE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
+#else
+    #define JSON_HEDLEY_UNAVAILABLE(available_since)
+#endif
+
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
+    #undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#endif
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+#elif defined(_Check_return_) /* SAL */
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
+#else
+    #define JSON_HEDLEY_WARN_UNUSED_RESULT
+#endif
+
+#if defined(JSON_HEDLEY_SENTINEL)
+    #undef JSON_HEDLEY_SENTINEL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0)
+    #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
+#else
+    #define JSON_HEDLEY_SENTINEL(position)
+#endif
+
+#if defined(JSON_HEDLEY_NO_RETURN)
+    #undef JSON_HEDLEY_NO_RETURN
+#endif
+#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_NO_RETURN __noreturn
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+    #define JSON_HEDLEY_NO_RETURN _Noreturn
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+    #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
+    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+    #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#else
+    #define JSON_HEDLEY_NO_RETURN
+#endif
+
+#if defined(JSON_HEDLEY_NO_ESCAPE)
+    #undef JSON_HEDLEY_NO_ESCAPE
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
+    #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
+#else
+    #define JSON_HEDLEY_NO_ESCAPE
+#endif
+
+#if defined(JSON_HEDLEY_UNREACHABLE)
+    #undef JSON_HEDLEY_UNREACHABLE
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
+    #undef JSON_HEDLEY_UNREACHABLE_RETURN
+#endif
+#if \
+    (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
+    #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
+    #define JSON_HEDLEY_UNREACHABLE() __assume(0)
+#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0)
+    #if defined(__cplusplus)
+        #define JSON_HEDLEY_UNREACHABLE() std::_nassert(0)
+    #else
+        #define JSON_HEDLEY_UNREACHABLE() _nassert(0)
+    #endif
+    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value
+#elif defined(EXIT_FAILURE)
+    #define JSON_HEDLEY_UNREACHABLE() abort()
+#else
+    #define JSON_HEDLEY_UNREACHABLE()
+    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value
+#endif
+#if !defined(JSON_HEDLEY_UNREACHABLE_RETURN)
+    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
+#endif
+
+#if defined(JSON_HEDLEY_ASSUME)
+    #undef JSON_HEDLEY_ASSUME
+#endif
+#if \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
+#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
+    #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
+#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0)
+    #if defined(__cplusplus)
+        #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
+    #else
+        #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
+    #endif
+#elif \
+    (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5)
+    #define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1)))
+#else
+    #define JSON_HEDLEY_ASSUME(expr) ((void) (expr))
+#endif
+
+JSON_HEDLEY_DIAGNOSTIC_PUSH
+#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
+    #pragma clang diagnostic ignored "-Wpedantic"
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
+    #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif
+#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
+    #if defined(__clang__)
+        #pragma clang diagnostic ignored "-Wvariadic-macros"
+    #elif defined(JSON_HEDLEY_GCC_VERSION)
+        #pragma GCC diagnostic ignored "-Wvariadic-macros"
+    #endif
+#endif
+#if defined(JSON_HEDLEY_NON_NULL)
+    #undef JSON_HEDLEY_NON_NULL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+    #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
+#else
+    #define JSON_HEDLEY_NON_NULL(...)
+#endif
+JSON_HEDLEY_DIAGNOSTIC_POP
+
+#if defined(JSON_HEDLEY_PRINTF_FORMAT)
+    #undef JSON_HEDLEY_PRINTF_FORMAT
+#endif
+#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
+#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
+#elif \
+    JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
+#else
+    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
+#endif
+
+#if defined(JSON_HEDLEY_CONSTEXPR)
+    #undef JSON_HEDLEY_CONSTEXPR
+#endif
+#if defined(__cplusplus)
+    #if __cplusplus >= 201103L
+        #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
+    #endif
+#endif
+#if !defined(JSON_HEDLEY_CONSTEXPR)
+    #define JSON_HEDLEY_CONSTEXPR
+#endif
+
+#if defined(JSON_HEDLEY_PREDICT)
+    #undef JSON_HEDLEY_PREDICT
+#endif
+#if defined(JSON_HEDLEY_LIKELY)
+    #undef JSON_HEDLEY_LIKELY
+#endif
+#if defined(JSON_HEDLEY_UNLIKELY)
+    #undef JSON_HEDLEY_UNLIKELY
+#endif
+#if defined(JSON_HEDLEY_UNPREDICTABLE)
+    #undef JSON_HEDLEY_UNPREDICTABLE
+#endif
+#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
+    #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr))
+#endif
+#if \
+  JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0)
+#  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability)
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability)
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability)
+#  define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
+#  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
+#if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE)
+    #define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5)
+#endif
+#elif \
+  JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+  (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+  JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \
+  JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27)
+#  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
+    (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr)))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
+    (__extension__ ({ \
+        JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \
+        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
+    }))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
+    (__extension__ ({ \
+        JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \
+        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
+    }))
+#  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
+#  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
+#else
+#  define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr))
+#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
+#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
+#  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
+#  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
+#endif
+#if !defined(JSON_HEDLEY_UNPREDICTABLE)
+    #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
+#endif
+
+#if defined(JSON_HEDLEY_MALLOC)
+    #undef JSON_HEDLEY_MALLOC
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+    #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0)
+    #define JSON_HEDLEY_MALLOC __declspec(restrict)
+#else
+    #define JSON_HEDLEY_MALLOC
+#endif
+
+#if defined(JSON_HEDLEY_PURE)
+    #undef JSON_HEDLEY_PURE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_PURE __attribute__((__pure__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
+#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
+#else
+    #define JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_CONST)
+    #undef JSON_HEDLEY_CONST
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+    #define JSON_HEDLEY_CONST __attribute__((__const__))
+#elif \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+    #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
+#else
+    #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_RESTRICT)
+    #undef JSON_HEDLEY_RESTRICT
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
+    #define JSON_HEDLEY_RESTRICT restrict
+#elif \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
+    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+    defined(__clang__)
+    #define JSON_HEDLEY_RESTRICT __restrict
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
+    #define JSON_HEDLEY_RESTRICT _Restrict
+#else
+    #define JSON_HEDLEY_RESTRICT
+#endif
+
+#if defined(JSON_HEDLEY_INLINE)
+    #undef JSON_HEDLEY_INLINE
+#endif
+#if \
+    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+    (defined(__cplusplus) && (__cplusplus >= 199711L))
+    #define JSON_HEDLEY_INLINE inline
+#elif \
+    defined(JSON_HEDLEY_GCC_VERSION) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
+    #define JSON_HEDLEY_INLINE __inline__
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_INLINE __inline
+#else
+    #define JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_ALWAYS_INLINE)
+    #undef JSON_HEDLEY_ALWAYS_INLINE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+    #define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0)
+    #define JSON_HEDLEY_ALWAYS_INLINE __forceinline
+#elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
+#else
+    #define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_NEVER_INLINE)
+    #undef JSON_HEDLEY_NEVER_INLINE
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+    (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+    #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0)
+    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
+#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+    #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+    #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#else
+    #define JSON_HEDLEY_NEVER_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_PRIVATE)
+    #undef JSON_HEDLEY_PRIVATE
+#endif
+#if defined(JSON_HEDLEY_PUBLIC)
+    #undef JSON_HEDLEY_PUBLIC
+#endif
+#if defined(JSON_HEDLEY_IMPORT)
+    #undef JSON_HEDLEY_IMPORT
+#endif
+#if defined(_WIN32) || defined(__CYGWIN__)
+    #define JSON_HEDLEY_PRIVATE
+    #define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
+    #define JSON_HEDLEY_IMPORT   __declspec(dllimport)
+#else
+    #if \
+        JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
+        JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+        JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+        JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+        JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+        JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+        JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \
+        (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+        #define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
+        #define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
+    #else
+        #define JSON_HEDLEY_PRIVATE
+        #define JSON_HEDLEY_PUBLIC
+    #endif
+    #define JSON_HEDLEY_IMPORT    extern
+#endif
+
+#if defined(JSON_HEDLEY_NO_THROW)
+    #undef JSON_HEDLEY_NO_THROW
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+    #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
+#elif \
+    JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+    #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
+#else
+    #define JSON_HEDLEY_NO_THROW
+#endif
+
+#if defined(JSON_HEDLEY_FALL_THROUGH)
+    #undef JSON_HEDLEY_FALL_THROUGH
+#endif
+#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION)
+    #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
+    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
+    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
+#elif defined(__fallthrough) /* SAL */
+    #define JSON_HEDLEY_FALL_THROUGH __fallthrough
+#else
+    #define JSON_HEDLEY_FALL_THROUGH
+#endif
+
+#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
+    #undef JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+#if \
+    JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
+    #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
+#elif defined(_Ret_notnull_) /* SAL */
+    #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
+#else
+    #define JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+
+#if defined(JSON_HEDLEY_ARRAY_PARAM)
+    #undef JSON_HEDLEY_ARRAY_PARAM
+#endif
+#if \
+    defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+    !defined(__STDC_NO_VLA__) && \
+    !defined(__cplusplus) && \
+    !defined(JSON_HEDLEY_PGI_VERSION) && \
+    !defined(JSON_HEDLEY_TINYC_VERSION)
+    #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
+#else
+    #define JSON_HEDLEY_ARRAY_PARAM(name)
+#endif
+
+#if defined(JSON_HEDLEY_IS_CONSTANT)
+    #undef JSON_HEDLEY_IS_CONSTANT
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
+    #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#endif
+/* JSON_HEDLEY_IS_CONSTEXPR_ is for
+   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+    #undef JSON_HEDLEY_IS_CONSTEXPR_
+#endif
+#if \
+    JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
+    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
+    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+    JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \
+    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
+    JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0)
+    #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
+#endif
+#if !defined(__cplusplus)
+#  if \
+       JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
+       JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+       JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+       JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+       JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+       JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
+#if defined(__INTPTR_TYPE__)
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
+#else
+    #include <stdint.h>
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
+#endif
+#  elif \
+       (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
+       JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \
+       JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+       JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
+       JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+       JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
+#if defined(__INTPTR_TYPE__)
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
+#else
+    #include <stdint.h>
+    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
+#endif
+#  elif \
+       defined(JSON_HEDLEY_GCC_VERSION) || \
+       defined(JSON_HEDLEY_INTEL_VERSION) || \
+       defined(JSON_HEDLEY_TINYC_VERSION) || \
+       defined(JSON_HEDLEY_TI_VERSION) || \
+       defined(__clang__)
+#    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
+        sizeof(void) != \
+        sizeof(*( \
+                  1 ? \
+                  ((void*) ((expr) * 0L) ) : \
+((struct { char v[sizeof(void) * 2]; } *) 1) \
+                ) \
+              ) \
+                                            )
+#  endif
+#endif
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+    #if !defined(JSON_HEDLEY_IS_CONSTANT)
+        #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
+    #endif
+    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
+#else
+    #if !defined(JSON_HEDLEY_IS_CONSTANT)
+        #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
+    #endif
+    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
+    #undef JSON_HEDLEY_BEGIN_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_END_C_DECLS)
+    #undef JSON_HEDLEY_END_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_C_DECL)
+    #undef JSON_HEDLEY_C_DECL
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
+    #define JSON_HEDLEY_END_C_DECLS }
+    #define JSON_HEDLEY_C_DECL extern "C"
+#else
+    #define JSON_HEDLEY_BEGIN_C_DECLS
+    #define JSON_HEDLEY_END_C_DECLS
+    #define JSON_HEDLEY_C_DECL
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_ASSERT)
+    #undef JSON_HEDLEY_STATIC_ASSERT
+#endif
+#if \
+  !defined(__cplusplus) && ( \
+      (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
+      JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \
+      JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
+      JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+      defined(_Static_assert) \
+    )
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
+#elif \
+  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
+  JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
+  (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0))
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
+#else
+#  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
+#endif
+
+#if defined(JSON_HEDLEY_CONST_CAST)
+    #undef JSON_HEDLEY_CONST_CAST
+#endif
+#if defined(__cplusplus)
+#  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
+#elif \
+  JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
+        JSON_HEDLEY_DIAGNOSTIC_PUSH \
+        JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
+        ((T) (expr)); \
+        JSON_HEDLEY_DIAGNOSTIC_POP \
+    }))
+#else
+#  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_REINTERPRET_CAST)
+    #undef JSON_HEDLEY_REINTERPRET_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
+#else
+    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr)))
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_CAST)
+    #undef JSON_HEDLEY_STATIC_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
+#else
+    #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_CPP_CAST)
+    #undef JSON_HEDLEY_CPP_CAST
+#endif
+#if defined(__cplusplus)
+    #define JSON_HEDLEY_CPP_CAST(T, expr) static_cast<T>(expr)
+#else
+    #define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_NULL)
+    #undef JSON_HEDLEY_NULL
+#endif
+#if defined(__cplusplus)
+    #if __cplusplus >= 201103L
+        #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
+    #elif defined(NULL)
+        #define JSON_HEDLEY_NULL NULL
+    #else
+        #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
+    #endif
+#elif defined(NULL)
+    #define JSON_HEDLEY_NULL NULL
+#else
+    #define JSON_HEDLEY_NULL ((void*) 0)
+#endif
+
+#if defined(JSON_HEDLEY_MESSAGE)
+    #undef JSON_HEDLEY_MESSAGE
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+#  define JSON_HEDLEY_MESSAGE(msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+    JSON_HEDLEY_PRAGMA(message msg) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
+  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
+#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
+#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+#  define JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_WARNING)
+    #undef JSON_HEDLEY_WARNING
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+#  define JSON_HEDLEY_WARNING(msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+    JSON_HEDLEY_PRAGMA(clang warning msg) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+  JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
+  JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0)
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_REQUIRE)
+    #undef JSON_HEDLEY_REQUIRE
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_MSG)
+    #undef JSON_HEDLEY_REQUIRE_MSG
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
+#  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
+#    define JSON_HEDLEY_REQUIRE(expr) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+    __attribute__((diagnose_if(!(expr), #expr, "error"))) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
+    JSON_HEDLEY_DIAGNOSTIC_PUSH \
+    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+    __attribute__((diagnose_if(!(expr), msg, "error"))) \
+    JSON_HEDLEY_DIAGNOSTIC_POP
+#  else
+#    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
+#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
+#  endif
+#else
+#  define JSON_HEDLEY_REQUIRE(expr)
+#  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS)
+    #undef JSON_HEDLEY_FLAGS
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum)
+    #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS_CAST)
+    #undef JSON_HEDLEY_FLAGS_CAST
+#endif
+#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
+#  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
+        JSON_HEDLEY_DIAGNOSTIC_PUSH \
+        _Pragma("warning(disable:188)") \
+        ((T) (expr)); \
+        JSON_HEDLEY_DIAGNOSTIC_POP \
+    }))
+#else
+#  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
+#endif
+
+#if defined(JSON_HEDLEY_EMPTY_BASES)
+    #undef JSON_HEDLEY_EMPTY_BASES
+#endif
+#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)
+    #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
+#else
+    #define JSON_HEDLEY_EMPTY_BASES
+#endif
+
+/* Remaining macros are deprecated. */
+
+#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
+    #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#endif
+#if defined(__clang__)
+    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
+#else
+    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
+    #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#endif
+#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
+    #undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
+    #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#endif
+#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
+    #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
+    #undef JSON_HEDLEY_CLANG_HAS_WARNING
+#endif
+#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
+
+#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
+
+
+// This file contains all internal macro definitions
+// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
+
+// exclude unsupported compilers
+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
+    #if defined(__clang__)
+        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+        #endif
+    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
+            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+        #endif
+    #endif
+#endif
+
+// C++ language standard detection
+#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+    #define JSON_HAS_CPP_17
+    #define JSON_HAS_CPP_14
+#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+    #define JSON_HAS_CPP_14
+#endif
+
+// disable float-equal warnings on GCC/clang
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+    #pragma GCC diagnostic push
+    #pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+
+// disable documentation warnings on clang
+#if defined(__clang__)
+    #pragma GCC diagnostic push
+    #pragma GCC diagnostic ignored "-Wdocumentation"
+#endif
+
+// allow to disable exceptions
+#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
+    #define JSON_THROW(exception) throw exception
+    #define JSON_TRY try
+    #define JSON_CATCH(exception) catch(exception)
+    #define JSON_INTERNAL_CATCH(exception) catch(exception)
+#else
+    #include <cstdlib>
+    #define JSON_THROW(exception) std::abort()
+    #define JSON_TRY if(true)
+    #define JSON_CATCH(exception) if(false)
+    #define JSON_INTERNAL_CATCH(exception) if(false)
+#endif
+
+// override exception macros
+#if defined(JSON_THROW_USER)
+    #undef JSON_THROW
+    #define JSON_THROW JSON_THROW_USER
+#endif
+#if defined(JSON_TRY_USER)
+    #undef JSON_TRY
+    #define JSON_TRY JSON_TRY_USER
+#endif
+#if defined(JSON_CATCH_USER)
+    #undef JSON_CATCH
+    #define JSON_CATCH JSON_CATCH_USER
+    #undef JSON_INTERNAL_CATCH
+    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
+#endif
+#if defined(JSON_INTERNAL_CATCH_USER)
+    #undef JSON_INTERNAL_CATCH
+    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
+#endif
+
+/*!
+@brief macro to briefly define a mapping between an enum and JSON
+@def NLOHMANN_JSON_SERIALIZE_ENUM
+@since version 3.4.0
+*/
+#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
+    template<typename BasicJsonType>                                                            \
+    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
+    {                                                                                           \
+        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
+        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
+        auto it = std::find_if(std::begin(m), std::end(m),                                      \
+                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
+        {                                                                                       \
+            return ej_pair.first == e;                                                          \
+        });                                                                                     \
+        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
+    }                                                                                           \
+    template<typename BasicJsonType>                                                            \
+    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
+    {                                                                                           \
+        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
+        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
+        auto it = std::find_if(std::begin(m), std::end(m),                                      \
+                               [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
+        {                                                                                       \
+            return ej_pair.second == j;                                                         \
+        });                                                                                     \
+        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
+    }
+
+// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
+// may be removed in the future once the class is split.
+
+#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
+    template<template<typename, typename, typename...> class ObjectType,   \
+             template<typename, typename...> class ArrayType,              \
+             class StringType, class BooleanType, class NumberIntegerType, \
+             class NumberUnsignedType, class NumberFloatType,              \
+             template<typename> class AllocatorType,                       \
+             template<typename, typename = void> class JSONSerializer>
+
+#define NLOHMANN_BASIC_JSON_TPL                                            \
+    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
+    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
+    AllocatorType, JSONSerializer>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+////////////////
+// exceptions //
+////////////////
+
+/*!
+@brief general exception of the @ref basic_json class
+
+This class is an extension of `std::exception` objects with a member @a id for
+exception ids. It is used as the base class for all exceptions thrown by the
+@ref basic_json class. This class can hence be used as "wildcard" to catch
+exceptions.
+
+Subclasses:
+- @ref parse_error for exceptions indicating a parse error
+- @ref invalid_iterator for exceptions indicating errors with iterators
+- @ref type_error for exceptions indicating executing a member function with
+                  a wrong type
+- @ref out_of_range for exceptions indicating access out of the defined range
+- @ref other_error for exceptions indicating other library errors
+
+@internal
+@note To have nothrow-copy-constructible exceptions, we internally use
+      `std::runtime_error` which can cope with arbitrary-length error messages.
+      Intermediate strings are built with static functions and then passed to
+      the actual constructor.
+@endinternal
+
+@liveexample{The following code shows how arbitrary library exceptions can be
+caught.,exception}
+
+@since version 3.0.0
+*/
+class exception : public std::exception
+{
+  public:
+    /// returns the explanatory string
+    JSON_HEDLEY_RETURNS_NON_NULL
+    const char* what() const noexcept override
+    {
+        return m.what();
+    }
+
+    /// the id of the exception
+    const int id;
+
+  protected:
+    JSON_HEDLEY_NON_NULL(3)
+    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
+
+    static std::string name(const std::string& ename, int id_)
+    {
+        return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
+    }
+
+  private:
+    /// an exception object as storage for error messages
+    std::runtime_error m;
+};
+
+/*!
+@brief exception indicating a parse error
+
+This exception is thrown by the library when a parse error occurs. Parse errors
+can occur during the deserialization of JSON text, CBOR, MessagePack, as well
+as when using JSON Patch.
+
+Member @a byte holds the byte index of the last read character in the input
+file.
+
+Exceptions have ids 1xx.
+
+name / id                      | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
+json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
+json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
+json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
+json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
+json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
+json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
+json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
+json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
+json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
+json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
+json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
+json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
+
+@note For an input with n bytes, 1 is the index of the first character and n+1
+      is the index of the terminating null byte or the end of file. This also
+      holds true when reading a byte vector (CBOR or MessagePack).
+
+@liveexample{The following code shows how a `parse_error` exception can be
+caught.,parse_error}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class parse_error : public exception
+{
+  public:
+    /*!
+    @brief create a parse error exception
+    @param[in] id_       the id of the exception
+    @param[in] pos       the position where the error occurred (or with
+                         chars_read_total=0 if the position cannot be
+                         determined)
+    @param[in] what_arg  the explanatory string
+    @return parse_error object
+    */
+    static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
+    {
+        std::string w = exception::name("parse_error", id_) + "parse error" +
+                        position_string(pos) + ": " + what_arg;
+        return parse_error(id_, pos.chars_read_total, w.c_str());
+    }
+
+    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
+    {
+        std::string w = exception::name("parse_error", id_) + "parse error" +
+                        (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
+                        ": " + what_arg;
+        return parse_error(id_, byte_, w.c_str());
+    }
+
+    /*!
+    @brief byte index of the parse error
+
+    The byte index of the last read character in the input file.
+
+    @note For an input with n bytes, 1 is the index of the first character and
+          n+1 is the index of the terminating null byte or the end of file.
+          This also holds true when reading a byte vector (CBOR or MessagePack).
+    */
+    const std::size_t byte;
+
+  private:
+    parse_error(int id_, std::size_t byte_, const char* what_arg)
+        : exception(id_, what_arg), byte(byte_) {}
+
+    static std::string position_string(const position_t& pos)
+    {
+        return " at line " + std::to_string(pos.lines_read + 1) +
+               ", column " + std::to_string(pos.chars_read_current_line);
+    }
+};
+
+/*!
+@brief exception indicating errors with iterators
+
+This exception is thrown if iterators passed to a library function do not match
+the expected semantics.
+
+Exceptions have ids 2xx.
+
+name / id                           | example message | description
+----------------------------------- | --------------- | -------------------------
+json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
+json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
+json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
+json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
+json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
+json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
+json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
+json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
+json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
+json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
+
+@liveexample{The following code shows how an `invalid_iterator` exception can be
+caught.,invalid_iterator}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class invalid_iterator : public exception
+{
+  public:
+    static invalid_iterator create(int id_, const std::string& what_arg)
+    {
+        std::string w = exception::name("invalid_iterator", id_) + what_arg;
+        return invalid_iterator(id_, w.c_str());
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    invalid_iterator(int id_, const char* what_arg)
+        : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating executing a member function with a wrong type
+
+This exception is thrown in case of a type error; that is, a library function is
+executed on a JSON value whose type does not match the expected semantics.
+
+Exceptions have ids 3xx.
+
+name / id                     | example message | description
+----------------------------- | --------------- | -------------------------
+json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
+json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
+json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
+json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
+json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
+json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
+json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
+json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
+json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
+json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
+json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
+json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
+json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
+json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
+json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
+json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
+json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
+
+@liveexample{The following code shows how a `type_error` exception can be
+caught.,type_error}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class type_error : public exception
+{
+  public:
+    static type_error create(int id_, const std::string& what_arg)
+    {
+        std::string w = exception::name("type_error", id_) + what_arg;
+        return type_error(id_, w.c_str());
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating access out of the defined range
+
+This exception is thrown in case a library function is called on an input
+parameter that exceeds the expected range, for instance in case of array
+indices or nonexisting object keys.
+
+Exceptions have ids 4xx.
+
+name / id                       | example message | description
+------------------------------- | --------------- | -------------------------
+json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
+json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
+json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
+json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
+json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
+json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
+json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
+json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
+json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
+
+@liveexample{The following code shows how an `out_of_range` exception can be
+caught.,out_of_range}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class out_of_range : public exception
+{
+  public:
+    static out_of_range create(int id_, const std::string& what_arg)
+    {
+        std::string w = exception::name("out_of_range", id_) + what_arg;
+        return out_of_range(id_, w.c_str());
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating other library errors
+
+This exception is thrown in case of errors that cannot be classified with the
+other exception types.
+
+Exceptions have ids 5xx.
+
+name / id                      | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+                    a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+
+@liveexample{The following code shows how an `other_error` exception can be
+caught.,other_error}
+
+@since version 3.0.0
+*/
+class other_error : public exception
+{
+  public:
+    static other_error create(int id_, const std::string& what_arg)
+    {
+        std::string w = exception::name("other_error", id_) + what_arg;
+        return other_error(id_, w.c_str());
+    }
+
+  private:
+    JSON_HEDLEY_NON_NULL(3)
+    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+#include <ciso646> // not
+#include <cstddef> // size_t
+#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
+
+namespace nlohmann
+{
+namespace detail
+{
+// alias templates to reduce boilerplate
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+template<typename T>
+using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+// implementation of C++14 index_sequence and affiliates
+// source: https://stackoverflow.com/a/32223343
+template<std::size_t... Ints>
+struct index_sequence
+{
+    using type = index_sequence;
+    using value_type = std::size_t;
+    static constexpr std::size_t size() noexcept
+    {
+        return sizeof...(Ints);
+    }
+};
+
+template<class Sequence1, class Sequence2>
+struct merge_and_renumber;
+
+template<std::size_t... I1, std::size_t... I2>
+struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
+        : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
+
+template<std::size_t N>
+struct make_index_sequence
+    : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
+      typename make_index_sequence < N - N / 2 >::type > {};
+
+template<> struct make_index_sequence<0> : index_sequence<> {};
+template<> struct make_index_sequence<1> : index_sequence<0> {};
+
+template<typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+// dispatch utility (taken from ranges-v3)
+template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
+template<> struct priority_tag<0> {};
+
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+    static constexpr T value{};
+};
+
+template<typename T>
+constexpr T static_const<T>::value;
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+#include <ciso646> // not
+#include <limits> // numeric_limits
+#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
+#include <utility> // declval
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+
+#include <iterator> // random_access_iterator_tag
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename ...Ts> struct make_void
+{
+    using type = void;
+};
+template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
+} // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename It, typename = void>
+struct iterator_types {};
+
+template <typename It>
+struct iterator_types <
+    It,
+    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
+    typename It::reference, typename It::iterator_category >>
+{
+    using difference_type = typename It::difference_type;
+    using value_type = typename It::value_type;
+    using pointer = typename It::pointer;
+    using reference = typename It::reference;
+    using iterator_category = typename It::iterator_category;
+};
+
+// This is required as some compilers implement std::iterator_traits in a way that
+// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
+template <typename T, typename = void>
+struct iterator_traits
+{
+};
+
+template <typename T>
+struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
+            : iterator_types<T>
+{
+};
+
+template <typename T>
+struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
+{
+    using iterator_category = std::random_access_iterator_tag;
+    using value_type = T;
+    using difference_type = ptrdiff_t;
+    using pointer = T*;
+    using reference = T&;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+
+#include <type_traits>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+
+// http://en.cppreference.com/w/cpp/experimental/is_detected
+namespace nlohmann
+{
+namespace detail
+{
+struct nonesuch
+{
+    nonesuch() = delete;
+    ~nonesuch() = delete;
+    nonesuch(nonesuch const&) = delete;
+    nonesuch(nonesuch const&&) = delete;
+    void operator=(nonesuch const&) = delete;
+    void operator=(nonesuch&&) = delete;
+};
+
+template <class Default,
+          class AlwaysVoid,
+          template <class...> class Op,
+          class... Args>
+struct detector
+{
+    using value_t = std::false_type;
+    using type = Default;
+};
+
+template <class Default, template <class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+    using value_t = std::true_type;
+    using type = Op<Args...>;
+};
+
+template <template <class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
+
+template <template <class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
+
+template <class Default, template <class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template <class Default, template <class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template <class Expected, template <class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template <class To, template <class...> class Op, class... Args>
+using is_detected_convertible =
+    std::is_convertible<detected_t<Op, Args...>, To>;
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/json_fwd.hpp>
+#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
+#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+#include <cstdint> // int64_t, uint64_t
+#include <map> // map
+#include <memory> // allocator
+#include <string> // string
+#include <vector> // vector
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+/*!
+@brief default JSONSerializer template argument
+
+This serializer ignores the template arguments and uses ADL
+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
+for serialization.
+*/
+template<typename T = void, typename SFINAE = void>
+struct adl_serializer;
+
+template<template<typename U, typename V, typename... Args> class ObjectType =
+         std::map,
+         template<typename U, typename... Args> class ArrayType = std::vector,
+         class StringType = std::string, class BooleanType = bool,
+         class NumberIntegerType = std::int64_t,
+         class NumberUnsignedType = std::uint64_t,
+         class NumberFloatType = double,
+         template<typename U> class AllocatorType = std::allocator,
+         template<typename T, typename SFINAE = void> class JSONSerializer =
+         adl_serializer>
+class basic_json;
+
+/*!
+@brief JSON Pointer
+
+A JSON pointer defines a string syntax for identifying a specific value
+within a JSON document. It can be used with functions `at` and
+`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
+
+@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
+
+@since version 2.0.0
+*/
+template<typename BasicJsonType>
+class json_pointer;
+
+/*!
+@brief default JSON class
+
+This type is the default specialization of the @ref basic_json class which
+uses the standard template types.
+
+@since version 1.0.0
+*/
+using json = basic_json<>;
+}  // namespace nlohmann
+
+#endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+
+namespace nlohmann
+{
+/*!
+@brief detail namespace with internal helper functions
+
+This namespace collects functions that should not be exposed,
+implementations of some @ref basic_json methods, and meta-programming helpers.
+
+@since version 2.1.0
+*/
+namespace detail
+{
+/////////////
+// helpers //
+/////////////
+
+// Note to maintainers:
+//
+// Every trait in this file expects a non CV-qualified type.
+// The only exceptions are in the 'aliases for detected' section
+// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
+//
+// In this case, T has to be properly CV-qualified to constraint the function arguments
+// (e.g. to_json(BasicJsonType&, const T&))
+
+template<typename> struct is_basic_json : std::false_type {};
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+
+//////////////////////////
+// aliases for detected //
+//////////////////////////
+
+template <typename T>
+using mapped_type_t = typename T::mapped_type;
+
+template <typename T>
+using key_type_t = typename T::key_type;
+
+template <typename T>
+using value_type_t = typename T::value_type;
+
+template <typename T>
+using difference_type_t = typename T::difference_type;
+
+template <typename T>
+using pointer_t = typename T::pointer;
+
+template <typename T>
+using reference_t = typename T::reference;
+
+template <typename T>
+using iterator_category_t = typename T::iterator_category;
+
+template <typename T>
+using iterator_t = typename T::iterator;
+
+template <typename T, typename... Args>
+using to_json_function = decltype(T::to_json(std::declval<Args>()...));
+
+template <typename T, typename... Args>
+using from_json_function = decltype(T::from_json(std::declval<Args>()...));
+
+template <typename T, typename U>
+using get_template_function = decltype(std::declval<T>().template get<U>());
+
+// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
+template <typename BasicJsonType, typename T, typename = void>
+struct has_from_json : std::false_type {};
+
+template <typename BasicJsonType, typename T>
+struct has_from_json<BasicJsonType, T,
+           enable_if_t<not is_basic_json<T>::value>>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<void, from_json_function, serializer,
+        const BasicJsonType&, T&>::value;
+};
+
+// This trait checks if JSONSerializer<T>::from_json(json const&) exists
+// this overload is used for non-default-constructible user-defined-types
+template <typename BasicJsonType, typename T, typename = void>
+struct has_non_default_from_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<T, from_json_function, serializer,
+        const BasicJsonType&>::value;
+};
+
+// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
+// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
+template <typename BasicJsonType, typename T, typename = void>
+struct has_to_json : std::false_type {};
+
+template <typename BasicJsonType, typename T>
+struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
+{
+    using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+    static constexpr bool value =
+        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
+        T>::value;
+};
+
+
+///////////////////
+// is_ functions //
+///////////////////
+
+template <typename T, typename = void>
+struct is_iterator_traits : std::false_type {};
+
+template <typename T>
+struct is_iterator_traits<iterator_traits<T>>
+{
+  private:
+    using traits = iterator_traits<T>;
+
+  public:
+    static constexpr auto value =
+        is_detected<value_type_t, traits>::value &&
+        is_detected<difference_type_t, traits>::value &&
+        is_detected<pointer_t, traits>::value &&
+        is_detected<iterator_category_t, traits>::value &&
+        is_detected<reference_t, traits>::value;
+};
+
+// source: https://stackoverflow.com/a/37193089/4116453
+
+template <typename T, typename = void>
+struct is_complete_type : std::false_type {};
+
+template <typename T>
+struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
+
+template <typename BasicJsonType, typename CompatibleObjectType,
+          typename = void>
+struct is_compatible_object_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type_impl <
+    BasicJsonType, CompatibleObjectType,
+    enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
+    is_detected<key_type_t, CompatibleObjectType>::value >>
+{
+
+    using object_t = typename BasicJsonType::object_t;
+
+    // macOS's is_constructible does not play well with nonesuch...
+    static constexpr bool value =
+        std::is_constructible<typename object_t::key_type,
+        typename CompatibleObjectType::key_type>::value and
+        std::is_constructible<typename object_t::mapped_type,
+        typename CompatibleObjectType::mapped_type>::value;
+};
+
+template <typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type
+    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
+
+template <typename BasicJsonType, typename ConstructibleObjectType,
+          typename = void>
+struct is_constructible_object_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type_impl <
+    BasicJsonType, ConstructibleObjectType,
+    enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
+    is_detected<key_type_t, ConstructibleObjectType>::value >>
+{
+    using object_t = typename BasicJsonType::object_t;
+
+    static constexpr bool value =
+        (std::is_default_constructible<ConstructibleObjectType>::value and
+         (std::is_move_assignable<ConstructibleObjectType>::value or
+          std::is_copy_assignable<ConstructibleObjectType>::value) and
+         (std::is_constructible<typename ConstructibleObjectType::key_type,
+          typename object_t::key_type>::value and
+          std::is_same <
+          typename object_t::mapped_type,
+          typename ConstructibleObjectType::mapped_type >::value)) or
+        (has_from_json<BasicJsonType,
+         typename ConstructibleObjectType::mapped_type>::value or
+         has_non_default_from_json <
+         BasicJsonType,
+         typename ConstructibleObjectType::mapped_type >::value);
+};
+
+template <typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type
+    : is_constructible_object_type_impl<BasicJsonType,
+      ConstructibleObjectType> {};
+
+template <typename BasicJsonType, typename CompatibleStringType,
+          typename = void>
+struct is_compatible_string_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleStringType>
+struct is_compatible_string_type_impl <
+    BasicJsonType, CompatibleStringType,
+    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
+    value_type_t, CompatibleStringType>::value >>
+{
+    static constexpr auto value =
+        std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
+};
+
+template <typename BasicJsonType, typename ConstructibleStringType>
+struct is_compatible_string_type
+    : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
+
+template <typename BasicJsonType, typename ConstructibleStringType,
+          typename = void>
+struct is_constructible_string_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename ConstructibleStringType>
+struct is_constructible_string_type_impl <
+    BasicJsonType, ConstructibleStringType,
+    enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
+    value_type_t, ConstructibleStringType>::value >>
+{
+    static constexpr auto value =
+        std::is_constructible<ConstructibleStringType,
+        typename BasicJsonType::string_t>::value;
+};
+
+template <typename BasicJsonType, typename ConstructibleStringType>
+struct is_constructible_string_type
+    : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
+
+template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
+struct is_compatible_array_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type_impl <
+    BasicJsonType, CompatibleArrayType,
+    enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
+    is_detected<iterator_t, CompatibleArrayType>::value and
+// This is needed because json_reverse_iterator has a ::iterator type...
+// Therefore it is detected as a CompatibleArrayType.
+// The real fix would be to have an Iterable concept.
+    not is_iterator_traits<
+    iterator_traits<CompatibleArrayType>>::value >>
+{
+    static constexpr bool value =
+        std::is_constructible<BasicJsonType,
+        typename CompatibleArrayType::value_type>::value;
+};
+
+template <typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type
+    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
+
+template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
+struct is_constructible_array_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+    BasicJsonType, ConstructibleArrayType,
+    enable_if_t<std::is_same<ConstructibleArrayType,
+    typename BasicJsonType::value_type>::value >>
+            : std::true_type {};
+
+template <typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+    BasicJsonType, ConstructibleArrayType,
+    enable_if_t<not std::is_same<ConstructibleArrayType,
+    typename BasicJsonType::value_type>::value and
+    std::is_default_constructible<ConstructibleArrayType>::value and
+(std::is_move_assignable<ConstructibleArrayType>::value or
+ std::is_copy_assignable<ConstructibleArrayType>::value) and
+is_detected<value_type_t, ConstructibleArrayType>::value and
+is_detected<iterator_t, ConstructibleArrayType>::value and
+is_complete_type<
+detected_t<value_type_t, ConstructibleArrayType>>::value >>
+{
+    static constexpr bool value =
+        // This is needed because json_reverse_iterator has a ::iterator type,
+        // furthermore, std::back_insert_iterator (and other iterators) have a
+        // base class `iterator`... Therefore it is detected as a
+        // ConstructibleArrayType. The real fix would be to have an Iterable
+        // concept.
+        not is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value and
+
+        (std::is_same<typename ConstructibleArrayType::value_type,
+         typename BasicJsonType::array_t::value_type>::value or
+         has_from_json<BasicJsonType,
+         typename ConstructibleArrayType::value_type>::value or
+         has_non_default_from_json <
+         BasicJsonType, typename ConstructibleArrayType::value_type >::value);
+};
+
+template <typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type
+    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
+
+template <typename RealIntegerType, typename CompatibleNumberIntegerType,
+          typename = void>
+struct is_compatible_integer_type_impl : std::false_type {};
+
+template <typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type_impl <
+    RealIntegerType, CompatibleNumberIntegerType,
+    enable_if_t<std::is_integral<RealIntegerType>::value and
+    std::is_integral<CompatibleNumberIntegerType>::value and
+    not std::is_same<bool, CompatibleNumberIntegerType>::value >>
+{
+    // is there an assert somewhere on overflows?
+    using RealLimits = std::numeric_limits<RealIntegerType>;
+    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
+
+    static constexpr auto value =
+        std::is_constructible<RealIntegerType,
+        CompatibleNumberIntegerType>::value and
+        CompatibleLimits::is_integer and
+        RealLimits::is_signed == CompatibleLimits::is_signed;
+};
+
+template <typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type
+    : is_compatible_integer_type_impl<RealIntegerType,
+      CompatibleNumberIntegerType> {};
+
+template <typename BasicJsonType, typename CompatibleType, typename = void>
+struct is_compatible_type_impl: std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type_impl <
+    BasicJsonType, CompatibleType,
+    enable_if_t<is_complete_type<CompatibleType>::value >>
+{
+    static constexpr bool value =
+        has_to_json<BasicJsonType, CompatibleType>::value;
+};
+
+template <typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type
+    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
+
+// https://en.cppreference.com/w/cpp/types/conjunction
+template<class...> struct conjunction : std::true_type { };
+template<class B1> struct conjunction<B1> : B1 { };
+template<class B1, class... Bn>
+struct conjunction<B1, Bn...>
+: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+template <typename T1, typename T2>
+struct is_constructible_tuple : std::false_type {};
+
+template <typename T1, typename... Args>
+struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#include <array> // array
+#include <ciso646> // and
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t
+#include <string> // string
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////////////
+// JSON type enumeration //
+///////////////////////////
+
+/*!
+@brief the JSON type enumeration
+
+This enumeration collects the different JSON types. It is internally used to
+distinguish the stored values, and the functions @ref basic_json::is_null(),
+@ref basic_json::is_object(), @ref basic_json::is_array(),
+@ref basic_json::is_string(), @ref basic_json::is_boolean(),
+@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
+@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
+@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
+@ref basic_json::is_structured() rely on it.
+
+@note There are three enumeration entries (number_integer, number_unsigned, and
+number_float), because the library distinguishes these three types for numbers:
+@ref basic_json::number_unsigned_t is used for unsigned integers,
+@ref basic_json::number_integer_t is used for signed integers, and
+@ref basic_json::number_float_t is used for floating-point numbers or to
+approximate integers which do not fit in the limits of their respective type.
+
+@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON
+value with the default value for a given type
+
+@since version 1.0.0
+*/
+enum class value_t : std::uint8_t
+{
+    null,             ///< null value
+    object,           ///< object (unordered set of name/value pairs)
+    array,            ///< array (ordered collection of values)
+    string,           ///< string value
+    boolean,          ///< boolean value
+    number_integer,   ///< number value (signed integer)
+    number_unsigned,  ///< number value (unsigned integer)
+    number_float,     ///< number value (floating-point)
+    discarded         ///< discarded by the the parser callback function
+};
+
+/*!
+@brief comparison operator for JSON types
+
+Returns an ordering that is similar to Python:
+- order: null < boolean < number < object < array < string
+- furthermore, each type is not smaller than itself
+- discarded values are not comparable
+
+@since version 1.0.0
+*/
+inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+{
+    static constexpr std::array<std::uint8_t, 8> order = {{
+            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
+            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
+        }
+    };
+
+    const auto l_index = static_cast<std::size_t>(lhs);
+    const auto r_index = static_cast<std::size_t>(rhs);
+    return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
+}
+}  // namespace detail
+}  // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_null()))
+    {
+        JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
+    }
+    n = nullptr;
+}
+
+// overloads for basic_json template parameters
+template<typename BasicJsonType, typename ArithmeticType,
+         enable_if_t<std::is_arithmetic<ArithmeticType>::value and
+                     not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+                     int> = 0>
+void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
+{
+    switch (static_cast<value_t>(j))
+    {
+        case value_t::number_unsigned:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+            break;
+        }
+        case value_t::number_integer:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+            break;
+        }
+        case value_t::number_float:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+            break;
+        }
+
+        default:
+            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
+    }
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_boolean()))
+    {
+        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
+    }
+    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
+    }
+    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template <
+    typename BasicJsonType, typename ConstructibleStringType,
+    enable_if_t <
+        is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
+        not std::is_same<typename BasicJsonType::string_t,
+                         ConstructibleStringType>::value,
+        int > = 0 >
+void from_json(const BasicJsonType& j, ConstructibleStringType& s)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
+    {
+        JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
+    }
+
+    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
+{
+    get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType, typename EnumType,
+         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void from_json(const BasicJsonType& j, EnumType& e)
+{
+    typename std::underlying_type<EnumType>::type val;
+    get_arithmetic_value(j, val);
+    e = static_cast<EnumType>(val);
+}
+
+// forward_list doesn't have an insert method
+template<typename BasicJsonType, typename T, typename Allocator,
+         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+    }
+    l.clear();
+    std::transform(j.rbegin(), j.rend(),
+                   std::front_inserter(l), [](const BasicJsonType & i)
+    {
+        return i.template get<T>();
+    });
+}
+
+// valarray doesn't have an insert method
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::valarray<T>& l)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+    }
+    l.resize(j.size());
+    std::copy(j.begin(), j.end(), std::begin(l));
+}
+
+template <typename BasicJsonType, typename T, std::size_t N>
+auto from_json(const BasicJsonType& j, T (&arr)[N])
+-> decltype(j.template get<T>(), void())
+{
+    for (std::size_t i = 0; i < N; ++i)
+    {
+        arr[i] = j.at(i).template get<T>();
+    }
+}
+
+template<typename BasicJsonType>
+void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
+{
+    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
+}
+
+template <typename BasicJsonType, typename T, std::size_t N>
+auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
+                          priority_tag<2> /*unused*/)
+-> decltype(j.template get<T>(), void())
+{
+    for (std::size_t i = 0; i < N; ++i)
+    {
+        arr[i] = j.at(i).template get<T>();
+    }
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
+-> decltype(
+    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
+    j.template get<typename ConstructibleArrayType::value_type>(),
+    void())
+{
+    using std::end;
+
+    ConstructibleArrayType ret;
+    ret.reserve(j.size());
+    std::transform(j.begin(), j.end(),
+                   std::inserter(ret, end(ret)), [](const BasicJsonType & i)
+    {
+        // get<BasicJsonType>() returns *this, this won't call a from_json
+        // method when value_type is BasicJsonType
+        return i.template get<typename ConstructibleArrayType::value_type>();
+    });
+    arr = std::move(ret);
+}
+
+template <typename BasicJsonType, typename ConstructibleArrayType>
+void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
+                          priority_tag<0> /*unused*/)
+{
+    using std::end;
+
+    ConstructibleArrayType ret;
+    std::transform(
+        j.begin(), j.end(), std::inserter(ret, end(ret)),
+        [](const BasicJsonType & i)
+    {
+        // get<BasicJsonType>() returns *this, this won't call a from_json
+        // method when value_type is BasicJsonType
+        return i.template get<typename ConstructibleArrayType::value_type>();
+    });
+    arr = std::move(ret);
+}
+
+template <typename BasicJsonType, typename ConstructibleArrayType,
+          enable_if_t <
+              is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
+              not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
+              not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
+              not is_basic_json<ConstructibleArrayType>::value,
+              int > = 0 >
+
+auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
+-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
+j.template get<typename ConstructibleArrayType::value_type>(),
+void())
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " +
+                                      std::string(j.type_name())));
+    }
+
+    from_json_array_impl(j, arr, priority_tag<3> {});
+}
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
+void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
+    {
+        JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
+    }
+
+    ConstructibleObjectType ret;
+    auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
+    using value_type = typename ConstructibleObjectType::value_type;
+    std::transform(
+        inner_object->begin(), inner_object->end(),
+        std::inserter(ret, ret.begin()),
+        [](typename BasicJsonType::object_t::value_type const & p)
+    {
+        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
+    });
+    obj = std::move(ret);
+}
+
+// overload for arithmetic types, not chosen for basic_json template arguments
+// (BooleanType, etc..); note: Is it really necessary to provide explicit
+// overloads for boolean_t etc. in case of a custom BooleanType which is not
+// an arithmetic type?
+template<typename BasicJsonType, typename ArithmeticType,
+         enable_if_t <
+             std::is_arithmetic<ArithmeticType>::value and
+             not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
+             not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
+             not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
+             not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+             int> = 0>
+void from_json(const BasicJsonType& j, ArithmeticType& val)
+{
+    switch (static_cast<value_t>(j))
+    {
+        case value_t::number_unsigned:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+            break;
+        }
+        case value_t::number_integer:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+            break;
+        }
+        case value_t::number_float:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+            break;
+        }
+        case value_t::boolean:
+        {
+            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
+            break;
+        }
+
+        default:
+            JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
+    }
+}
+
+template<typename BasicJsonType, typename A1, typename A2>
+void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
+{
+    p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
+{
+    t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
+}
+
+template<typename BasicJsonType, typename... Args>
+void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
+{
+    from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
+}
+
+template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
+          typename = enable_if_t<not std::is_constructible<
+                                     typename BasicJsonType::string_t, Key>::value>>
+void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+    }
+    m.clear();
+    for (const auto& p : j)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
+        {
+            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
+        }
+        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+    }
+}
+
+template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
+          typename = enable_if_t<not std::is_constructible<
+                                     typename BasicJsonType::string_t, Key>::value>>
+void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+{
+    if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
+    {
+        JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+    }
+    m.clear();
+    for (const auto& p : j)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
+        {
+            JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
+        }
+        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+    }
+}
+
+struct from_json_fn
+{
+    template<typename BasicJsonType, typename T>
+    auto operator()(const BasicJsonType& j, T& val) const
+    noexcept(noexcept(from_json(j, val)))
+    -> decltype(from_json(j, val), void())
+    {
+        return from_json(j, val);
+    }
+};
+}  // namespace detail
+
+/// namespace to hold default `from_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace
+{
+constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
+} // namespace
+} // namespace nlohmann
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+
+#include <algorithm> // copy
+#include <ciso646> // or, and, not
+#include <iterator> // begin, end
+#include <string> // string
+#include <tuple> // tuple, get
+#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
+#include <utility> // move, forward, declval, pair
+#include <valarray> // valarray
+#include <vector> // vector
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+
+#include <cstddef> // size_t
+#include <iterator> // input_iterator_tag
+#include <string> // string, to_string
+#include <tuple> // tuple_size, get, tuple_element
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename string_type>
+void int_to_string( string_type& target, std::size_t value )
+{
+    target = std::to_string(value);
+}
+template <typename IteratorType> class iteration_proxy_value
+{
+  public:
+    using difference_type = std::ptrdiff_t;
+    using value_type = iteration_proxy_value;
+    using pointer = value_type * ;
+    using reference = value_type & ;
+    using iterator_category = std::input_iterator_tag;
+    using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
+
+  private:
+    /// the iterator
+    IteratorType anchor;
+    /// an index for arrays (used to create key names)
+    std::size_t array_index = 0;
+    /// last stringified array index
+    mutable std::size_t array_index_last = 0;
+    /// a string representation of the array index
+    mutable string_type array_index_str = "0";
+    /// an empty string (to return a reference for primitive values)
+    const string_type empty_str = "";
+
+  public:
+    explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
+
+    /// dereference operator (needed for range-based for)
+    iteration_proxy_value& operator*()
+    {
+        return *this;
+    }
+
+    /// increment operator (needed for range-based for)
+    iteration_proxy_value& operator++()
+    {
+        ++anchor;
+        ++array_index;
+
+        return *this;
+    }
+
+    /// equality operator (needed for InputIterator)
+    bool operator==(const iteration_proxy_value& o) const
+    {
+        return anchor == o.anchor;
+    }
+
+    /// inequality operator (needed for range-based for)
+    bool operator!=(const iteration_proxy_value& o) const
+    {
+        return anchor != o.anchor;
+    }
+
+    /// return key of the iterator
+    const string_type& key() const
+    {
+        assert(anchor.m_object != nullptr);
+
+        switch (anchor.m_object->type())
+        {
+            // use integer array index as key
+            case value_t::array:
+            {
+                if (array_index != array_index_last)
+                {
+                    int_to_string( array_index_str, array_index );
+                    array_index_last = array_index;
+                }
+                return array_index_str;
+            }
+
+            // use key from the object
+            case value_t::object:
+                return anchor.key();
+
+            // use an empty key for all primitive types
+            default:
+                return empty_str;
+        }
+    }
+
+    /// return value of the iterator
+    typename IteratorType::reference value() const
+    {
+        return anchor.value();
+    }
+};
+
+/// proxy class for the items() function
+template<typename IteratorType> class iteration_proxy
+{
+  private:
+    /// the container to iterate
+    typename IteratorType::reference container;
+
+  public:
+    /// construct iteration proxy from a container
+    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
+        : container(cont) {}
+
+    /// return iterator begin (needed for range-based for)
+    iteration_proxy_value<IteratorType> begin() noexcept
+    {
+        return iteration_proxy_value<IteratorType>(container.begin());
+    }
+
+    /// return iterator end (needed for range-based for)
+    iteration_proxy_value<IteratorType> end() noexcept
+    {
+        return iteration_proxy_value<IteratorType>(container.end());
+    }
+};
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
+{
+    return i.key();
+}
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
+{
+    return i.value();
+}
+}  // namespace detail
+}  // namespace nlohmann
+
+// The Addition to the STD Namespace is required to add
+// Structured Bindings Support to the iteration_proxy_value class
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+namespace std
+{
+#if defined(__clang__)
+    // Fix: https://github.com/nlohmann/json/issues/1401
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+template <typename IteratorType>
+class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
+            : public std::integral_constant<std::size_t, 2> {};
+
+template <std::size_t N, typename IteratorType>
+class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
+{
+  public:
+    using type = decltype(
+                     get<N>(std::declval <
+                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
+};
+#if defined(__clang__)
+    #pragma clang diagnostic pop
+#endif
+} // namespace std
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+//////////////////
+// constructors //
+//////////////////
+
+template<value_t> struct external_constructor;
+
+template<>
+struct external_constructor<value_t::boolean>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
+    {
+        j.m_type = value_t::boolean;
+        j.m_value = b;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::string>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
+    {
+        j.m_type = value_t::string;
+        j.m_value = s;
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+    {
+        j.m_type = value_t::string;
+        j.m_value = std::move(s);
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType, typename CompatibleStringType,
+             enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
+                         int> = 0>
+    static void construct(BasicJsonType& j, const CompatibleStringType& str)
+    {
+        j.m_type = value_t::string;
+        j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_float>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
+    {
+        j.m_type = value_t::number_float;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_unsigned>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
+    {
+        j.m_type = value_t::number_unsigned;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::number_integer>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
+    {
+        j.m_type = value_t::number_integer;
+        j.m_value = val;
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::array>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
+    {
+        j.m_type = value_t::array;
+        j.m_value = arr;
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+    {
+        j.m_type = value_t::array;
+        j.m_value = std::move(arr);
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType, typename CompatibleArrayType,
+             enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
+                         int> = 0>
+    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
+    {
+        using std::begin;
+        using std::end;
+        j.m_type = value_t::array;
+        j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
+    {
+        j.m_type = value_t::array;
+        j.m_value = value_t::array;
+        j.m_value.array->reserve(arr.size());
+        for (const bool x : arr)
+        {
+            j.m_value.array->push_back(x);
+        }
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType, typename T,
+             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
+    {
+        j.m_type = value_t::array;
+        j.m_value = value_t::array;
+        j.m_value.array->resize(arr.size());
+        if (arr.size() > 0)
+        {
+            std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
+        }
+        j.assert_invariant();
+    }
+};
+
+template<>
+struct external_constructor<value_t::object>
+{
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
+    {
+        j.m_type = value_t::object;
+        j.m_value = obj;
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType>
+    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+    {
+        j.m_type = value_t::object;
+        j.m_value = std::move(obj);
+        j.assert_invariant();
+    }
+
+    template<typename BasicJsonType, typename CompatibleObjectType,
+             enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
+    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
+    {
+        using std::begin;
+        using std::end;
+
+        j.m_type = value_t::object;
+        j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
+        j.assert_invariant();
+    }
+};
+
+/////////////
+// to_json //
+/////////////
+
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+    external_constructor<value_t::boolean>::construct(j, b);
+}
+
+template<typename BasicJsonType, typename CompatibleString,
+         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
+void to_json(BasicJsonType& j, const CompatibleString& s)
+{
+    external_constructor<value_t::string>::construct(j, s);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+{
+    external_constructor<value_t::string>::construct(j, std::move(s));
+}
+
+template<typename BasicJsonType, typename FloatType,
+         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
+void to_json(BasicJsonType& j, FloatType val) noexcept
+{
+    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
+         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
+{
+    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberIntegerType,
+         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
+{
+    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
+}
+
+template<typename BasicJsonType, typename EnumType,
+         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void to_json(BasicJsonType& j, EnumType e) noexcept
+{
+    using underlying_type = typename std::underlying_type<EnumType>::type;
+    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const std::vector<bool>& e)
+{
+    external_constructor<value_t::array>::construct(j, e);
+}
+
+template <typename BasicJsonType, typename CompatibleArrayType,
+          enable_if_t<is_compatible_array_type<BasicJsonType,
+                      CompatibleArrayType>::value and
+                      not is_compatible_object_type<
+                          BasicJsonType, CompatibleArrayType>::value and
+                      not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
+                      not is_basic_json<CompatibleArrayType>::value,
+                      int> = 0>
+void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
+{
+    external_constructor<value_t::array>::construct(j, arr);
+}
+
+template<typename BasicJsonType, typename T,
+         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+void to_json(BasicJsonType& j, const std::valarray<T>& arr)
+{
+    external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+{
+    external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType, typename CompatibleObjectType,
+         enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
+void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
+{
+    external_constructor<value_t::object>::construct(j, obj);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+{
+    external_constructor<value_t::object>::construct(j, std::move(obj));
+}
+
+template <
+    typename BasicJsonType, typename T, std::size_t N,
+    enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
+                const T(&)[N]>::value,
+                int> = 0 >
+void to_json(BasicJsonType& j, const T(&arr)[N])
+{
+    external_constructor<value_t::array>::construct(j, arr);
+}
+
+template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
+void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
+{
+    j = { p.first, p.second };
+}
+
+// for https://github.com/nlohmann/json/pull/1134
+template < typename BasicJsonType, typename T,
+           enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
+void to_json(BasicJsonType& j, const T& b)
+{
+    j = { {b.key(), b.value()} };
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
+{
+    j = { std::get<Idx>(t)... };
+}
+
+template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
+void to_json(BasicJsonType& j, const T& t)
+{
+    to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
+}
+
+struct to_json_fn
+{
+    template<typename BasicJsonType, typename T>
+    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
+    -> decltype(to_json(j, std::forward<T>(val)), void())
+    {
+        return to_json(j, std::forward<T>(val));
+    }
+};
+}  // namespace detail
+
+/// namespace to hold default `to_json` function
+namespace
+{
+constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
+} // namespace
+} // namespace nlohmann
+
+
+namespace nlohmann
+{
+
+template<typename, typename>
+struct adl_serializer
+{
+    /*!
+    @brief convert a JSON value to any value type
+
+    This function is usually called by the `get()` function of the
+    @ref basic_json class (either explicit or via conversion operators).
+
+    @param[in] j        JSON value to read from
+    @param[in,out] val  value to write to
+    */
+    template<typename BasicJsonType, typename ValueType>
+    static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
+        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
+    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
+    {
+        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
+    }
+
+    /*!
+    @brief convert any value type to a JSON value
+
+    This function is usually called by the constructors of the @ref basic_json
+    class.
+
+    @param[in,out] j  JSON value to write to
+    @param[in] val    value to read from
+    */
+    template <typename BasicJsonType, typename ValueType>
+    static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
+        noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
+    -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
+    {
+        ::nlohmann::to_json(j, std::forward<ValueType>(val));
+    }
+};
+
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+
+#include <algorithm> // generate_n
+#include <array> // array
+#include <cassert> // assert
+#include <cmath> // ldexp
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstdio> // snprintf
+#include <cstring> // memcpy
+#include <iterator> // back_inserter
+#include <limits> // numeric_limits
+#include <string> // char_traits, string
+#include <utility> // make_pair, move
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+
+#include <array> // array
+#include <cassert> // assert
+#include <cstddef> // size_t
+#include <cstdio> //FILE *
+#include <cstring> // strlen
+#include <istream> // istream
+#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
+#include <memory> // shared_ptr, make_shared, addressof
+#include <numeric> // accumulate
+#include <string> // string, char_traits
+#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
+#include <utility> // pair, declval
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// the supported input formats
+enum class input_format_t { json, cbor, msgpack, ubjson, bson };
+
+////////////////////
+// input adapters //
+////////////////////
+
+/*!
+@brief abstract input adapter interface
+
+Produces a stream of std::char_traits<char>::int_type characters from a
+std::istream, a buffer, or some other input type. Accepts the return of
+exactly one non-EOF character for future input. The int_type characters
+returned consist of all valid char values as positive values (typically
+unsigned char), plus an EOF value outside that range, specified by the value
+of the function std::char_traits<char>::eof(). This value is typically -1, but
+could be any arbitrary value which is not a valid char value.
+*/
+struct input_adapter_protocol
+{
+    /// get a character [0,255] or std::char_traits<char>::eof().
+    virtual std::char_traits<char>::int_type get_character() = 0;
+    virtual ~input_adapter_protocol() = default;
+};
+
+/// a type to simplify interfaces
+using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
+
+/*!
+Input adapter for stdio file access. This adapter read only 1 byte and do not use any
+ buffer. This adapter is a very low level adapter.
+*/
+class file_input_adapter : public input_adapter_protocol
+{
+  public:
+    JSON_HEDLEY_NON_NULL(2)
+    explicit file_input_adapter(std::FILE* f)  noexcept
+        : m_file(f)
+    {}
+
+    // make class move-only
+    file_input_adapter(const file_input_adapter&) = delete;
+    file_input_adapter(file_input_adapter&&) = default;
+    file_input_adapter& operator=(const file_input_adapter&) = delete;
+    file_input_adapter& operator=(file_input_adapter&&) = default;
+    ~file_input_adapter() override = default;
+
+    std::char_traits<char>::int_type get_character() noexcept override
+    {
+        return std::fgetc(m_file);
+    }
+
+  private:
+    /// the file pointer to read from
+    std::FILE* m_file;
+};
+
+
+/*!
+Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
+beginning of input. Does not support changing the underlying std::streambuf
+in mid-input. Maintains underlying std::istream and std::streambuf to support
+subsequent use of standard std::istream operations to process any input
+characters following those used in parsing the JSON input.  Clears the
+std::istream flags; any input errors (e.g., EOF) will be detected by the first
+subsequent call for input from the std::istream.
+*/
+class input_stream_adapter : public input_adapter_protocol
+{
+  public:
+    ~input_stream_adapter() override
+    {
+        // clear stream flags; we use underlying streambuf I/O, do not
+        // maintain ifstream flags, except eof
+        is.clear(is.rdstate() & std::ios::eofbit);
+    }
+
+    explicit input_stream_adapter(std::istream& i)
+        : is(i), sb(*i.rdbuf())
+    {}
+
+    // delete because of pointer members
+    input_stream_adapter(const input_stream_adapter&) = delete;
+    input_stream_adapter& operator=(input_stream_adapter&) = delete;
+    input_stream_adapter(input_stream_adapter&&) = delete;
+    input_stream_adapter& operator=(input_stream_adapter&&) = delete;
+
+    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
+    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
+    // end up as the same value, eg. 0xFFFFFFFF.
+    std::char_traits<char>::int_type get_character() override
+    {
+        auto res = sb.sbumpc();
+        // set eof manually, as we don't use the istream interface.
+        if (res == EOF)
+        {
+            is.clear(is.rdstate() | std::ios::eofbit);
+        }
+        return res;
+    }
+
+  private:
+    /// the associated input stream
+    std::istream& is;
+    std::streambuf& sb;
+};
+
+/// input adapter for buffer input
+class input_buffer_adapter : public input_adapter_protocol
+{
+  public:
+    input_buffer_adapter(const char* b, const std::size_t l) noexcept
+        : cursor(b), limit(b == nullptr ? nullptr : (b + l))
+    {}
+
+    // delete because of pointer members
+    input_buffer_adapter(const input_buffer_adapter&) = delete;
+    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
+    input_buffer_adapter(input_buffer_adapter&&) = delete;
+    input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
+    ~input_buffer_adapter() override = default;
+
+    std::char_traits<char>::int_type get_character() noexcept override
+    {
+        if (JSON_HEDLEY_LIKELY(cursor < limit))
+        {
+            assert(cursor != nullptr and limit != nullptr);
+            return std::char_traits<char>::to_int_type(*(cursor++));
+        }
+
+        return std::char_traits<char>::eof();
+    }
+
+  private:
+    /// pointer to the current character
+    const char* cursor;
+    /// pointer past the last character
+    const char* const limit;
+};
+
+template<typename WideStringType, size_t T>
+struct wide_string_input_helper
+{
+    // UTF-32
+    static void fill_buffer(const WideStringType& str,
+                            size_t& current_wchar,
+                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+                            size_t& utf8_bytes_index,
+                            size_t& utf8_bytes_filled)
+    {
+        utf8_bytes_index = 0;
+
+        if (current_wchar == str.size())
+        {
+            utf8_bytes[0] = std::char_traits<char>::eof();
+            utf8_bytes_filled = 1;
+        }
+        else
+        {
+            // get the current character
+            const auto wc = static_cast<unsigned int>(str[current_wchar++]);
+
+            // UTF-32 to UTF-8 encoding
+            if (wc < 0x80)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+            else if (wc <= 0x7FF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
+                utf8_bytes_filled = 2;
+            }
+            else if (wc <= 0xFFFF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
+                utf8_bytes_filled = 3;
+            }
+            else if (wc <= 0x10FFFF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
+                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
+                utf8_bytes_filled = 4;
+            }
+            else
+            {
+                // unknown character
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+        }
+    }
+};
+
+template<typename WideStringType>
+struct wide_string_input_helper<WideStringType, 2>
+{
+    // UTF-16
+    static void fill_buffer(const WideStringType& str,
+                            size_t& current_wchar,
+                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+                            size_t& utf8_bytes_index,
+                            size_t& utf8_bytes_filled)
+    {
+        utf8_bytes_index = 0;
+
+        if (current_wchar == str.size())
+        {
+            utf8_bytes[0] = std::char_traits<char>::eof();
+            utf8_bytes_filled = 1;
+        }
+        else
+        {
+            // get the current character
+            const auto wc = static_cast<unsigned int>(str[current_wchar++]);
+
+            // UTF-16 to UTF-8 encoding
+            if (wc < 0x80)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                utf8_bytes_filled = 1;
+            }
+            else if (wc <= 0x7FF)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
+                utf8_bytes_filled = 2;
+            }
+            else if (0xD800 > wc or wc >= 0xE000)
+            {
+                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
+                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
+                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
+                utf8_bytes_filled = 3;
+            }
+            else
+            {
+                if (current_wchar < str.size())
+                {
+                    const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
+                    const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
+                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
+                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
+                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
+                    utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
+                    utf8_bytes_filled = 4;
+                }
+                else
+                {
+                    // unknown character
+                    ++current_wchar;
+                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+                    utf8_bytes_filled = 1;
+                }
+            }
+        }
+    }
+};
+
+template<typename WideStringType>
+class wide_string_input_adapter : public input_adapter_protocol
+{
+  public:
+    explicit wide_string_input_adapter(const WideStringType& w) noexcept
+        : str(w)
+    {}
+
+    std::char_traits<char>::int_type get_character() noexcept override
+    {
+        // check if buffer needs to be filled
+        if (utf8_bytes_index == utf8_bytes_filled)
+        {
+            fill_buffer<sizeof(typename WideStringType::value_type)>();
+
+            assert(utf8_bytes_filled > 0);
+            assert(utf8_bytes_index == 0);
+        }
+
+        // use buffer
+        assert(utf8_bytes_filled > 0);
+        assert(utf8_bytes_index < utf8_bytes_filled);
+        return utf8_bytes[utf8_bytes_index++];
+    }
+
+  private:
+    template<size_t T>
+    void fill_buffer()
+    {
+        wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
+    }
+
+    /// the wstring to process
+    const WideStringType& str;
+
+    /// index of the current wchar in str
+    std::size_t current_wchar = 0;
+
+    /// a buffer for UTF-8 bytes
+    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
+
+    /// index to the utf8_codes array for the next valid byte
+    std::size_t utf8_bytes_index = 0;
+    /// number of valid bytes in the utf8_codes array
+    std::size_t utf8_bytes_filled = 0;
+};
+
+class input_adapter
+{
+  public:
+    // native support
+    JSON_HEDLEY_NON_NULL(2)
+    input_adapter(std::FILE* file)
+        : ia(std::make_shared<file_input_adapter>(file)) {}
+    /// input adapter for input stream
+    input_adapter(std::istream& i)
+        : ia(std::make_shared<input_stream_adapter>(i)) {}
+
+    /// input adapter for input stream
+    input_adapter(std::istream&& i)
+        : ia(std::make_shared<input_stream_adapter>(i)) {}
+
+    input_adapter(const std::wstring& ws)
+        : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
+
+    input_adapter(const std::u16string& ws)
+        : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
+
+    input_adapter(const std::u32string& ws)
+        : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
+
+    /// input adapter for buffer
+    template<typename CharT,
+             typename std::enable_if<
+                 std::is_pointer<CharT>::value and
+                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
+                 int>::type = 0>
+    input_adapter(CharT b, std::size_t l)
+        : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
+
+    // derived support
+
+    /// input adapter for string literal
+    template<typename CharT,
+             typename std::enable_if<
+                 std::is_pointer<CharT>::value and
+                 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+                 sizeof(typename std::remove_pointer<CharT>::type) == 1,
+                 int>::type = 0>
+    input_adapter(CharT b)
+        : input_adapter(reinterpret_cast<const char*>(b),
+                        std::strlen(reinterpret_cast<const char*>(b))) {}
+
+    /// input adapter for iterator range with contiguous storage
+    template<class IteratorType,
+             typename std::enable_if<
+                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
+                 int>::type = 0>
+    input_adapter(IteratorType first, IteratorType last)
+    {
+#ifndef NDEBUG
+        // assertion to check that the iterator range is indeed contiguous,
+        // see http://stackoverflow.com/a/35008842/266378 for more discussion
+        const auto is_contiguous = std::accumulate(
+                                       first, last, std::pair<bool, int>(true, 0),
+                                       [&first](std::pair<bool, int> res, decltype(*first) val)
+        {
+            res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
+            return res;
+        }).first;
+        assert(is_contiguous);
+#endif
+
+        // assertion to check that each element is 1 byte long
+        static_assert(
+            sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
+            "each element in the iterator range must have the size of 1 byte");
+
+        const auto len = static_cast<size_t>(std::distance(first, last));
+        if (JSON_HEDLEY_LIKELY(len > 0))
+        {
+            // there is at least one element: use the address of first
+            ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
+        }
+        else
+        {
+            // the address of first cannot be used: use nullptr
+            ia = std::make_shared<input_buffer_adapter>(nullptr, len);
+        }
+    }
+
+    /// input adapter for array
+    template<class T, std::size_t N>
+    input_adapter(T (&array)[N])
+        : input_adapter(std::begin(array), std::end(array)) {}
+
+    /// input adapter for contiguous container
+    template<class ContiguousContainer, typename
+             std::enable_if<not std::is_pointer<ContiguousContainer>::value and
+                            std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
+                            int>::type = 0>
+    input_adapter(const ContiguousContainer& c)
+        : input_adapter(std::begin(c), std::end(c)) {}
+
+    operator input_adapter_t()
+    {
+        return ia;
+    }
+
+  private:
+    /// the actual adapter
+    input_adapter_t ia = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+
+#include <cassert> // assert
+#include <cstddef>
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+
+/*!
+@brief SAX interface
+
+This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
+Each function is called in different situations while the input is parsed. The
+boolean return value informs the parser whether to continue processing the
+input.
+*/
+template<typename BasicJsonType>
+struct json_sax
+{
+    /// type for (signed) integers
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    /// type for unsigned integers
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    /// type for floating-point numbers
+    using number_float_t = typename BasicJsonType::number_float_t;
+    /// type for strings
+    using string_t = typename BasicJsonType::string_t;
+
+    /*!
+    @brief a null value was read
+    @return whether parsing should proceed
+    */
+    virtual bool null() = 0;
+
+    /*!
+    @brief a boolean value was read
+    @param[in] val  boolean value
+    @return whether parsing should proceed
+    */
+    virtual bool boolean(bool val) = 0;
+
+    /*!
+    @brief an integer number was read
+    @param[in] val  integer value
+    @return whether parsing should proceed
+    */
+    virtual bool number_integer(number_integer_t val) = 0;
+
+    /*!
+    @brief an unsigned integer number was read
+    @param[in] val  unsigned integer value
+    @return whether parsing should proceed
+    */
+    virtual bool number_unsigned(number_unsigned_t val) = 0;
+
+    /*!
+    @brief an floating-point number was read
+    @param[in] val  floating-point value
+    @param[in] s    raw token value
+    @return whether parsing should proceed
+    */
+    virtual bool number_float(number_float_t val, const string_t& s) = 0;
+
+    /*!
+    @brief a string was read
+    @param[in] val  string value
+    @return whether parsing should proceed
+    @note It is safe to move the passed string.
+    */
+    virtual bool string(string_t& val) = 0;
+
+    /*!
+    @brief the beginning of an object was read
+    @param[in] elements  number of object elements or -1 if unknown
+    @return whether parsing should proceed
+    @note binary formats may report the number of elements
+    */
+    virtual bool start_object(std::size_t elements) = 0;
+
+    /*!
+    @brief an object key was read
+    @param[in] val  object key
+    @return whether parsing should proceed
+    @note It is safe to move the passed string.
+    */
+    virtual bool key(string_t& val) = 0;
+
+    /*!
+    @brief the end of an object was read
+    @return whether parsing should proceed
+    */
+    virtual bool end_object() = 0;
+
+    /*!
+    @brief the beginning of an array was read
+    @param[in] elements  number of array elements or -1 if unknown
+    @return whether parsing should proceed
+    @note binary formats may report the number of elements
+    */
+    virtual bool start_array(std::size_t elements) = 0;
+
+    /*!
+    @brief the end of an array was read
+    @return whether parsing should proceed
+    */
+    virtual bool end_array() = 0;
+
+    /*!
+    @brief a parse error occurred
+    @param[in] position    the position in the input where the error occurs
+    @param[in] last_token  the last read token
+    @param[in] ex          an exception object describing the error
+    @return whether parsing should proceed (must return false)
+    */
+    virtual bool parse_error(std::size_t position,
+                             const std::string& last_token,
+                             const detail::exception& ex) = 0;
+
+    virtual ~json_sax() = default;
+};
+
+
+namespace detail
+{
+/*!
+@brief SAX implementation to create a JSON value from SAX events
+
+This class implements the @ref json_sax interface and processes the SAX events
+to create a JSON value which makes it basically a DOM parser. The structure or
+hierarchy of the JSON value is managed by the stack `ref_stack` which contains
+a pointer to the respective array or object for each recursion depth.
+
+After successful parsing, the value that is passed by reference to the
+constructor contains the parsed value.
+
+@tparam BasicJsonType  the JSON type
+*/
+template<typename BasicJsonType>
+class json_sax_dom_parser
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+
+    /*!
+    @param[in, out] r  reference to a JSON value that is manipulated while
+                       parsing
+    @param[in] allow_exceptions_  whether parse errors yield exceptions
+    */
+    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
+        : root(r), allow_exceptions(allow_exceptions_)
+    {}
+
+    // make class move-only
+    json_sax_dom_parser(const json_sax_dom_parser&) = delete;
+    json_sax_dom_parser(json_sax_dom_parser&&) = default;
+    json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
+    json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
+    ~json_sax_dom_parser() = default;
+
+    bool null()
+    {
+        handle_value(nullptr);
+        return true;
+    }
+
+    bool boolean(bool val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_integer(number_integer_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_float(number_float_t val, const string_t& /*unused*/)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool string(string_t& val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool start_object(std::size_t len)
+    {
+        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
+
+        if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408,
+                                            "excessive object size: " + std::to_string(len)));
+        }
+
+        return true;
+    }
+
+    bool key(string_t& val)
+    {
+        // add null at given key and store the reference for later
+        object_element = &(ref_stack.back()->m_value.object->operator[](val));
+        return true;
+    }
+
+    bool end_object()
+    {
+        ref_stack.pop_back();
+        return true;
+    }
+
+    bool start_array(std::size_t len)
+    {
+        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
+
+        if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408,
+                                            "excessive array size: " + std::to_string(len)));
+        }
+
+        return true;
+    }
+
+    bool end_array()
+    {
+        ref_stack.pop_back();
+        return true;
+    }
+
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+                     const detail::exception& ex)
+    {
+        errored = true;
+        if (allow_exceptions)
+        {
+            // determine the proper exception type from the id
+            switch ((ex.id / 100) % 100)
+            {
+                case 1:
+                    JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
+                case 4:
+                    JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
+                // LCOV_EXCL_START
+                case 2:
+                    JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
+                case 3:
+                    JSON_THROW(*static_cast<const detail::type_error*>(&ex));
+                case 5:
+                    JSON_THROW(*static_cast<const detail::other_error*>(&ex));
+                default:
+                    assert(false);
+                    // LCOV_EXCL_STOP
+            }
+        }
+        return false;
+    }
+
+    constexpr bool is_errored() const
+    {
+        return errored;
+    }
+
+  private:
+    /*!
+    @invariant If the ref stack is empty, then the passed value will be the new
+               root.
+    @invariant If the ref stack contains a value, then it is an array or an
+               object to which we can add elements
+    */
+    template<typename Value>
+    JSON_HEDLEY_RETURNS_NON_NULL
+    BasicJsonType* handle_value(Value&& v)
+    {
+        if (ref_stack.empty())
+        {
+            root = BasicJsonType(std::forward<Value>(v));
+            return &root;
+        }
+
+        assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
+
+        if (ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
+            return &(ref_stack.back()->m_value.array->back());
+        }
+
+        assert(ref_stack.back()->is_object());
+        assert(object_element);
+        *object_element = BasicJsonType(std::forward<Value>(v));
+        return object_element;
+    }
+
+    /// the parsed JSON value
+    BasicJsonType& root;
+    /// stack to model hierarchy of values
+    std::vector<BasicJsonType*> ref_stack {};
+    /// helper to hold the reference for the next object element
+    BasicJsonType* object_element = nullptr;
+    /// whether a syntax error occurred
+    bool errored = false;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+};
+
+template<typename BasicJsonType>
+class json_sax_dom_callback_parser
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using parser_callback_t = typename BasicJsonType::parser_callback_t;
+    using parse_event_t = typename BasicJsonType::parse_event_t;
+
+    json_sax_dom_callback_parser(BasicJsonType& r,
+                                 const parser_callback_t cb,
+                                 const bool allow_exceptions_ = true)
+        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
+    {
+        keep_stack.push_back(true);
+    }
+
+    // make class move-only
+    json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
+    json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
+    json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
+    json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
+    ~json_sax_dom_callback_parser() = default;
+
+    bool null()
+    {
+        handle_value(nullptr);
+        return true;
+    }
+
+    bool boolean(bool val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_integer(number_integer_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool number_float(number_float_t val, const string_t& /*unused*/)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool string(string_t& val)
+    {
+        handle_value(val);
+        return true;
+    }
+
+    bool start_object(std::size_t len)
+    {
+        // check callback for object start
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
+        keep_stack.push_back(keep);
+
+        auto val = handle_value(BasicJsonType::value_t::object, true);
+        ref_stack.push_back(val.second);
+
+        // check object limit
+        if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
+        }
+
+        return true;
+    }
+
+    bool key(string_t& val)
+    {
+        BasicJsonType k = BasicJsonType(val);
+
+        // check callback for key
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
+        key_keep_stack.push_back(keep);
+
+        // add discarded value at given key and store the reference for later
+        if (keep and ref_stack.back())
+        {
+            object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
+        }
+
+        return true;
+    }
+
+    bool end_object()
+    {
+        if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
+        {
+            // discard object
+            *ref_stack.back() = discarded;
+        }
+
+        assert(not ref_stack.empty());
+        assert(not keep_stack.empty());
+        ref_stack.pop_back();
+        keep_stack.pop_back();
+
+        if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
+        {
+            // remove discarded value
+            for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
+            {
+                if (it->is_discarded())
+                {
+                    ref_stack.back()->erase(it);
+                    break;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool start_array(std::size_t len)
+    {
+        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
+        keep_stack.push_back(keep);
+
+        auto val = handle_value(BasicJsonType::value_t::array, true);
+        ref_stack.push_back(val.second);
+
+        // check array limit
+        if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+        {
+            JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
+        }
+
+        return true;
+    }
+
+    bool end_array()
+    {
+        bool keep = true;
+
+        if (ref_stack.back())
+        {
+            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
+            if (not keep)
+            {
+                // discard array
+                *ref_stack.back() = discarded;
+            }
+        }
+
+        assert(not ref_stack.empty());
+        assert(not keep_stack.empty());
+        ref_stack.pop_back();
+        keep_stack.pop_back();
+
+        // remove discarded value
+        if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->pop_back();
+        }
+
+        return true;
+    }
+
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+                     const detail::exception& ex)
+    {
+        errored = true;
+        if (allow_exceptions)
+        {
+            // determine the proper exception type from the id
+            switch ((ex.id / 100) % 100)
+            {
+                case 1:
+                    JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
+                case 4:
+                    JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
+                // LCOV_EXCL_START
+                case 2:
+                    JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
+                case 3:
+                    JSON_THROW(*static_cast<const detail::type_error*>(&ex));
+                case 5:
+                    JSON_THROW(*static_cast<const detail::other_error*>(&ex));
+                default:
+                    assert(false);
+                    // LCOV_EXCL_STOP
+            }
+        }
+        return false;
+    }
+
+    constexpr bool is_errored() const
+    {
+        return errored;
+    }
+
+  private:
+    /*!
+    @param[in] v  value to add to the JSON value we build during parsing
+    @param[in] skip_callback  whether we should skip calling the callback
+               function; this is required after start_array() and
+               start_object() SAX events, because otherwise we would call the
+               callback function with an empty array or object, respectively.
+
+    @invariant If the ref stack is empty, then the passed value will be the new
+               root.
+    @invariant If the ref stack contains a value, then it is an array or an
+               object to which we can add elements
+
+    @return pair of boolean (whether value should be kept) and pointer (to the
+            passed value in the ref_stack hierarchy; nullptr if not kept)
+    */
+    template<typename Value>
+    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
+    {
+        assert(not keep_stack.empty());
+
+        // do not handle this value if we know it would be added to a discarded
+        // container
+        if (not keep_stack.back())
+        {
+            return {false, nullptr};
+        }
+
+        // create value
+        auto value = BasicJsonType(std::forward<Value>(v));
+
+        // check callback
+        const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
+
+        // do not handle this value if we just learnt it shall be discarded
+        if (not keep)
+        {
+            return {false, nullptr};
+        }
+
+        if (ref_stack.empty())
+        {
+            root = std::move(value);
+            return {true, &root};
+        }
+
+        // skip this value if we already decided to skip the parent
+        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
+        if (not ref_stack.back())
+        {
+            return {false, nullptr};
+        }
+
+        // we now only expect arrays and objects
+        assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
+
+        // array
+        if (ref_stack.back()->is_array())
+        {
+            ref_stack.back()->m_value.array->push_back(std::move(value));
+            return {true, &(ref_stack.back()->m_value.array->back())};
+        }
+
+        // object
+        assert(ref_stack.back()->is_object());
+        // check if we should store an element for the current key
+        assert(not key_keep_stack.empty());
+        const bool store_element = key_keep_stack.back();
+        key_keep_stack.pop_back();
+
+        if (not store_element)
+        {
+            return {false, nullptr};
+        }
+
+        assert(object_element);
+        *object_element = std::move(value);
+        return {true, object_element};
+    }
+
+    /// the parsed JSON value
+    BasicJsonType& root;
+    /// stack to model hierarchy of values
+    std::vector<BasicJsonType*> ref_stack {};
+    /// stack to manage which values to keep
+    std::vector<bool> keep_stack {};
+    /// stack to manage which object keys to keep
+    std::vector<bool> key_keep_stack {};
+    /// helper to hold the reference for the next object element
+    BasicJsonType* object_element = nullptr;
+    /// whether a syntax error occurred
+    bool errored = false;
+    /// callback function
+    const parser_callback_t callback = nullptr;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+    /// a discarded value for the callback
+    BasicJsonType discarded = BasicJsonType::value_t::discarded;
+};
+
+template<typename BasicJsonType>
+class json_sax_acceptor
+{
+  public:
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+
+    bool null()
+    {
+        return true;
+    }
+
+    bool boolean(bool /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_integer(number_integer_t /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_unsigned(number_unsigned_t /*unused*/)
+    {
+        return true;
+    }
+
+    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool string(string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool start_object(std::size_t  /*unused*/ = std::size_t(-1))
+    {
+        return true;
+    }
+
+    bool key(string_t& /*unused*/)
+    {
+        return true;
+    }
+
+    bool end_object()
+    {
+        return true;
+    }
+
+    bool start_array(std::size_t  /*unused*/ = std::size_t(-1))
+    {
+        return true;
+    }
+
+    bool end_array()
+    {
+        return true;
+    }
+
+    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
+    {
+        return false;
+    }
+};
+}  // namespace detail
+
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+
+#include <cstdint> // size_t
+#include <utility> // declval
+#include <string> // string
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename T>
+using null_function_t = decltype(std::declval<T&>().null());
+
+template <typename T>
+using boolean_function_t =
+    decltype(std::declval<T&>().boolean(std::declval<bool>()));
+
+template <typename T, typename Integer>
+using number_integer_function_t =
+    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
+
+template <typename T, typename Unsigned>
+using number_unsigned_function_t =
+    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
+
+template <typename T, typename Float, typename String>
+using number_float_function_t = decltype(std::declval<T&>().number_float(
+                                    std::declval<Float>(), std::declval<const String&>()));
+
+template <typename T, typename String>
+using string_function_t =
+    decltype(std::declval<T&>().string(std::declval<String&>()));
+
+template <typename T>
+using start_object_function_t =
+    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
+
+template <typename T, typename String>
+using key_function_t =
+    decltype(std::declval<T&>().key(std::declval<String&>()));
+
+template <typename T>
+using end_object_function_t = decltype(std::declval<T&>().end_object());
+
+template <typename T>
+using start_array_function_t =
+    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
+
+template <typename T>
+using end_array_function_t = decltype(std::declval<T&>().end_array());
+
+template <typename T, typename Exception>
+using parse_error_function_t = decltype(std::declval<T&>().parse_error(
+        std::declval<std::size_t>(), std::declval<const std::string&>(),
+        std::declval<const Exception&>()));
+
+template <typename SAX, typename BasicJsonType>
+struct is_sax
+{
+  private:
+    static_assert(is_basic_json<BasicJsonType>::value,
+                  "BasicJsonType must be of type basic_json<...>");
+
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using exception_t = typename BasicJsonType::exception;
+
+  public:
+    static constexpr bool value =
+        is_detected_exact<bool, null_function_t, SAX>::value &&
+        is_detected_exact<bool, boolean_function_t, SAX>::value &&
+        is_detected_exact<bool, number_integer_function_t, SAX,
+        number_integer_t>::value &&
+        is_detected_exact<bool, number_unsigned_function_t, SAX,
+        number_unsigned_t>::value &&
+        is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
+        string_t>::value &&
+        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
+        is_detected_exact<bool, start_object_function_t, SAX>::value &&
+        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
+        is_detected_exact<bool, end_object_function_t, SAX>::value &&
+        is_detected_exact<bool, start_array_function_t, SAX>::value &&
+        is_detected_exact<bool, end_array_function_t, SAX>::value &&
+        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
+};
+
+template <typename SAX, typename BasicJsonType>
+struct is_sax_static_asserts
+{
+  private:
+    static_assert(is_basic_json<BasicJsonType>::value,
+                  "BasicJsonType must be of type basic_json<...>");
+
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using exception_t = typename BasicJsonType::exception;
+
+  public:
+    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
+                  "Missing/invalid function: bool null()");
+    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+                  "Missing/invalid function: bool boolean(bool)");
+    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+                  "Missing/invalid function: bool boolean(bool)");
+    static_assert(
+        is_detected_exact<bool, number_integer_function_t, SAX,
+        number_integer_t>::value,
+        "Missing/invalid function: bool number_integer(number_integer_t)");
+    static_assert(
+        is_detected_exact<bool, number_unsigned_function_t, SAX,
+        number_unsigned_t>::value,
+        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
+    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
+                  number_float_t, string_t>::value,
+                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
+    static_assert(
+        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
+        "Missing/invalid function: bool string(string_t&)");
+    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
+                  "Missing/invalid function: bool start_object(std::size_t)");
+    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
+                  "Missing/invalid function: bool key(string_t&)");
+    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
+                  "Missing/invalid function: bool end_object()");
+    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
+                  "Missing/invalid function: bool start_array(std::size_t)");
+    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
+                  "Missing/invalid function: bool end_array()");
+    static_assert(
+        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
+        "Missing/invalid function: bool parse_error(std::size_t, const "
+        "std::string&, const exception&)");
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// binary reader //
+///////////////////
+
+/*!
+@brief deserialization of CBOR, MessagePack, and UBJSON values
+*/
+template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
+class binary_reader
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using json_sax_t = SAX;
+
+  public:
+    /*!
+    @brief create a binary reader
+
+    @param[in] adapter  input adapter to read from
+    */
+    explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
+    {
+        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+        assert(ia);
+    }
+
+    // make class move-only
+    binary_reader(const binary_reader&) = delete;
+    binary_reader(binary_reader&&) = default;
+    binary_reader& operator=(const binary_reader&) = delete;
+    binary_reader& operator=(binary_reader&&) = default;
+    ~binary_reader() = default;
+
+    /*!
+    @param[in] format  the binary format to parse
+    @param[in] sax_    a SAX event processor
+    @param[in] strict  whether to expect the input to be consumed completed
+
+    @return
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    bool sax_parse(const input_format_t format,
+                   json_sax_t* sax_,
+                   const bool strict = true)
+    {
+        sax = sax_;
+        bool result = false;
+
+        switch (format)
+        {
+            case input_format_t::bson:
+                result = parse_bson_internal();
+                break;
+
+            case input_format_t::cbor:
+                result = parse_cbor_internal();
+                break;
+
+            case input_format_t::msgpack:
+                result = parse_msgpack_internal();
+                break;
+
+            case input_format_t::ubjson:
+                result = parse_ubjson_internal();
+                break;
+
+            default:            // LCOV_EXCL_LINE
+                assert(false);  // LCOV_EXCL_LINE
+        }
+
+        // strict mode: next byte must be EOF
+        if (result and strict)
+        {
+            if (format == input_format_t::ubjson)
+            {
+                get_ignore_noop();
+            }
+            else
+            {
+                get();
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char>::eof()))
+            {
+                return sax->parse_error(chars_read, get_token_string(),
+                                        parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
+            }
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief determine system byte order
+
+    @return true if and only if system's byte order is little endian
+
+    @note from http://stackoverflow.com/a/1001328/266378
+    */
+    static constexpr bool little_endianess(int num = 1) noexcept
+    {
+        return *reinterpret_cast<char*>(&num) == 1;
+    }
+
+  private:
+    //////////
+    // BSON //
+    //////////
+
+    /*!
+    @brief Reads in a BSON-object and passes it to the SAX-parser.
+    @return whether a valid BSON-value was passed to the SAX parser
+    */
+    bool parse_bson_internal()
+    {
+        std::int32_t document_size;
+        get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+        if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
+        {
+            return false;
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
+        {
+            return false;
+        }
+
+        return sax->end_object();
+    }
+
+    /*!
+    @brief Parses a C-style string from the BSON input.
+    @param[in, out] result  A reference to the string variable where the read
+                            string is to be stored.
+    @return `true` if the \x00-byte indicating the end of the string was
+             encountered before the EOF; false` indicates an unexpected EOF.
+    */
+    bool get_bson_cstr(string_t& result)
+    {
+        auto out = std::back_inserter(result);
+        while (true)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
+            {
+                return false;
+            }
+            if (current == 0x00)
+            {
+                return true;
+            }
+            *out++ = static_cast<char>(current);
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief Parses a zero-terminated string of length @a len from the BSON
+           input.
+    @param[in] len  The length (including the zero-byte at the end) of the
+                    string to be read.
+    @param[in, out] result  A reference to the string variable where the read
+                            string is to be stored.
+    @tparam NumberType The type of the length @a len
+    @pre len >= 1
+    @return `true` if the string was successfully parsed
+    */
+    template<typename NumberType>
+    bool get_bson_string(const NumberType len, string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(len < 1))
+        {
+            auto last_token = get_token_string();
+            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
+        }
+
+        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
+    }
+
+    /*!
+    @brief Read a BSON document element of the given @a element_type.
+    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
+    @param[in] element_type_parse_position The position in the input stream,
+               where the `element_type` was read.
+    @warning Not all BSON element types are supported yet. An unsupported
+             @a element_type will give rise to a parse_error.114:
+             Unsupported BSON record type 0x...
+    @return whether a valid BSON-object/array was passed to the SAX parser
+    */
+    bool parse_bson_element_internal(const int element_type,
+                                     const std::size_t element_type_parse_position)
+    {
+        switch (element_type)
+        {
+            case 0x01: // double
+            {
+                double number;
+                return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0x02: // string
+            {
+                std::int32_t len;
+                string_t value;
+                return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
+            }
+
+            case 0x03: // object
+            {
+                return parse_bson_internal();
+            }
+
+            case 0x04: // array
+            {
+                return parse_bson_array();
+            }
+
+            case 0x08: // boolean
+            {
+                return sax->boolean(get() != 0);
+            }
+
+            case 0x0A: // null
+            {
+                return sax->null();
+            }
+
+            case 0x10: // int32
+            {
+                std::int32_t value;
+                return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
+            }
+
+            case 0x12: // int64
+            {
+                std::int64_t value;
+                return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
+            }
+
+            default: // anything else not supported (yet)
+            {
+                std::array<char, 3> cr{{}};
+                (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
+                return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
+            }
+        }
+    }
+
+    /*!
+    @brief Read a BSON element list (as specified in the BSON-spec)
+
+    The same binary layout is used for objects and arrays, hence it must be
+    indicated with the argument @a is_array which one is expected
+    (true --> array, false --> object).
+
+    @param[in] is_array Determines if the element list being read is to be
+                        treated as an object (@a is_array == false), or as an
+                        array (@a is_array == true).
+    @return whether a valid BSON-object/array was passed to the SAX parser
+    */
+    bool parse_bson_element_list(const bool is_array)
+    {
+        string_t key;
+        while (int element_type = get())
+        {
+            if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
+            {
+                return false;
+            }
+
+            const std::size_t element_type_parse_position = chars_read;
+            if (JSON_HEDLEY_UNLIKELY(not get_bson_cstr(key)))
+            {
+                return false;
+            }
+
+            if (not is_array and not sax->key(key))
+            {
+                return false;
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
+            {
+                return false;
+            }
+
+            // get_bson_cstr only appends
+            key.clear();
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief Reads an array from the BSON input and passes it to the SAX-parser.
+    @return whether a valid BSON-array was passed to the SAX parser
+    */
+    bool parse_bson_array()
+    {
+        std::int32_t document_size;
+        get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+        if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
+        {
+            return false;
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
+        {
+            return false;
+        }
+
+        return sax->end_array();
+    }
+
+    //////////
+    // CBOR //
+    //////////
+
+    /*!
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether a valid CBOR value was passed to the SAX parser
+    */
+    bool parse_cbor_internal(const bool get_char = true)
+    {
+        switch (get_char ? get() : current)
+        {
+            // EOF
+            case std::char_traits<char>::eof():
+                return unexpect_eof(input_format_t::cbor, "value");
+
+            // Integer 0x00..0x17 (0..23)
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0A:
+            case 0x0B:
+            case 0x0C:
+            case 0x0D:
+            case 0x0E:
+            case 0x0F:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+            case 0x18: // Unsigned integer (one-byte uint8_t follows)
+            {
+                std::uint8_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
+            }
+
+            case 0x19: // Unsigned integer (two-byte uint16_t follows)
+            {
+                std::uint16_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
+            }
+
+            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
+            {
+                std::uint32_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
+            }
+
+            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
+            {
+                std::uint64_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
+            }
+
+            // Negative integer -1-0x00..-1-0x17 (-1..-24)
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2A:
+            case 0x2B:
+            case 0x2C:
+            case 0x2D:
+            case 0x2E:
+            case 0x2F:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+                return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
+
+            case 0x38: // Negative integer (one-byte uint8_t follows)
+            {
+                std::uint8_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+            {
+                std::uint16_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
+            {
+                std::uint32_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
+            }
+
+            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
+            {
+                std::uint64_t number;
+                return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
+                        - static_cast<number_integer_t>(number));
+            }
+
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+            case 0x7F: // UTF-8 string (indefinite length)
+            {
+                string_t s;
+                return get_cbor_string(s) and sax->string(s);
+            }
+
+            // array (0x00..0x17 data items follow)
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8A:
+            case 0x8B:
+            case 0x8C:
+            case 0x8D:
+            case 0x8E:
+            case 0x8F:
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+                return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
+
+            case 0x98: // array (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
+            }
+
+            case 0x99: // array (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
+            }
+
+            case 0x9A: // array (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
+            }
+
+            case 0x9B: // array (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
+            }
+
+            case 0x9F: // array (indefinite length)
+                return get_cbor_array(std::size_t(-1));
+
+            // map (0x00..0x17 pairs of data items follow)
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+                return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
+
+            case 0xB8: // map (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xB9: // map (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xBA: // map (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xBB: // map (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len;
+                return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xBF: // map (indefinite length)
+                return get_cbor_object(std::size_t(-1));
+
+            case 0xF4: // false
+                return sax->boolean(false);
+
+            case 0xF5: // true
+                return sax->boolean(true);
+
+            case 0xF6: // null
+                return sax->null();
+
+            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
+            {
+                const int byte1_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
+                {
+                    return false;
+                }
+                const int byte2_raw = get();
+                if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
+                {
+                    return false;
+                }
+
+                const auto byte1 = static_cast<unsigned char>(byte1_raw);
+                const auto byte2 = static_cast<unsigned char>(byte2_raw);
+
+                // code from RFC 7049, Appendix D, Figure 3:
+                // As half-precision floating-point numbers were only added
+                // to IEEE 754 in 2008, today's programming platforms often
+                // still only have limited support for them. It is very
+                // easy to include at least decoding support for them even
+                // without such support. An example of a small decoder for
+                // half-precision floating-point numbers in the C language
+                // is shown in Fig. 3.
+                const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
+                const double val = [&half]
+                {
+                    const int exp = (half >> 10u) & 0x1Fu;
+                    const unsigned int mant = half & 0x3FFu;
+                    assert(0 <= exp and exp <= 32);
+                    assert(mant <= 1024);
+                    switch (exp)
+                    {
+                        case 0:
+                            return std::ldexp(mant, -24);
+                        case 31:
+                            return (mant == 0)
+                            ? std::numeric_limits<double>::infinity()
+                            : std::numeric_limits<double>::quiet_NaN();
+                        default:
+                            return std::ldexp(mant + 1024, exp - 25);
+                    }
+                }();
+                return sax->number_float((half & 0x8000u) != 0
+                                         ? static_cast<number_float_t>(-val)
+                                         : static_cast<number_float_t>(val), "");
+            }
+
+            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
+            {
+                float number;
+                return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
+            {
+                double number;
+                return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            default: // anything else (0xFF is handled inside the other types)
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a CBOR string
+
+    This function first reads starting bytes to determine the expected
+    string length and then copies this number of bytes into a string.
+    Additionally, CBOR's strings with indefinite lengths are supported.
+
+    @param[out] result  created string
+
+    @return whether string creation completed
+    */
+    bool get_cbor_string(string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // UTF-8 string (0x00..0x17 bytes follow)
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            {
+                return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+            {
+                std::uint8_t len;
+                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+            {
+                std::uint16_t len;
+                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+            {
+                std::uint32_t len;
+                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+            {
+                std::uint64_t len;
+                return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
+            }
+
+            case 0x7F: // UTF-8 string (indefinite length)
+            {
+                while (get() != 0xFF)
+                {
+                    string_t chunk;
+                    if (not get_cbor_string(chunk))
+                    {
+                        return false;
+                    }
+                    result.append(chunk);
+                }
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
+            }
+        }
+    }
+
+    /*!
+    @param[in] len  the length of the array or std::size_t(-1) for an
+                    array of indefinite size
+    @return whether array creation completed
+    */
+    bool get_cbor_array(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len)))
+        {
+            return false;
+        }
+
+        if (len != std::size_t(-1))
+        {
+            for (std::size_t i = 0; i < len; ++i)
+            {
+                if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
+                {
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            while (get() != 0xFF)
+            {
+                if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal(false)))
+                {
+                    return false;
+                }
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @param[in] len  the length of the object or std::size_t(-1) for an
+                    object of indefinite size
+    @return whether object creation completed
+    */
+    bool get_cbor_object(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len)))
+        {
+            return false;
+        }
+
+        string_t key;
+        if (len != std::size_t(-1))
+        {
+            for (std::size_t i = 0; i < len; ++i)
+            {
+                get();
+                if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
+                {
+                    return false;
+                }
+
+                if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
+                {
+                    return false;
+                }
+                key.clear();
+            }
+        }
+        else
+        {
+            while (get() != 0xFF)
+            {
+                if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
+                {
+                    return false;
+                }
+
+                if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
+                {
+                    return false;
+                }
+                key.clear();
+            }
+        }
+
+        return sax->end_object();
+    }
+
+    /////////////
+    // MsgPack //
+    /////////////
+
+    /*!
+    @return whether a valid MessagePack value was passed to the SAX parser
+    */
+    bool parse_msgpack_internal()
+    {
+        switch (get())
+        {
+            // EOF
+            case std::char_traits<char>::eof():
+                return unexpect_eof(input_format_t::msgpack, "value");
+
+            // positive fixint
+            case 0x00:
+            case 0x01:
+            case 0x02:
+            case 0x03:
+            case 0x04:
+            case 0x05:
+            case 0x06:
+            case 0x07:
+            case 0x08:
+            case 0x09:
+            case 0x0A:
+            case 0x0B:
+            case 0x0C:
+            case 0x0D:
+            case 0x0E:
+            case 0x0F:
+            case 0x10:
+            case 0x11:
+            case 0x12:
+            case 0x13:
+            case 0x14:
+            case 0x15:
+            case 0x16:
+            case 0x17:
+            case 0x18:
+            case 0x19:
+            case 0x1A:
+            case 0x1B:
+            case 0x1C:
+            case 0x1D:
+            case 0x1E:
+            case 0x1F:
+            case 0x20:
+            case 0x21:
+            case 0x22:
+            case 0x23:
+            case 0x24:
+            case 0x25:
+            case 0x26:
+            case 0x27:
+            case 0x28:
+            case 0x29:
+            case 0x2A:
+            case 0x2B:
+            case 0x2C:
+            case 0x2D:
+            case 0x2E:
+            case 0x2F:
+            case 0x30:
+            case 0x31:
+            case 0x32:
+            case 0x33:
+            case 0x34:
+            case 0x35:
+            case 0x36:
+            case 0x37:
+            case 0x38:
+            case 0x39:
+            case 0x3A:
+            case 0x3B:
+            case 0x3C:
+            case 0x3D:
+            case 0x3E:
+            case 0x3F:
+            case 0x40:
+            case 0x41:
+            case 0x42:
+            case 0x43:
+            case 0x44:
+            case 0x45:
+            case 0x46:
+            case 0x47:
+            case 0x48:
+            case 0x49:
+            case 0x4A:
+            case 0x4B:
+            case 0x4C:
+            case 0x4D:
+            case 0x4E:
+            case 0x4F:
+            case 0x50:
+            case 0x51:
+            case 0x52:
+            case 0x53:
+            case 0x54:
+            case 0x55:
+            case 0x56:
+            case 0x57:
+            case 0x58:
+            case 0x59:
+            case 0x5A:
+            case 0x5B:
+            case 0x5C:
+            case 0x5D:
+            case 0x5E:
+            case 0x5F:
+            case 0x60:
+            case 0x61:
+            case 0x62:
+            case 0x63:
+            case 0x64:
+            case 0x65:
+            case 0x66:
+            case 0x67:
+            case 0x68:
+            case 0x69:
+            case 0x6A:
+            case 0x6B:
+            case 0x6C:
+            case 0x6D:
+            case 0x6E:
+            case 0x6F:
+            case 0x70:
+            case 0x71:
+            case 0x72:
+            case 0x73:
+            case 0x74:
+            case 0x75:
+            case 0x76:
+            case 0x77:
+            case 0x78:
+            case 0x79:
+            case 0x7A:
+            case 0x7B:
+            case 0x7C:
+            case 0x7D:
+            case 0x7E:
+            case 0x7F:
+                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+            // fixmap
+            case 0x80:
+            case 0x81:
+            case 0x82:
+            case 0x83:
+            case 0x84:
+            case 0x85:
+            case 0x86:
+            case 0x87:
+            case 0x88:
+            case 0x89:
+            case 0x8A:
+            case 0x8B:
+            case 0x8C:
+            case 0x8D:
+            case 0x8E:
+            case 0x8F:
+                return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+            // fixarray
+            case 0x90:
+            case 0x91:
+            case 0x92:
+            case 0x93:
+            case 0x94:
+            case 0x95:
+            case 0x96:
+            case 0x97:
+            case 0x98:
+            case 0x99:
+            case 0x9A:
+            case 0x9B:
+            case 0x9C:
+            case 0x9D:
+            case 0x9E:
+            case 0x9F:
+                return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+            // fixstr
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+            case 0xB8:
+            case 0xB9:
+            case 0xBA:
+            case 0xBB:
+            case 0xBC:
+            case 0xBD:
+            case 0xBE:
+            case 0xBF:
+            case 0xD9: // str 8
+            case 0xDA: // str 16
+            case 0xDB: // str 32
+            {
+                string_t s;
+                return get_msgpack_string(s) and sax->string(s);
+            }
+
+            case 0xC0: // nil
+                return sax->null();
+
+            case 0xC2: // false
+                return sax->boolean(false);
+
+            case 0xC3: // true
+                return sax->boolean(true);
+
+            case 0xCA: // float 32
+            {
+                float number;
+                return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xCB: // float 64
+            {
+                double number;
+                return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 0xCC: // uint 8
+            {
+                std::uint8_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
+            }
+
+            case 0xCD: // uint 16
+            {
+                std::uint16_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
+            }
+
+            case 0xCE: // uint 32
+            {
+                std::uint32_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
+            }
+
+            case 0xCF: // uint 64
+            {
+                std::uint64_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
+            }
+
+            case 0xD0: // int 8
+            {
+                std::int8_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
+            }
+
+            case 0xD1: // int 16
+            {
+                std::int16_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
+            }
+
+            case 0xD2: // int 32
+            {
+                std::int32_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
+            }
+
+            case 0xD3: // int 64
+            {
+                std::int64_t number;
+                return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
+            }
+
+            case 0xDC: // array 16
+            {
+                std::uint16_t len;
+                return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
+            }
+
+            case 0xDD: // array 32
+            {
+                std::uint32_t len;
+                return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
+            }
+
+            case 0xDE: // map 16
+            {
+                std::uint16_t len;
+                return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
+            }
+
+            case 0xDF: // map 32
+            {
+                std::uint32_t len;
+                return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
+            }
+
+            // negative fixint
+            case 0xE0:
+            case 0xE1:
+            case 0xE2:
+            case 0xE3:
+            case 0xE4:
+            case 0xE5:
+            case 0xE6:
+            case 0xE7:
+            case 0xE8:
+            case 0xE9:
+            case 0xEA:
+            case 0xEB:
+            case 0xEC:
+            case 0xED:
+            case 0xEE:
+            case 0xEF:
+            case 0xF0:
+            case 0xF1:
+            case 0xF2:
+            case 0xF3:
+            case 0xF4:
+            case 0xF5:
+            case 0xF6:
+            case 0xF7:
+            case 0xF8:
+            case 0xF9:
+            case 0xFA:
+            case 0xFB:
+            case 0xFC:
+            case 0xFD:
+            case 0xFE:
+            case 0xFF:
+                return sax->number_integer(static_cast<std::int8_t>(current));
+
+            default: // anything else
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
+            }
+        }
+    }
+
+    /*!
+    @brief reads a MessagePack string
+
+    This function first reads starting bytes to determine the expected
+    string length and then copies this number of bytes into a string.
+
+    @param[out] result  created string
+
+    @return whether string creation completed
+    */
+    bool get_msgpack_string(string_t& result)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            // fixstr
+            case 0xA0:
+            case 0xA1:
+            case 0xA2:
+            case 0xA3:
+            case 0xA4:
+            case 0xA5:
+            case 0xA6:
+            case 0xA7:
+            case 0xA8:
+            case 0xA9:
+            case 0xAA:
+            case 0xAB:
+            case 0xAC:
+            case 0xAD:
+            case 0xAE:
+            case 0xAF:
+            case 0xB0:
+            case 0xB1:
+            case 0xB2:
+            case 0xB3:
+            case 0xB4:
+            case 0xB5:
+            case 0xB6:
+            case 0xB7:
+            case 0xB8:
+            case 0xB9:
+            case 0xBA:
+            case 0xBB:
+            case 0xBC:
+            case 0xBD:
+            case 0xBE:
+            case 0xBF:
+            {
+                return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
+            }
+
+            case 0xD9: // str 8
+            {
+                std::uint8_t len;
+                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
+            }
+
+            case 0xDA: // str 16
+            {
+                std::uint16_t len;
+                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
+            }
+
+            case 0xDB: // str 32
+            {
+                std::uint32_t len;
+                return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
+            }
+        }
+    }
+
+    /*!
+    @param[in] len  the length of the array
+    @return whether array creation completed
+    */
+    bool get_msgpack_array(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len)))
+        {
+            return false;
+        }
+
+        for (std::size_t i = 0; i < len; ++i)
+        {
+            if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal()))
+            {
+                return false;
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @param[in] len  the length of the object
+    @return whether object creation completed
+    */
+    bool get_msgpack_object(const std::size_t len)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len)))
+        {
+            return false;
+        }
+
+        string_t key;
+        for (std::size_t i = 0; i < len; ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
+            {
+                return false;
+            }
+
+            if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal()))
+            {
+                return false;
+            }
+            key.clear();
+        }
+
+        return sax->end_object();
+    }
+
+    ////////////
+    // UBJSON //
+    ////////////
+
+    /*!
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether a valid UBJSON value was passed to the SAX parser
+    */
+    bool parse_ubjson_internal(const bool get_char = true)
+    {
+        return get_ubjson_value(get_char ? get_ignore_noop() : current);
+    }
+
+    /*!
+    @brief reads a UBJSON string
+
+    This function is either called after reading the 'S' byte explicitly
+    indicating a string, or in case of an object key where the 'S' byte can be
+    left out.
+
+    @param[out] result   created string
+    @param[in] get_char  whether a new character should be retrieved from the
+                         input (true, default) or whether the last read
+                         character should be considered instead
+
+    @return whether string creation completed
+    */
+    bool get_ubjson_string(string_t& result, const bool get_char = true)
+    {
+        if (get_char)
+        {
+            get();  // TODO(niels): may we ignore N here?
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
+        {
+            return false;
+        }
+
+        switch (current)
+        {
+            case 'U':
+            {
+                std::uint8_t len;
+                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'i':
+            {
+                std::int8_t len;
+                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'I':
+            {
+                std::int16_t len;
+                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'l':
+            {
+                std::int32_t len;
+                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
+            }
+
+            case 'L':
+            {
+                std::int64_t len;
+                return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
+            }
+
+            default:
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
+        }
+    }
+
+    /*!
+    @param[out] result  determined size
+    @return whether size determination completed
+    */
+    bool get_ubjson_size_value(std::size_t& result)
+    {
+        switch (get_ignore_noop())
+        {
+            case 'U':
+            {
+                std::uint8_t number;
+                if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'i':
+            {
+                std::int8_t number;
+                if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'I':
+            {
+                std::int16_t number;
+                if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'l':
+            {
+                std::int32_t number;
+                if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            case 'L':
+            {
+                std::int64_t number;
+                if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
+                {
+                    return false;
+                }
+                result = static_cast<std::size_t>(number);
+                return true;
+            }
+
+            default:
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
+            }
+        }
+    }
+
+    /*!
+    @brief determine the type and size for a container
+
+    In the optimized UBJSON format, a type and a size can be provided to allow
+    for a more compact representation.
+
+    @param[out] result  pair of the size and the type
+
+    @return whether pair creation completed
+    */
+    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
+    {
+        result.first = string_t::npos; // size
+        result.second = 0; // type
+
+        get_ignore_noop();
+
+        if (current == '$')
+        {
+            result.second = get();  // must not ignore 'N', because 'N' maybe the type
+            if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
+            {
+                return false;
+            }
+
+            get_ignore_noop();
+            if (JSON_HEDLEY_UNLIKELY(current != '#'))
+            {
+                if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
+                {
+                    return false;
+                }
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
+            }
+
+            return get_ubjson_size_value(result.first);
+        }
+
+        if (current == '#')
+        {
+            return get_ubjson_size_value(result.first);
+        }
+
+        return true;
+    }
+
+    /*!
+    @param prefix  the previously read or set type prefix
+    @return whether value creation completed
+    */
+    bool get_ubjson_value(const int prefix)
+    {
+        switch (prefix)
+        {
+            case std::char_traits<char>::eof():  // EOF
+                return unexpect_eof(input_format_t::ubjson, "value");
+
+            case 'T':  // true
+                return sax->boolean(true);
+            case 'F':  // false
+                return sax->boolean(false);
+
+            case 'Z':  // null
+                return sax->null();
+
+            case 'U':
+            {
+                std::uint8_t number;
+                return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
+            }
+
+            case 'i':
+            {
+                std::int8_t number;
+                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
+            }
+
+            case 'I':
+            {
+                std::int16_t number;
+                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
+            }
+
+            case 'l':
+            {
+                std::int32_t number;
+                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
+            }
+
+            case 'L':
+            {
+                std::int64_t number;
+                return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
+            }
+
+            case 'd':
+            {
+                float number;
+                return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 'D':
+            {
+                double number;
+                return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
+            }
+
+            case 'C':  // char
+            {
+                get();
+                if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
+                {
+                    return false;
+                }
+                if (JSON_HEDLEY_UNLIKELY(current > 127))
+                {
+                    auto last_token = get_token_string();
+                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
+                }
+                string_t s(1, static_cast<char>(current));
+                return sax->string(s);
+            }
+
+            case 'S':  // string
+            {
+                string_t s;
+                return get_ubjson_string(s) and sax->string(s);
+            }
+
+            case '[':  // array
+                return get_ubjson_array();
+
+            case '{':  // object
+                return get_ubjson_object();
+
+            default: // anything else
+            {
+                auto last_token = get_token_string();
+                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
+            }
+        }
+    }
+
+    /*!
+    @return whether array creation completed
+    */
+    bool get_ubjson_array()
+    {
+        std::pair<std::size_t, int> size_and_type;
+        if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type)))
+        {
+            return false;
+        }
+
+        if (size_and_type.first != string_t::npos)
+        {
+            if (JSON_HEDLEY_UNLIKELY(not sax->start_array(size_and_type.first)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second != 0)
+            {
+                if (size_and_type.second != 'N')
+                {
+                    for (std::size_t i = 0; i < size_and_type.first; ++i)
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second)))
+                        {
+                            return false;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
+                    {
+                        return false;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
+            {
+                return false;
+            }
+
+            while (current != ']')
+            {
+                if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal(false)))
+                {
+                    return false;
+                }
+                get_ignore_noop();
+            }
+        }
+
+        return sax->end_array();
+    }
+
+    /*!
+    @return whether object creation completed
+    */
+    bool get_ubjson_object()
+    {
+        std::pair<std::size_t, int> size_and_type;
+        if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type)))
+        {
+            return false;
+        }
+
+        string_t key;
+        if (size_and_type.first != string_t::npos)
+        {
+            if (JSON_HEDLEY_UNLIKELY(not sax->start_object(size_and_type.first)))
+            {
+                return false;
+            }
+
+            if (size_and_type.second != 0)
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
+                    {
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second)))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+            else
+            {
+                for (std::size_t i = 0; i < size_and_type.first; ++i)
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
+                    {
+                        return false;
+                    }
+                    if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
+                    {
+                        return false;
+                    }
+                    key.clear();
+                }
+            }
+        }
+        else
+        {
+            if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
+            {
+                return false;
+            }
+
+            while (current != '}')
+            {
+                if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
+                {
+                    return false;
+                }
+                if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
+                {
+                    return false;
+                }
+                get_ignore_noop();
+                key.clear();
+            }
+        }
+
+        return sax->end_object();
+    }
+
+    ///////////////////////
+    // Utility functions //
+    ///////////////////////
+
+    /*!
+    @brief get next character from the input
+
+    This function provides the interface to the used input adapter. It does
+    not throw in case the input reached EOF, but returns a -'ve valued
+    `std::char_traits<char>::eof()` in that case.
+
+    @return character read from the input
+    */
+    int get()
+    {
+        ++chars_read;
+        return current = ia->get_character();
+    }
+
+    /*!
+    @return character read from the input after ignoring all 'N' entries
+    */
+    int get_ignore_noop()
+    {
+        do
+        {
+            get();
+        }
+        while (current == 'N');
+
+        return current;
+    }
+
+    /*
+    @brief read a number from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format   the current format (for diagnostics)
+    @param[out] result  number of type @a NumberType
+
+    @return whether conversion completed
+
+    @note This function needs to respect the system's endianess, because
+          bytes in CBOR, MessagePack, and UBJSON are stored in network order
+          (big endian) and therefore need reordering on little endian systems.
+    */
+    template<typename NumberType, bool InputIsLittleEndian = false>
+    bool get_number(const input_format_t format, NumberType& result)
+    {
+        // step 1: read input into array with system's byte order
+        std::array<std::uint8_t, sizeof(NumberType)> vec;
+        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "number")))
+            {
+                return false;
+            }
+
+            // reverse byte order prior to conversion if necessary
+            if (is_little_endian != InputIsLittleEndian)
+            {
+                vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
+            }
+            else
+            {
+                vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
+            }
+        }
+
+        // step 2: convert array into number of type T and return
+        std::memcpy(&result, vec.data(), sizeof(NumberType));
+        return true;
+    }
+
+    /*!
+    @brief create a string by reading characters from the input
+
+    @tparam NumberType the type of the number
+    @param[in] format the current format (for diagnostics)
+    @param[in] len number of characters to read
+    @param[out] result string created by reading @a len bytes
+
+    @return whether string creation completed
+
+    @note We can not reserve @a len bytes for the result, because @a len
+          may be too large. Usually, @ref unexpect_eof() detects the end of
+          the input before we run out of string memory.
+    */
+    template<typename NumberType>
+    bool get_string(const input_format_t format,
+                    const NumberType len,
+                    string_t& result)
+    {
+        bool success = true;
+        std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
+        {
+            get();
+            if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "string")))
+            {
+                success = false;
+            }
+            return static_cast<char>(current);
+        });
+        return success;
+    }
+
+    /*!
+    @param[in] format   the current format (for diagnostics)
+    @param[in] context  further context information (for diagnostics)
+    @return whether the last read character is not EOF
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    bool unexpect_eof(const input_format_t format, const char* context) const
+    {
+        if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char>::eof()))
+        {
+            return sax->parse_error(chars_read, "<end of file>",
+                                    parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
+        }
+        return true;
+    }
+
+    /*!
+    @return a string representation of the last read byte
+    */
+    std::string get_token_string() const
+    {
+        std::array<char, 3> cr{{}};
+        (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
+        return std::string{cr.data()};
+    }
+
+    /*!
+    @param[in] format   the current format
+    @param[in] detail   a detailed error message
+    @param[in] context  further context information
+    @return a message string to use in the parse_error exceptions
+    */
+    std::string exception_message(const input_format_t format,
+                                  const std::string& detail,
+                                  const std::string& context) const
+    {
+        std::string error_msg = "syntax error while parsing ";
+
+        switch (format)
+        {
+            case input_format_t::cbor:
+                error_msg += "CBOR";
+                break;
+
+            case input_format_t::msgpack:
+                error_msg += "MessagePack";
+                break;
+
+            case input_format_t::ubjson:
+                error_msg += "UBJSON";
+                break;
+
+            case input_format_t::bson:
+                error_msg += "BSON";
+                break;
+
+            default:            // LCOV_EXCL_LINE
+                assert(false);  // LCOV_EXCL_LINE
+        }
+
+        return error_msg + " " + context + ": " + detail;
+    }
+
+  private:
+    /// input adapter
+    input_adapter_t ia = nullptr;
+
+    /// the current character
+    int current = std::char_traits<char>::eof();
+
+    /// the number of characters read
+    std::size_t chars_read = 0;
+
+    /// whether we can assume little endianess
+    const bool is_little_endian = little_endianess();
+
+    /// the SAX parser
+    json_sax_t* sax = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+
+#include <array> // array
+#include <clocale> // localeconv
+#include <cstddef> // size_t
+#include <cstdio> // snprintf
+#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
+#include <initializer_list> // initializer_list
+#include <string> // char_traits, string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////
+// lexer //
+///////////
+
+/*!
+@brief lexical analysis
+
+This class organizes the lexical analysis during JSON deserialization.
+*/
+template<typename BasicJsonType>
+class lexer
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+
+  public:
+    /// token types for the parser
+    enum class token_type
+    {
+        uninitialized,    ///< indicating the scanner is uninitialized
+        literal_true,     ///< the `true` literal
+        literal_false,    ///< the `false` literal
+        literal_null,     ///< the `null` literal
+        value_string,     ///< a string -- use get_string() for actual value
+        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
+        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
+        value_float,      ///< an floating point number -- use get_number_float() for actual value
+        begin_array,      ///< the character for array begin `[`
+        begin_object,     ///< the character for object begin `{`
+        end_array,        ///< the character for array end `]`
+        end_object,       ///< the character for object end `}`
+        name_separator,   ///< the name separator `:`
+        value_separator,  ///< the value separator `,`
+        parse_error,      ///< indicating a parse error
+        end_of_input,     ///< indicating the end of the input buffer
+        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
+    };
+
+    /// return name of values of type token_type (only used for errors)
+    JSON_HEDLEY_RETURNS_NON_NULL
+    JSON_HEDLEY_CONST
+    static const char* token_type_name(const token_type t) noexcept
+    {
+        switch (t)
+        {
+            case token_type::uninitialized:
+                return "<uninitialized>";
+            case token_type::literal_true:
+                return "true literal";
+            case token_type::literal_false:
+                return "false literal";
+            case token_type::literal_null:
+                return "null literal";
+            case token_type::value_string:
+                return "string literal";
+            case lexer::token_type::value_unsigned:
+            case lexer::token_type::value_integer:
+            case lexer::token_type::value_float:
+                return "number literal";
+            case token_type::begin_array:
+                return "'['";
+            case token_type::begin_object:
+                return "'{'";
+            case token_type::end_array:
+                return "']'";
+            case token_type::end_object:
+                return "'}'";
+            case token_type::name_separator:
+                return "':'";
+            case token_type::value_separator:
+                return "','";
+            case token_type::parse_error:
+                return "<parse error>";
+            case token_type::end_of_input:
+                return "end of input";
+            case token_type::literal_or_value:
+                return "'[', '{', or a literal";
+            // LCOV_EXCL_START
+            default: // catch non-enum values
+                return "unknown token";
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    explicit lexer(detail::input_adapter_t&& adapter)
+        : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
+
+    // delete because of pointer members
+    lexer(const lexer&) = delete;
+    lexer(lexer&&) = delete;
+    lexer& operator=(lexer&) = delete;
+    lexer& operator=(lexer&&) = delete;
+    ~lexer() = default;
+
+  private:
+    /////////////////////
+    // locales
+    /////////////////////
+
+    /// return the locale-dependent decimal point
+    JSON_HEDLEY_PURE
+    static char get_decimal_point() noexcept
+    {
+        const auto loc = localeconv();
+        assert(loc != nullptr);
+        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
+    }
+
+    /////////////////////
+    // scan functions
+    /////////////////////
+
+    /*!
+    @brief get codepoint from 4 hex characters following `\u`
+
+    For input "\u c1 c2 c3 c4" the codepoint is:
+      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
+    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
+
+    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
+    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
+    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
+    between the ASCII value of the character and the desired integer value.
+
+    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
+            non-hex character)
+    */
+    int get_codepoint()
+    {
+        // this function only makes sense after reading `\u`
+        assert(current == 'u');
+        int codepoint = 0;
+
+        const auto factors = { 12u, 8u, 4u, 0u };
+        for (const auto factor : factors)
+        {
+            get();
+
+            if (current >= '0' and current <= '9')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
+            }
+            else if (current >= 'A' and current <= 'F')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
+            }
+            else if (current >= 'a' and current <= 'f')
+            {
+                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
+            }
+            else
+            {
+                return -1;
+            }
+        }
+
+        assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
+        return codepoint;
+    }
+
+    /*!
+    @brief check if the next byte(s) are inside a given range
+
+    Adds the current byte and, for each passed range, reads a new byte and
+    checks if it is inside the range. If a violation was detected, set up an
+    error message and return false. Otherwise, return true.
+
+    @param[in] ranges  list of integers; interpreted as list of pairs of
+                       inclusive lower and upper bound, respectively
+
+    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
+         1, 2, or 3 pairs. This precondition is enforced by an assertion.
+
+    @return true if and only if no range violation was detected
+    */
+    bool next_byte_in_range(std::initializer_list<int> ranges)
+    {
+        assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
+        add(current);
+
+        for (auto range = ranges.begin(); range != ranges.end(); ++range)
+        {
+            get();
+            if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range)))
+            {
+                add(current);
+            }
+            else
+            {
+                error_message = "invalid string: ill-formed UTF-8 byte";
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /*!
+    @brief scan a string literal
+
+    This function scans a string according to Sect. 7 of RFC 7159. While
+    scanning, bytes are escaped and copied into buffer token_buffer. Then the
+    function returns successfully, token_buffer is *not* null-terminated (as it
+    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
+    string.
+
+    @return token_type::value_string if string could be successfully scanned,
+            token_type::parse_error otherwise
+
+    @note In case of errors, variable error_message contains a textual
+          description.
+    */
+    token_type scan_string()
+    {
+        // reset token_buffer (ignore opening quote)
+        reset();
+
+        // we entered the function by reading an open quote
+        assert(current == '\"');
+
+        while (true)
+        {
+            // get next character
+            switch (get())
+            {
+                // end of file while parsing string
+                case std::char_traits<char>::eof():
+                {
+                    error_message = "invalid string: missing closing quote";
+                    return token_type::parse_error;
+                }
+
+                // closing quote
+                case '\"':
+                {
+                    return token_type::value_string;
+                }
+
+                // escapes
+                case '\\':
+                {
+                    switch (get())
+                    {
+                        // quotation mark
+                        case '\"':
+                            add('\"');
+                            break;
+                        // reverse solidus
+                        case '\\':
+                            add('\\');
+                            break;
+                        // solidus
+                        case '/':
+                            add('/');
+                            break;
+                        // backspace
+                        case 'b':
+                            add('\b');
+                            break;
+                        // form feed
+                        case 'f':
+                            add('\f');
+                            break;
+                        // line feed
+                        case 'n':
+                            add('\n');
+                            break;
+                        // carriage return
+                        case 'r':
+                            add('\r');
+                            break;
+                        // tab
+                        case 't':
+                            add('\t');
+                            break;
+
+                        // unicode escapes
+                        case 'u':
+                        {
+                            const int codepoint1 = get_codepoint();
+                            int codepoint = codepoint1; // start with codepoint1
+
+                            if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
+                            {
+                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+                                return token_type::parse_error;
+                            }
+
+                            // check if code point is a high surrogate
+                            if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
+                            {
+                                // expect next \uxxxx entry
+                                if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u'))
+                                {
+                                    const int codepoint2 = get_codepoint();
+
+                                    if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
+                                    {
+                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+                                        return token_type::parse_error;
+                                    }
+
+                                    // check if codepoint2 is a low surrogate
+                                    if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
+                                    {
+                                        // overwrite codepoint
+                                        codepoint = static_cast<int>(
+                                                        // high surrogate occupies the most significant 22 bits
+                                                        (static_cast<unsigned int>(codepoint1) << 10u)
+                                                        // low surrogate occupies the least significant 15 bits
+                                                        + static_cast<unsigned int>(codepoint2)
+                                                        // there is still the 0xD800, 0xDC00 and 0x10000 noise
+                                                        // in the result so we have to subtract with:
+                                                        // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
+                                                        - 0x35FDC00u);
+                                    }
+                                    else
+                                    {
+                                        error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
+                                        return token_type::parse_error;
+                                    }
+                                }
+                                else
+                                {
+                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
+                                    return token_type::parse_error;
+                                }
+                            }
+                            else
+                            {
+                                if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
+                                {
+                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
+                                    return token_type::parse_error;
+                                }
+                            }
+
+                            // result of the above calculation yields a proper codepoint
+                            assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
+
+                            // translate codepoint into bytes
+                            if (codepoint < 0x80)
+                            {
+                                // 1-byte characters: 0xxxxxxx (ASCII)
+                                add(codepoint);
+                            }
+                            else if (codepoint <= 0x7FF)
+                            {
+                                // 2-byte characters: 110xxxxx 10xxxxxx
+                                add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
+                                add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+                            else if (codepoint <= 0xFFFF)
+                            {
+                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
+                                add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
+                                add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+                                add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+                            else
+                            {
+                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+                                add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
+                                add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
+                                add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+                                add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+                            }
+
+                            break;
+                        }
+
+                        // other characters after escape
+                        default:
+                            error_message = "invalid string: forbidden character after backslash";
+                            return token_type::parse_error;
+                    }
+
+                    break;
+                }
+
+                // invalid control characters
+                case 0x00:
+                {
+                    error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
+                    return token_type::parse_error;
+                }
+
+                case 0x01:
+                {
+                    error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
+                    return token_type::parse_error;
+                }
+
+                case 0x02:
+                {
+                    error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
+                    return token_type::parse_error;
+                }
+
+                case 0x03:
+                {
+                    error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
+                    return token_type::parse_error;
+                }
+
+                case 0x04:
+                {
+                    error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
+                    return token_type::parse_error;
+                }
+
+                case 0x05:
+                {
+                    error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
+                    return token_type::parse_error;
+                }
+
+                case 0x06:
+                {
+                    error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
+                    return token_type::parse_error;
+                }
+
+                case 0x07:
+                {
+                    error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
+                    return token_type::parse_error;
+                }
+
+                case 0x08:
+                {
+                    error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
+                    return token_type::parse_error;
+                }
+
+                case 0x09:
+                {
+                    error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
+                    return token_type::parse_error;
+                }
+
+                case 0x0A:
+                {
+                    error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
+                    return token_type::parse_error;
+                }
+
+                case 0x0B:
+                {
+                    error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
+                    return token_type::parse_error;
+                }
+
+                case 0x0C:
+                {
+                    error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
+                    return token_type::parse_error;
+                }
+
+                case 0x0D:
+                {
+                    error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
+                    return token_type::parse_error;
+                }
+
+                case 0x0E:
+                {
+                    error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
+                    return token_type::parse_error;
+                }
+
+                case 0x0F:
+                {
+                    error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
+                    return token_type::parse_error;
+                }
+
+                case 0x10:
+                {
+                    error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
+                    return token_type::parse_error;
+                }
+
+                case 0x11:
+                {
+                    error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
+                    return token_type::parse_error;
+                }
+
+                case 0x12:
+                {
+                    error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
+                    return token_type::parse_error;
+                }
+
+                case 0x13:
+                {
+                    error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
+                    return token_type::parse_error;
+                }
+
+                case 0x14:
+                {
+                    error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
+                    return token_type::parse_error;
+                }
+
+                case 0x15:
+                {
+                    error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
+                    return token_type::parse_error;
+                }
+
+                case 0x16:
+                {
+                    error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
+                    return token_type::parse_error;
+                }
+
+                case 0x17:
+                {
+                    error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
+                    return token_type::parse_error;
+                }
+
+                case 0x18:
+                {
+                    error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
+                    return token_type::parse_error;
+                }
+
+                case 0x19:
+                {
+                    error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
+                    return token_type::parse_error;
+                }
+
+                case 0x1A:
+                {
+                    error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
+                    return token_type::parse_error;
+                }
+
+                case 0x1B:
+                {
+                    error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
+                    return token_type::parse_error;
+                }
+
+                case 0x1C:
+                {
+                    error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
+                    return token_type::parse_error;
+                }
+
+                case 0x1D:
+                {
+                    error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
+                    return token_type::parse_error;
+                }
+
+                case 0x1E:
+                {
+                    error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
+                    return token_type::parse_error;
+                }
+
+                case 0x1F:
+                {
+                    error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
+                    return token_type::parse_error;
+                }
+
+                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
+                case 0x20:
+                case 0x21:
+                case 0x23:
+                case 0x24:
+                case 0x25:
+                case 0x26:
+                case 0x27:
+                case 0x28:
+                case 0x29:
+                case 0x2A:
+                case 0x2B:
+                case 0x2C:
+                case 0x2D:
+                case 0x2E:
+                case 0x2F:
+                case 0x30:
+                case 0x31:
+                case 0x32:
+                case 0x33:
+                case 0x34:
+                case 0x35:
+                case 0x36:
+                case 0x37:
+                case 0x38:
+                case 0x39:
+                case 0x3A:
+                case 0x3B:
+                case 0x3C:
+                case 0x3D:
+                case 0x3E:
+                case 0x3F:
+                case 0x40:
+                case 0x41:
+                case 0x42:
+                case 0x43:
+                case 0x44:
+                case 0x45:
+                case 0x46:
+                case 0x47:
+                case 0x48:
+                case 0x49:
+                case 0x4A:
+                case 0x4B:
+                case 0x4C:
+                case 0x4D:
+                case 0x4E:
+                case 0x4F:
+                case 0x50:
+                case 0x51:
+                case 0x52:
+                case 0x53:
+                case 0x54:
+                case 0x55:
+                case 0x56:
+                case 0x57:
+                case 0x58:
+                case 0x59:
+                case 0x5A:
+                case 0x5B:
+                case 0x5D:
+                case 0x5E:
+                case 0x5F:
+                case 0x60:
+                case 0x61:
+                case 0x62:
+                case 0x63:
+                case 0x64:
+                case 0x65:
+                case 0x66:
+                case 0x67:
+                case 0x68:
+                case 0x69:
+                case 0x6A:
+                case 0x6B:
+                case 0x6C:
+                case 0x6D:
+                case 0x6E:
+                case 0x6F:
+                case 0x70:
+                case 0x71:
+                case 0x72:
+                case 0x73:
+                case 0x74:
+                case 0x75:
+                case 0x76:
+                case 0x77:
+                case 0x78:
+                case 0x79:
+                case 0x7A:
+                case 0x7B:
+                case 0x7C:
+                case 0x7D:
+                case 0x7E:
+                case 0x7F:
+                {
+                    add(current);
+                    break;
+                }
+
+                // U+0080..U+07FF: bytes C2..DF 80..BF
+                case 0xC2:
+                case 0xC3:
+                case 0xC4:
+                case 0xC5:
+                case 0xC6:
+                case 0xC7:
+                case 0xC8:
+                case 0xC9:
+                case 0xCA:
+                case 0xCB:
+                case 0xCC:
+                case 0xCD:
+                case 0xCE:
+                case 0xCF:
+                case 0xD0:
+                case 0xD1:
+                case 0xD2:
+                case 0xD3:
+                case 0xD4:
+                case 0xD5:
+                case 0xD6:
+                case 0xD7:
+                case 0xD8:
+                case 0xD9:
+                case 0xDA:
+                case 0xDB:
+                case 0xDC:
+                case 0xDD:
+                case 0xDE:
+                case 0xDF:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
+                case 0xE0:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
+                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
+                case 0xE1:
+                case 0xE2:
+                case 0xE3:
+                case 0xE4:
+                case 0xE5:
+                case 0xE6:
+                case 0xE7:
+                case 0xE8:
+                case 0xE9:
+                case 0xEA:
+                case 0xEB:
+                case 0xEC:
+                case 0xEE:
+                case 0xEF:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
+                case 0xED:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
+                case 0xF0:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
+                case 0xF1:
+                case 0xF2:
+                case 0xF3:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+                case 0xF4:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
+                    {
+                        return token_type::parse_error;
+                    }
+                    break;
+                }
+
+                // remaining bytes (80..C1 and F5..FF) are ill-formed
+                default:
+                {
+                    error_message = "invalid string: ill-formed UTF-8 byte";
+                    return token_type::parse_error;
+                }
+            }
+        }
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(float& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtof(str, endptr);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(double& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtod(str, endptr);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    static void strtof(long double& f, const char* str, char** endptr) noexcept
+    {
+        f = std::strtold(str, endptr);
+    }
+
+    /*!
+    @brief scan a number literal
+
+    This function scans a string according to Sect. 6 of RFC 7159.
+
+    The function is realized with a deterministic finite state machine derived
+    from the grammar described in RFC 7159. Starting in state "init", the
+    input is read and used to determined the next state. Only state "done"
+    accepts the number. State "error" is a trap state to model errors. In the
+    table below, "anything" means any character but the ones listed before.
+
+    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
+    ---------|----------|----------|----------|---------|---------|----------|-----------
+    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
+    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
+    zero     | done     | done     | exponent | done    | done    | decimal1 | done
+    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
+    decimal1 | decimal2 | [error]  | [error]  | [error] | [error] | [error]  | [error]
+    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
+    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
+    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
+    any2     | any2     | any2     | done     | done    | done    | done     | done
+
+    The state machine is realized with one label per state (prefixed with
+    "scan_number_") and `goto` statements between them. The state machine
+    contains cycles, but any cycle can be left when EOF is read. Therefore,
+    the function is guaranteed to terminate.
+
+    During scanning, the read bytes are stored in token_buffer. This string is
+    then converted to a signed integer, an unsigned integer, or a
+    floating-point number.
+
+    @return token_type::value_unsigned, token_type::value_integer, or
+            token_type::value_float if number could be successfully scanned,
+            token_type::parse_error otherwise
+
+    @note The scanner is independent of the current locale. Internally, the
+          locale's decimal point is used instead of `.` to work with the
+          locale-dependent converters.
+    */
+    token_type scan_number()  // lgtm [cpp/use-of-goto]
+    {
+        // reset token_buffer to store the number's bytes
+        reset();
+
+        // the type of the parsed number; initially set to unsigned; will be
+        // changed if minus sign, decimal point or exponent is read
+        token_type number_type = token_type::value_unsigned;
+
+        // state (init): we just found out we need to scan a number
+        switch (current)
+        {
+            case '-':
+            {
+                add(current);
+                goto scan_number_minus;
+            }
+
+            case '0':
+            {
+                add(current);
+                goto scan_number_zero;
+            }
+
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            // all other characters are rejected outside scan_number()
+            default:            // LCOV_EXCL_LINE
+                assert(false);  // LCOV_EXCL_LINE
+        }
+
+scan_number_minus:
+        // state: we just parsed a leading minus sign
+        number_type = token_type::value_integer;
+        switch (get())
+        {
+            case '0':
+            {
+                add(current);
+                goto scan_number_zero;
+            }
+
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after '-'";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_zero:
+        // state: we just parse a zero (maybe with a leading minus sign)
+        switch (get())
+        {
+            case '.':
+            {
+                add(decimal_point_char);
+                goto scan_number_decimal1;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_any1:
+        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any1;
+            }
+
+            case '.':
+            {
+                add(decimal_point_char);
+                goto scan_number_decimal1;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_decimal1:
+        // state: we just parsed a decimal point
+        number_type = token_type::value_float;
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_decimal2;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after '.'";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_decimal2:
+        // we just parsed at least one number after a decimal point
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_decimal2;
+            }
+
+            case 'e':
+            case 'E':
+            {
+                add(current);
+                goto scan_number_exponent;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_exponent:
+        // we just parsed an exponent
+        number_type = token_type::value_float;
+        switch (get())
+        {
+            case '+':
+            case '-':
+            {
+                add(current);
+                goto scan_number_sign;
+            }
+
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+            {
+                error_message =
+                    "invalid number; expected '+', '-', or digit after exponent";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_sign:
+        // we just parsed an exponent sign
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+            {
+                error_message = "invalid number; expected digit after exponent sign";
+                return token_type::parse_error;
+            }
+        }
+
+scan_number_any2:
+        // we just parsed a number after the exponent or exponent sign
+        switch (get())
+        {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            {
+                add(current);
+                goto scan_number_any2;
+            }
+
+            default:
+                goto scan_number_done;
+        }
+
+scan_number_done:
+        // unget the character after the number (we only read it to know that
+        // we are done scanning a number)
+        unget();
+
+        char* endptr = nullptr;
+        errno = 0;
+
+        // try to parse integers first and fall back to floats
+        if (number_type == token_type::value_unsigned)
+        {
+            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
+
+            // we checked the number format before
+            assert(endptr == token_buffer.data() + token_buffer.size());
+
+            if (errno == 0)
+            {
+                value_unsigned = static_cast<number_unsigned_t>(x);
+                if (value_unsigned == x)
+                {
+                    return token_type::value_unsigned;
+                }
+            }
+        }
+        else if (number_type == token_type::value_integer)
+        {
+            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
+
+            // we checked the number format before
+            assert(endptr == token_buffer.data() + token_buffer.size());
+
+            if (errno == 0)
+            {
+                value_integer = static_cast<number_integer_t>(x);
+                if (value_integer == x)
+                {
+                    return token_type::value_integer;
+                }
+            }
+        }
+
+        // this code is reached if we parse a floating-point number or if an
+        // integer conversion above failed
+        strtof(value_float, token_buffer.data(), &endptr);
+
+        // we checked the number format before
+        assert(endptr == token_buffer.data() + token_buffer.size());
+
+        return token_type::value_float;
+    }
+
+    /*!
+    @param[in] literal_text  the literal text to expect
+    @param[in] length        the length of the passed literal text
+    @param[in] return_type   the token type to return on success
+    */
+    JSON_HEDLEY_NON_NULL(2)
+    token_type scan_literal(const char* literal_text, const std::size_t length,
+                            token_type return_type)
+    {
+        assert(current == literal_text[0]);
+        for (std::size_t i = 1; i < length; ++i)
+        {
+            if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i]))
+            {
+                error_message = "invalid literal";
+                return token_type::parse_error;
+            }
+        }
+        return return_type;
+    }
+
+    /////////////////////
+    // input management
+    /////////////////////
+
+    /// reset token_buffer; current character is beginning of token
+    void reset() noexcept
+    {
+        token_buffer.clear();
+        token_string.clear();
+        token_string.push_back(std::char_traits<char>::to_char_type(current));
+    }
+
+    /*
+    @brief get next character from the input
+
+    This function provides the interface to the used input adapter. It does
+    not throw in case the input reached EOF, but returns a
+    `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
+    for use in error messages.
+
+    @return character read from the input
+    */
+    std::char_traits<char>::int_type get()
+    {
+        ++position.chars_read_total;
+        ++position.chars_read_current_line;
+
+        if (next_unget)
+        {
+            // just reset the next_unget variable and work with current
+            next_unget = false;
+        }
+        else
+        {
+            current = ia->get_character();
+        }
+
+        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
+        {
+            token_string.push_back(std::char_traits<char>::to_char_type(current));
+        }
+
+        if (current == '\n')
+        {
+            ++position.lines_read;
+            position.chars_read_current_line = 0;
+        }
+
+        return current;
+    }
+
+    /*!
+    @brief unget current character (read it again on next get)
+
+    We implement unget by setting variable next_unget to true. The input is not
+    changed - we just simulate ungetting by modifying chars_read_total,
+    chars_read_current_line, and token_string. The next call to get() will
+    behave as if the unget character is read again.
+    */
+    void unget()
+    {
+        next_unget = true;
+
+        --position.chars_read_total;
+
+        // in case we "unget" a newline, we have to also decrement the lines_read
+        if (position.chars_read_current_line == 0)
+        {
+            if (position.lines_read > 0)
+            {
+                --position.lines_read;
+            }
+        }
+        else
+        {
+            --position.chars_read_current_line;
+        }
+
+        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
+        {
+            assert(not token_string.empty());
+            token_string.pop_back();
+        }
+    }
+
+    /// add a character to token_buffer
+    void add(int c)
+    {
+        token_buffer.push_back(std::char_traits<char>::to_char_type(c));
+    }
+
+  public:
+    /////////////////////
+    // value getters
+    /////////////////////
+
+    /// return integer value
+    constexpr number_integer_t get_number_integer() const noexcept
+    {
+        return value_integer;
+    }
+
+    /// return unsigned integer value
+    constexpr number_unsigned_t get_number_unsigned() const noexcept
+    {
+        return value_unsigned;
+    }
+
+    /// return floating-point value
+    constexpr number_float_t get_number_float() const noexcept
+    {
+        return value_float;
+    }
+
+    /// return current string value (implicitly resets the token; useful only once)
+    string_t& get_string()
+    {
+        return token_buffer;
+    }
+
+    /////////////////////
+    // diagnostics
+    /////////////////////
+
+    /// return position of last read token
+    constexpr position_t get_position() const noexcept
+    {
+        return position;
+    }
+
+    /// return the last read token (for errors only).  Will never contain EOF
+    /// (an arbitrary value that is not a valid char value, often -1), because
+    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
+    std::string get_token_string() const
+    {
+        // escape control characters
+        std::string result;
+        for (const auto c : token_string)
+        {
+            if ('\x00' <= c and c <= '\x1F')
+            {
+                // escape control characters
+                std::array<char, 9> cs{{}};
+                (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
+                result += cs.data();
+            }
+            else
+            {
+                // add character as is
+                result.push_back(c);
+            }
+        }
+
+        return result;
+    }
+
+    /// return syntax error message
+    JSON_HEDLEY_RETURNS_NON_NULL
+    constexpr const char* get_error_message() const noexcept
+    {
+        return error_message;
+    }
+
+    /////////////////////
+    // actual scanner
+    /////////////////////
+
+    /*!
+    @brief skip the UTF-8 byte order mark
+    @return true iff there is no BOM or the correct BOM has been skipped
+    */
+    bool skip_bom()
+    {
+        if (get() == 0xEF)
+        {
+            // check if we completely parse the BOM
+            return get() == 0xBB and get() == 0xBF;
+        }
+
+        // the first character is not the beginning of the BOM; unget it to
+        // process is later
+        unget();
+        return true;
+    }
+
+    token_type scan()
+    {
+        // initially, skip the BOM
+        if (position.chars_read_total == 0 and not skip_bom())
+        {
+            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
+            return token_type::parse_error;
+        }
+
+        // read next character and ignore whitespace
+        do
+        {
+            get();
+        }
+        while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
+
+        switch (current)
+        {
+            // structural characters
+            case '[':
+                return token_type::begin_array;
+            case ']':
+                return token_type::end_array;
+            case '{':
+                return token_type::begin_object;
+            case '}':
+                return token_type::end_object;
+            case ':':
+                return token_type::name_separator;
+            case ',':
+                return token_type::value_separator;
+
+            // literals
+            case 't':
+                return scan_literal("true", 4, token_type::literal_true);
+            case 'f':
+                return scan_literal("false", 5, token_type::literal_false);
+            case 'n':
+                return scan_literal("null", 4, token_type::literal_null);
+
+            // string
+            case '\"':
+                return scan_string();
+
+            // number
+            case '-':
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                return scan_number();
+
+            // end of input (the null byte is needed when parsing from
+            // string literals)
+            case '\0':
+            case std::char_traits<char>::eof():
+                return token_type::end_of_input;
+
+            // error
+            default:
+                error_message = "invalid literal";
+                return token_type::parse_error;
+        }
+    }
+
+  private:
+    /// input adapter
+    detail::input_adapter_t ia = nullptr;
+
+    /// the current character
+    std::char_traits<char>::int_type current = std::char_traits<char>::eof();
+
+    /// whether the next get() call should just return current
+    bool next_unget = false;
+
+    /// the start position of the current token
+    position_t position {};
+
+    /// raw input token string (for error messages)
+    std::vector<char> token_string {};
+
+    /// buffer for variable-length tokens (numbers, strings)
+    string_t token_buffer {};
+
+    /// a description of occurred lexer errors
+    const char* error_message = "";
+
+    // number values
+    number_integer_t value_integer = 0;
+    number_unsigned_t value_unsigned = 0;
+    number_float_t value_float = 0;
+
+    /// the decimal point
+    const char decimal_point_char = '.';
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/input/parser.hpp>
+
+
+#include <cassert> // assert
+#include <cmath> // isfinite
+#include <cstdint> // uint8_t
+#include <functional> // function
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+////////////
+// parser //
+////////////
+
+/*!
+@brief syntax analysis
+
+This class implements a recursive decent parser.
+*/
+template<typename BasicJsonType>
+class parser
+{
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using string_t = typename BasicJsonType::string_t;
+    using lexer_t = lexer<BasicJsonType>;
+    using token_type = typename lexer_t::token_type;
+
+  public:
+    enum class parse_event_t : uint8_t
+    {
+        /// the parser read `{` and started to process a JSON object
+        object_start,
+        /// the parser read `}` and finished processing a JSON object
+        object_end,
+        /// the parser read `[` and started to process a JSON array
+        array_start,
+        /// the parser read `]` and finished processing a JSON array
+        array_end,
+        /// the parser read a key of a value in an object
+        key,
+        /// the parser finished reading a JSON value
+        value
+    };
+
+    using parser_callback_t =
+        std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
+
+    /// a parser reading from an input adapter
+    explicit parser(detail::input_adapter_t&& adapter,
+                    const parser_callback_t cb = nullptr,
+                    const bool allow_exceptions_ = true)
+        : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
+    {
+        // read first token
+        get_token();
+    }
+
+    /*!
+    @brief public parser interface
+
+    @param[in] strict      whether to expect the last token to be EOF
+    @param[in,out] result  parsed JSON value
+
+    @throw parse_error.101 in case of an unexpected token
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+    */
+    void parse(const bool strict, BasicJsonType& result)
+    {
+        if (callback)
+        {
+            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
+            sax_parse_internal(&sdp);
+            result.assert_invariant();
+
+            // in strict mode, input must be completely read
+            if (strict and (get_token() != token_type::end_of_input))
+            {
+                sdp.parse_error(m_lexer.get_position(),
+                                m_lexer.get_token_string(),
+                                parse_error::create(101, m_lexer.get_position(),
+                                                    exception_message(token_type::end_of_input, "value")));
+            }
+
+            // in case of an error, return discarded value
+            if (sdp.is_errored())
+            {
+                result = value_t::discarded;
+                return;
+            }
+
+            // set top-level value to null if it was discarded by the callback
+            // function
+            if (result.is_discarded())
+            {
+                result = nullptr;
+            }
+        }
+        else
+        {
+            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
+            sax_parse_internal(&sdp);
+            result.assert_invariant();
+
+            // in strict mode, input must be completely read
+            if (strict and (get_token() != token_type::end_of_input))
+            {
+                sdp.parse_error(m_lexer.get_position(),
+                                m_lexer.get_token_string(),
+                                parse_error::create(101, m_lexer.get_position(),
+                                                    exception_message(token_type::end_of_input, "value")));
+            }
+
+            // in case of an error, return discarded value
+            if (sdp.is_errored())
+            {
+                result = value_t::discarded;
+                return;
+            }
+        }
+    }
+
+    /*!
+    @brief public accept interface
+
+    @param[in] strict  whether to expect the last token to be EOF
+    @return whether the input is a proper JSON text
+    */
+    bool accept(const bool strict = true)
+    {
+        json_sax_acceptor<BasicJsonType> sax_acceptor;
+        return sax_parse(&sax_acceptor, strict);
+    }
+
+    template <typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    bool sax_parse(SAX* sax, const bool strict = true)
+    {
+        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+        const bool result = sax_parse_internal(sax);
+
+        // strict mode: next byte must be EOF
+        if (result and strict and (get_token() != token_type::end_of_input))
+        {
+            return sax->parse_error(m_lexer.get_position(),
+                                    m_lexer.get_token_string(),
+                                    parse_error::create(101, m_lexer.get_position(),
+                                            exception_message(token_type::end_of_input, "value")));
+        }
+
+        return result;
+    }
+
+  private:
+    template <typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    bool sax_parse_internal(SAX* sax)
+    {
+        // stack to remember the hierarchy of structured values we are parsing
+        // true = array; false = object
+        std::vector<bool> states;
+        // value to avoid a goto (see comment where set to true)
+        bool skip_to_state_evaluation = false;
+
+        while (true)
+        {
+            if (not skip_to_state_evaluation)
+            {
+                // invariant: get_token() was called before each iteration
+                switch (last_token)
+                {
+                    case token_type::begin_object:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
+                        {
+                            return false;
+                        }
+
+                        // closing } -> we are done
+                        if (get_token() == token_type::end_object)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
+                            {
+                                return false;
+                            }
+                            break;
+                        }
+
+                        // parse key
+                        if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    parse_error::create(101, m_lexer.get_position(),
+                                                            exception_message(token_type::value_string, "object key")));
+                        }
+                        if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+
+                        // parse separator (:)
+                        if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    parse_error::create(101, m_lexer.get_position(),
+                                                            exception_message(token_type::name_separator, "object separator")));
+                        }
+
+                        // remember we are now inside an object
+                        states.push_back(false);
+
+                        // parse values
+                        get_token();
+                        continue;
+                    }
+
+                    case token_type::begin_array:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
+                        {
+                            return false;
+                        }
+
+                        // closing ] -> we are done
+                        if (get_token() == token_type::end_array)
+                        {
+                            if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
+                            {
+                                return false;
+                            }
+                            break;
+                        }
+
+                        // remember we are now inside an array
+                        states.push_back(true);
+
+                        // parse values (no need to call get_token)
+                        continue;
+                    }
+
+                    case token_type::value_float:
+                    {
+                        const auto res = m_lexer.get_number_float();
+
+                        if (JSON_HEDLEY_UNLIKELY(not std::isfinite(res)))
+                        {
+                            return sax->parse_error(m_lexer.get_position(),
+                                                    m_lexer.get_token_string(),
+                                                    out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
+                        }
+
+                        if (JSON_HEDLEY_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+
+                        break;
+                    }
+
+                    case token_type::literal_false:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->boolean(false)))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::literal_null:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->null()))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::literal_true:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->boolean(true)))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_integer:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_string:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->string(m_lexer.get_string())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::value_unsigned:
+                    {
+                        if (JSON_HEDLEY_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
+                        {
+                            return false;
+                        }
+                        break;
+                    }
+
+                    case token_type::parse_error:
+                    {
+                        // using "uninitialized" to avoid "expected" message
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(),
+                                                        exception_message(token_type::uninitialized, "value")));
+                    }
+
+                    default: // the last token was unexpected
+                    {
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(),
+                                                        exception_message(token_type::literal_or_value, "value")));
+                    }
+                }
+            }
+            else
+            {
+                skip_to_state_evaluation = false;
+            }
+
+            // we reached this line after we successfully parsed a value
+            if (states.empty())
+            {
+                // empty stack: we reached the end of the hierarchy: done
+                return true;
+            }
+
+            if (states.back())  // array
+            {
+                // comma -> next value
+                if (get_token() == token_type::value_separator)
+                {
+                    // parse a new value
+                    get_token();
+                    continue;
+                }
+
+                // closing ]
+                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
+                    {
+                        return false;
+                    }
+
+                    // We are done with this array. Before we can parse a
+                    // new value, we need to evaluate the new state first.
+                    // By setting skip_to_state_evaluation to false, we
+                    // are effectively jumping to the beginning of this if.
+                    assert(not states.empty());
+                    states.pop_back();
+                    skip_to_state_evaluation = true;
+                    continue;
+                }
+
+                return sax->parse_error(m_lexer.get_position(),
+                                        m_lexer.get_token_string(),
+                                        parse_error::create(101, m_lexer.get_position(),
+                                                exception_message(token_type::end_array, "array")));
+            }
+            else  // object
+            {
+                // comma -> next value
+                if (get_token() == token_type::value_separator)
+                {
+                    // parse key
+                    if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
+                    {
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(),
+                                                        exception_message(token_type::value_string, "object key")));
+                    }
+
+                    if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
+                    {
+                        return false;
+                    }
+
+                    // parse separator (:)
+                    if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+                    {
+                        return sax->parse_error(m_lexer.get_position(),
+                                                m_lexer.get_token_string(),
+                                                parse_error::create(101, m_lexer.get_position(),
+                                                        exception_message(token_type::name_separator, "object separator")));
+                    }
+
+                    // parse values
+                    get_token();
+                    continue;
+                }
+
+                // closing }
+                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
+                {
+                    if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
+                    {
+                        return false;
+                    }
+
+                    // We are done with this object. Before we can parse a
+                    // new value, we need to evaluate the new state first.
+                    // By setting skip_to_state_evaluation to false, we
+                    // are effectively jumping to the beginning of this if.
+                    assert(not states.empty());
+                    states.pop_back();
+                    skip_to_state_evaluation = true;
+                    continue;
+                }
+
+                return sax->parse_error(m_lexer.get_position(),
+                                        m_lexer.get_token_string(),
+                                        parse_error::create(101, m_lexer.get_position(),
+                                                exception_message(token_type::end_object, "object")));
+            }
+        }
+    }
+
+    /// get next token from lexer
+    token_type get_token()
+    {
+        return last_token = m_lexer.scan();
+    }
+
+    std::string exception_message(const token_type expected, const std::string& context)
+    {
+        std::string error_msg = "syntax error ";
+
+        if (not context.empty())
+        {
+            error_msg += "while parsing " + context + " ";
+        }
+
+        error_msg += "- ";
+
+        if (last_token == token_type::parse_error)
+        {
+            error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
+                         m_lexer.get_token_string() + "'";
+        }
+        else
+        {
+            error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
+        }
+
+        if (expected != token_type::uninitialized)
+        {
+            error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
+        }
+
+        return error_msg;
+    }
+
+  private:
+    /// callback function
+    const parser_callback_t callback = nullptr;
+    /// the type of the last read token
+    token_type last_token = token_type::uninitialized;
+    /// the lexer
+    lexer_t m_lexer;
+    /// whether to throw exceptions in case of errors
+    const bool allow_exceptions = true;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+
+#include <cstddef> // ptrdiff_t
+#include <limits>  // numeric_limits
+
+namespace nlohmann
+{
+namespace detail
+{
+/*
+@brief an iterator for primitive JSON types
+
+This class models an iterator for primitive JSON types (boolean, number,
+string). It's only purpose is to allow the iterator/const_iterator classes
+to "iterate" over primitive values. Internally, the iterator is modeled by
+a `difference_type` variable. Value begin_value (`0`) models the begin,
+end_value (`1`) models past the end.
+*/
+class primitive_iterator_t
+{
+  private:
+    using difference_type = std::ptrdiff_t;
+    static constexpr difference_type begin_value = 0;
+    static constexpr difference_type end_value = begin_value + 1;
+
+    /// iterator as signed integer type
+    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
+
+  public:
+    constexpr difference_type get_value() const noexcept
+    {
+        return m_it;
+    }
+
+    /// set iterator to a defined beginning
+    void set_begin() noexcept
+    {
+        m_it = begin_value;
+    }
+
+    /// set iterator to a defined past the end
+    void set_end() noexcept
+    {
+        m_it = end_value;
+    }
+
+    /// return whether the iterator can be dereferenced
+    constexpr bool is_begin() const noexcept
+    {
+        return m_it == begin_value;
+    }
+
+    /// return whether the iterator is at end
+    constexpr bool is_end() const noexcept
+    {
+        return m_it == end_value;
+    }
+
+    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it == rhs.m_it;
+    }
+
+    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it < rhs.m_it;
+    }
+
+    primitive_iterator_t operator+(difference_type n) noexcept
+    {
+        auto result = *this;
+        result += n;
+        return result;
+    }
+
+    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+    {
+        return lhs.m_it - rhs.m_it;
+    }
+
+    primitive_iterator_t& operator++() noexcept
+    {
+        ++m_it;
+        return *this;
+    }
+
+    primitive_iterator_t const operator++(int) noexcept
+    {
+        auto result = *this;
+        ++m_it;
+        return result;
+    }
+
+    primitive_iterator_t& operator--() noexcept
+    {
+        --m_it;
+        return *this;
+    }
+
+    primitive_iterator_t const operator--(int) noexcept
+    {
+        auto result = *this;
+        --m_it;
+        return result;
+    }
+
+    primitive_iterator_t& operator+=(difference_type n) noexcept
+    {
+        m_it += n;
+        return *this;
+    }
+
+    primitive_iterator_t& operator-=(difference_type n) noexcept
+    {
+        m_it -= n;
+        return *this;
+    }
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/*!
+@brief an iterator value
+
+@note This structure could easily be a union, but MSVC currently does not allow
+unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
+*/
+template<typename BasicJsonType> struct internal_iterator
+{
+    /// iterator for JSON objects
+    typename BasicJsonType::object_t::iterator object_iterator {};
+    /// iterator for JSON arrays
+    typename BasicJsonType::array_t::iterator array_iterator {};
+    /// generic iterator for all other types
+    primitive_iterator_t primitive_iterator {};
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/iter_impl.hpp>
+
+
+#include <ciso646> // not
+#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
+#include <type_traits> // conditional, is_const, remove_const
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+// forward declare, to be able to friend it later on
+template<typename IteratorType> class iteration_proxy;
+template<typename IteratorType> class iteration_proxy_value;
+
+/*!
+@brief a template for a bidirectional iterator for the @ref basic_json class
+This class implements a both iterators (iterator and const_iterator) for the
+@ref basic_json class.
+@note An iterator is called *initialized* when a pointer to a JSON value has
+      been set (e.g., by a constructor or a copy assignment). If the iterator is
+      default-constructed, it is *uninitialized* and most methods are undefined.
+      **The library uses assertions to detect calls on uninitialized iterators.**
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+  The iterator that can be moved can be moved in both directions (i.e.
+  incremented and decremented).
+@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
+       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
+*/
+template<typename BasicJsonType>
+class iter_impl
+{
+    /// allow basic_json to access private members
+    friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
+    friend BasicJsonType;
+    friend iteration_proxy<iter_impl>;
+    friend iteration_proxy_value<iter_impl>;
+
+    using object_t = typename BasicJsonType::object_t;
+    using array_t = typename BasicJsonType::array_t;
+    // make sure BasicJsonType is basic_json or const basic_json
+    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
+                  "iter_impl only accepts (const) basic_json");
+
+  public:
+
+    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
+    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
+    /// A user-defined iterator should provide publicly accessible typedefs named
+    /// iterator_category, value_type, difference_type, pointer, and reference.
+    /// Note that value_type is required to be non-const, even for constant iterators.
+    using iterator_category = std::bidirectional_iterator_tag;
+
+    /// the type of the values when the iterator is dereferenced
+    using value_type = typename BasicJsonType::value_type;
+    /// a type to represent differences between iterators
+    using difference_type = typename BasicJsonType::difference_type;
+    /// defines a pointer to the type iterated over (value_type)
+    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
+          typename BasicJsonType::const_pointer,
+          typename BasicJsonType::pointer>::type;
+    /// defines a reference to the type iterated over (value_type)
+    using reference =
+        typename std::conditional<std::is_const<BasicJsonType>::value,
+        typename BasicJsonType::const_reference,
+        typename BasicJsonType::reference>::type;
+
+    /// default constructor
+    iter_impl() = default;
+
+    /*!
+    @brief constructor for a given JSON instance
+    @param[in] object  pointer to a JSON object for this iterator
+    @pre object != nullptr
+    @post The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    explicit iter_impl(pointer object) noexcept : m_object(object)
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = typename object_t::iterator();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = typename array_t::iterator();
+                break;
+            }
+
+            default:
+            {
+                m_it.primitive_iterator = primitive_iterator_t();
+                break;
+            }
+        }
+    }
+
+    /*!
+    @note The conventional copy constructor and copy assignment are implicitly
+          defined. Combined with the following converting constructor and
+          assignment, they support: (1) copy from iterator to iterator, (2)
+          copy from const iterator to const iterator, and (3) conversion from
+          iterator to const iterator. However conversion from const iterator
+          to iterator is not defined.
+    */
+
+    /*!
+    @brief const copy constructor
+    @param[in] other const iterator to copy from
+    @note This copy constructor had to be defined explicitly to circumvent a bug
+          occurring on msvc v19.0 compiler (VS 2015) debug build. For more
+          information refer to: https://github.com/nlohmann/json/issues/1608
+    */
+    iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
+        : m_object(other.m_object), m_it(other.m_it)
+    {}
+
+    /*!
+    @brief converting assignment
+    @param[in] other const iterator to copy from
+    @return const/non-const iterator
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
+    {
+        m_object = other.m_object;
+        m_it = other.m_it;
+        return *this;
+    }
+
+    /*!
+    @brief converting constructor
+    @param[in] other  non-const iterator to copy from
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+        : m_object(other.m_object), m_it(other.m_it)
+    {}
+
+    /*!
+    @brief converting assignment
+    @param[in] other  non-const iterator to copy from
+    @return const/non-const iterator
+    @note It is not checked whether @a other is initialized.
+    */
+    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+    {
+        m_object = other.m_object;
+        m_it = other.m_it;
+        return *this;
+    }
+
+  private:
+    /*!
+    @brief set the iterator to the first value
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    void set_begin() noexcept
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = m_object->m_value.object->begin();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = m_object->m_value.array->begin();
+                break;
+            }
+
+            case value_t::null:
+            {
+                // set to end so begin()==end() is true: null is empty
+                m_it.primitive_iterator.set_end();
+                break;
+            }
+
+            default:
+            {
+                m_it.primitive_iterator.set_begin();
+                break;
+            }
+        }
+    }
+
+    /*!
+    @brief set the iterator past the last value
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    void set_end() noexcept
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                m_it.object_iterator = m_object->m_value.object->end();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_it.array_iterator = m_object->m_value.array->end();
+                break;
+            }
+
+            default:
+            {
+                m_it.primitive_iterator.set_end();
+                break;
+            }
+        }
+    }
+
+  public:
+    /*!
+    @brief return a reference to the value pointed to by the iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference operator*() const
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                assert(m_it.object_iterator != m_object->m_value.object->end());
+                return m_it.object_iterator->second;
+            }
+
+            case value_t::array:
+            {
+                assert(m_it.array_iterator != m_object->m_value.array->end());
+                return *m_it.array_iterator;
+            }
+
+            case value_t::null:
+                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+                {
+                    return *m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+            }
+        }
+    }
+
+    /*!
+    @brief dereference the iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    pointer operator->() const
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                assert(m_it.object_iterator != m_object->m_value.object->end());
+                return &(m_it.object_iterator->second);
+            }
+
+            case value_t::array:
+            {
+                assert(m_it.array_iterator != m_object->m_value.array->end());
+                return &*m_it.array_iterator;
+            }
+
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+                {
+                    return m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+            }
+        }
+    }
+
+    /*!
+    @brief post-increment (it++)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl const operator++(int)
+    {
+        auto result = *this;
+        ++(*this);
+        return result;
+    }
+
+    /*!
+    @brief pre-increment (++it)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator++()
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                std::advance(m_it.object_iterator, 1);
+                break;
+            }
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, 1);
+                break;
+            }
+
+            default:
+            {
+                ++m_it.primitive_iterator;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief post-decrement (it--)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl const operator--(int)
+    {
+        auto result = *this;
+        --(*this);
+        return result;
+    }
+
+    /*!
+    @brief pre-decrement (--it)
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator--()
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+            {
+                std::advance(m_it.object_iterator, -1);
+                break;
+            }
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, -1);
+                break;
+            }
+
+            default:
+            {
+                --m_it.primitive_iterator;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief  comparison: equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator==(const iter_impl& other) const
+    {
+        // if objects are not the same, the comparison is undefined
+        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
+        }
+
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                return (m_it.object_iterator == other.m_it.object_iterator);
+
+            case value_t::array:
+                return (m_it.array_iterator == other.m_it.array_iterator);
+
+            default:
+                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
+        }
+    }
+
+    /*!
+    @brief  comparison: not equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator!=(const iter_impl& other) const
+    {
+        return not operator==(other);
+    }
+
+    /*!
+    @brief  comparison: smaller
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator<(const iter_impl& other) const
+    {
+        // if objects are not the same, the comparison is undefined
+        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
+        }
+
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
+
+            case value_t::array:
+                return (m_it.array_iterator < other.m_it.array_iterator);
+
+            default:
+                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
+        }
+    }
+
+    /*!
+    @brief  comparison: less than or equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator<=(const iter_impl& other) const
+    {
+        return not other.operator < (*this);
+    }
+
+    /*!
+    @brief  comparison: greater than
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator>(const iter_impl& other) const
+    {
+        return not operator<=(other);
+    }
+
+    /*!
+    @brief  comparison: greater than or equal
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    bool operator>=(const iter_impl& other) const
+    {
+        return not operator<(other);
+    }
+
+    /*!
+    @brief  add to iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator+=(difference_type i)
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
+
+            case value_t::array:
+            {
+                std::advance(m_it.array_iterator, i);
+                break;
+            }
+
+            default:
+            {
+                m_it.primitive_iterator += i;
+                break;
+            }
+        }
+
+        return *this;
+    }
+
+    /*!
+    @brief  subtract from iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl& operator-=(difference_type i)
+    {
+        return operator+=(-i);
+    }
+
+    /*!
+    @brief  add to iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator+(difference_type i) const
+    {
+        auto result = *this;
+        result += i;
+        return result;
+    }
+
+    /*!
+    @brief  addition of distance and iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    friend iter_impl operator+(difference_type i, const iter_impl& it)
+    {
+        auto result = it;
+        result += i;
+        return result;
+    }
+
+    /*!
+    @brief  subtract from iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    iter_impl operator-(difference_type i) const
+    {
+        auto result = *this;
+        result -= i;
+        return result;
+    }
+
+    /*!
+    @brief  return difference
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    difference_type operator-(const iter_impl& other) const
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
+
+            case value_t::array:
+                return m_it.array_iterator - other.m_it.array_iterator;
+
+            default:
+                return m_it.primitive_iterator - other.m_it.primitive_iterator;
+        }
+    }
+
+    /*!
+    @brief  access to successor
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference operator[](difference_type n) const
+    {
+        assert(m_object != nullptr);
+
+        switch (m_object->m_type)
+        {
+            case value_t::object:
+                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
+
+            case value_t::array:
+                return *std::next(m_it.array_iterator, n);
+
+            case value_t::null:
+                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+
+            default:
+            {
+                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
+                {
+                    return *m_object;
+                }
+
+                JSON_THROW(invalid_iterator::create(214, "cannot get value"));
+            }
+        }
+    }
+
+    /*!
+    @brief  return the key of an object iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    const typename object_t::key_type& key() const
+    {
+        assert(m_object != nullptr);
+
+        if (JSON_HEDLEY_LIKELY(m_object->is_object()))
+        {
+            return m_it.object_iterator->first;
+        }
+
+        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
+    }
+
+    /*!
+    @brief  return the value of an iterator
+    @pre The iterator is initialized; i.e. `m_object != nullptr`.
+    */
+    reference value() const
+    {
+        return operator*();
+    }
+
+  private:
+    /// associated JSON instance
+    pointer m_object = nullptr;
+    /// the actual iterator of the associated instance
+    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
+
+
+#include <cstddef> // ptrdiff_t
+#include <iterator> // reverse_iterator
+#include <utility> // declval
+
+namespace nlohmann
+{
+namespace detail
+{
+//////////////////////
+// reverse_iterator //
+//////////////////////
+
+/*!
+@brief a template for a reverse iterator class
+
+@tparam Base the base iterator type to reverse. Valid types are @ref
+iterator (to create @ref reverse_iterator) and @ref const_iterator (to
+create @ref const_reverse_iterator).
+
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+  The iterator that can be moved can be moved in both directions (i.e.
+  incremented and decremented).
+- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
+  It is possible to write to the pointed-to element (only if @a Base is
+  @ref iterator).
+
+@since version 1.0.0
+*/
+template<typename Base>
+class json_reverse_iterator : public std::reverse_iterator<Base>
+{
+  public:
+    using difference_type = std::ptrdiff_t;
+    /// shortcut to the reverse iterator adapter
+    using base_iterator = std::reverse_iterator<Base>;
+    /// the reference type for the pointed-to element
+    using reference = typename Base::reference;
+
+    /// create reverse iterator from iterator
+    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+        : base_iterator(it) {}
+
+    /// create reverse iterator from base class
+    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+
+    /// post-increment (it++)
+    json_reverse_iterator const operator++(int)
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
+    }
+
+    /// pre-increment (++it)
+    json_reverse_iterator& operator++()
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
+    }
+
+    /// post-decrement (it--)
+    json_reverse_iterator const operator--(int)
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
+    }
+
+    /// pre-decrement (--it)
+    json_reverse_iterator& operator--()
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
+    }
+
+    /// add to iterator
+    json_reverse_iterator& operator+=(difference_type i)
+    {
+        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
+    }
+
+    /// add to iterator
+    json_reverse_iterator operator+(difference_type i) const
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
+    }
+
+    /// subtract from iterator
+    json_reverse_iterator operator-(difference_type i) const
+    {
+        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
+    }
+
+    /// return difference
+    difference_type operator-(const json_reverse_iterator& other) const
+    {
+        return base_iterator(*this) - base_iterator(other);
+    }
+
+    /// access to successor
+    reference operator[](difference_type n) const
+    {
+        return *(this->operator+(n));
+    }
+
+    /// return the key of an object iterator
+    auto key() const -> decltype(std::declval<Base>().key())
+    {
+        auto it = --this->base();
+        return it.key();
+    }
+
+    /// return the value of an iterator
+    reference value() const
+    {
+        auto it = --this->base();
+        return it.operator * ();
+    }
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/json_pointer.hpp>
+
+
+#include <algorithm> // all_of
+#include <cassert> // assert
+#include <cctype> // isdigit
+#include <numeric> // accumulate
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+template<typename BasicJsonType>
+class json_pointer
+{
+    // allow basic_json to access private members
+    NLOHMANN_BASIC_JSON_TPL_DECLARATION
+    friend class basic_json;
+
+  public:
+    /*!
+    @brief create JSON pointer
+
+    Create a JSON pointer according to the syntax described in
+    [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
+
+    @param[in] s  string representing the JSON pointer; if omitted, the empty
+                  string is assumed which references the whole JSON value
+
+    @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
+                           not begin with a slash (`/`); see example below
+
+    @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
+    not followed by `0` (representing `~`) or `1` (representing `/`); see
+    example below
+
+    @liveexample{The example shows the construction several valid JSON pointers
+    as well as the exceptional behavior.,json_pointer}
+
+    @since version 2.0.0
+    */
+    explicit json_pointer(const std::string& s = "")
+        : reference_tokens(split(s))
+    {}
+
+    /*!
+    @brief return a string representation of the JSON pointer
+
+    @invariant For each JSON pointer `ptr`, it holds:
+    @code {.cpp}
+    ptr == json_pointer(ptr.to_string());
+    @endcode
+
+    @return a string representation of the JSON pointer
+
+    @liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
+
+    @since version 2.0.0
+    */
+    std::string to_string() const
+    {
+        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
+                               std::string{},
+                               [](const std::string & a, const std::string & b)
+        {
+            return a + "/" + escape(b);
+        });
+    }
+
+    /// @copydoc to_string()
+    operator std::string() const
+    {
+        return to_string();
+    }
+
+    /*!
+    @brief append another JSON pointer at the end of this JSON pointer
+
+    @param[in] ptr  JSON pointer to append
+    @return JSON pointer with @a ptr appended
+
+    @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+    @complexity Linear in the length of @a ptr.
+
+    @sa @ref operator/=(std::string) to append a reference token
+    @sa @ref operator/=(std::size_t) to append an array index
+    @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
+
+    @since version 3.6.0
+    */
+    json_pointer& operator/=(const json_pointer& ptr)
+    {
+        reference_tokens.insert(reference_tokens.end(),
+                                ptr.reference_tokens.begin(),
+                                ptr.reference_tokens.end());
+        return *this;
+    }
+
+    /*!
+    @brief append an unescaped reference token at the end of this JSON pointer
+
+    @param[in] token  reference token to append
+    @return JSON pointer with @a token appended without escaping @a token
+
+    @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+    @complexity Amortized constant.
+
+    @sa @ref operator/=(const json_pointer&) to append a JSON pointer
+    @sa @ref operator/=(std::size_t) to append an array index
+    @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator
+
+    @since version 3.6.0
+    */
+    json_pointer& operator/=(std::string token)
+    {
+        push_back(std::move(token));
+        return *this;
+    }
+
+    /*!
+    @brief append an array index at the end of this JSON pointer
+
+    @param[in] array_index  array index to append
+    @return JSON pointer with @a array_index appended
+
+    @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+    @complexity Amortized constant.
+
+    @sa @ref operator/=(const json_pointer&) to append a JSON pointer
+    @sa @ref operator/=(std::string) to append a reference token
+    @sa @ref operator/(const json_pointer&, std::string) for a binary operator
+
+    @since version 3.6.0
+    */
+    json_pointer& operator/=(std::size_t array_index)
+    {
+        return *this /= std::to_string(array_index);
+    }
+
+    /*!
+    @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
+
+    @param[in] lhs  JSON pointer
+    @param[in] rhs  JSON pointer
+    @return a new JSON pointer with @a rhs appended to @a lhs
+
+    @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+    @complexity Linear in the length of @a lhs and @a rhs.
+
+    @sa @ref operator/=(const json_pointer&) to append a JSON pointer
+
+    @since version 3.6.0
+    */
+    friend json_pointer operator/(const json_pointer& lhs,
+                                  const json_pointer& rhs)
+    {
+        return json_pointer(lhs) /= rhs;
+    }
+
+    /*!
+    @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
+
+    @param[in] ptr  JSON pointer
+    @param[in] token  reference token
+    @return a new JSON pointer with unescaped @a token appended to @a ptr
+
+    @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+    @complexity Linear in the length of @a ptr.
+
+    @sa @ref operator/=(std::string) to append a reference token
+
+    @since version 3.6.0
+    */
+    friend json_pointer operator/(const json_pointer& ptr, std::string token)
+    {
+        return json_pointer(ptr) /= std::move(token);
+    }
+
+    /*!
+    @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
+
+    @param[in] ptr  JSON pointer
+    @param[in] array_index  array index
+    @return a new JSON pointer with @a array_index appended to @a ptr
+
+    @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+    @complexity Linear in the length of @a ptr.
+
+    @sa @ref operator/=(std::size_t) to append an array index
+
+    @since version 3.6.0
+    */
+    friend json_pointer operator/(const json_pointer& ptr, std::size_t array_index)
+    {
+        return json_pointer(ptr) /= array_index;
+    }
+
+    /*!
+    @brief returns the parent of this JSON pointer
+
+    @return parent of this JSON pointer; in case this JSON pointer is the root,
+            the root itself is returned
+
+    @complexity Linear in the length of the JSON pointer.
+
+    @liveexample{The example shows the result of `parent_pointer` for different
+    JSON Pointers.,json_pointer__parent_pointer}
+
+    @since version 3.6.0
+    */
+    json_pointer parent_pointer() const
+    {
+        if (empty())
+        {
+            return *this;
+        }
+
+        json_pointer res = *this;
+        res.pop_back();
+        return res;
+    }
+
+    /*!
+    @brief remove last reference token
+
+    @pre not `empty()`
+
+    @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
+
+    @complexity Constant.
+
+    @throw out_of_range.405 if JSON pointer has no parent
+
+    @since version 3.6.0
+    */
+    void pop_back()
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
+        }
+
+        reference_tokens.pop_back();
+    }
+
+    /*!
+    @brief return last reference token
+
+    @pre not `empty()`
+    @return last reference token
+
+    @liveexample{The example shows the usage of `back`.,json_pointer__back}
+
+    @complexity Constant.
+
+    @throw out_of_range.405 if JSON pointer has no parent
+
+    @since version 3.6.0
+    */
+    const std::string& back() const
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
+        }
+
+        return reference_tokens.back();
+    }
+
+    /*!
+    @brief append an unescaped token at the end of the reference pointer
+
+    @param[in] token  token to add
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows the result of `push_back` for different
+    JSON Pointers.,json_pointer__push_back}
+
+    @since version 3.6.0
+    */
+    void push_back(const std::string& token)
+    {
+        reference_tokens.push_back(token);
+    }
+
+    /// @copydoc push_back(const std::string&)
+    void push_back(std::string&& token)
+    {
+        reference_tokens.push_back(std::move(token));
+    }
+
+    /*!
+    @brief return whether pointer points to the root document
+
+    @return true iff the JSON pointer points to the root document
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example shows the result of `empty` for different JSON
+    Pointers.,json_pointer__empty}
+
+    @since version 3.6.0
+    */
+    bool empty() const noexcept
+    {
+        return reference_tokens.empty();
+    }
+
+  private:
+    /*!
+    @param[in] s  reference token to be converted into an array index
+
+    @return integer representation of @a s
+
+    @throw out_of_range.404 if string @a s could not be converted to an integer
+    */
+    static int array_index(const std::string& s)
+    {
+        std::size_t processed_chars = 0;
+        const int res = std::stoi(s, &processed_chars);
+
+        // check if the string was completely read
+        if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
+        {
+            JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
+        }
+
+        return res;
+    }
+
+    json_pointer top() const
+    {
+        if (JSON_HEDLEY_UNLIKELY(empty()))
+        {
+            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
+        }
+
+        json_pointer result = *this;
+        result.reference_tokens = {reference_tokens[0]};
+        return result;
+    }
+
+    /*!
+    @brief create and return a reference to the pointed to value
+
+    @complexity Linear in the number of reference tokens.
+
+    @throw parse_error.109 if array index is not a number
+    @throw type_error.313 if value cannot be unflattened
+    */
+    BasicJsonType& get_and_create(BasicJsonType& j) const
+    {
+        using size_type = typename BasicJsonType::size_type;
+        auto result = &j;
+
+        // in case no reference tokens exist, return a reference to the JSON value
+        // j which will be overwritten by a primitive value
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (result->type())
+            {
+                case detail::value_t::null:
+                {
+                    if (reference_token == "0")
+                    {
+                        // start a new array if reference token is 0
+                        result = &result->operator[](0);
+                    }
+                    else
+                    {
+                        // start a new object otherwise
+                        result = &result->operator[](reference_token);
+                    }
+                    break;
+                }
+
+                case detail::value_t::object:
+                {
+                    // create an entry in the object
+                    result = &result->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    // create an entry in the array
+                    JSON_TRY
+                    {
+                        result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
+                    }
+                    JSON_CATCH(std::invalid_argument&)
+                    {
+                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+                    }
+                    break;
+                }
+
+                /*
+                The following code is only reached if there exists a reference
+                token _and_ the current value is primitive. In this case, we have
+                an error situation, because primitive values may only occur as
+                single value; that is, with an empty list of reference tokens.
+                */
+                default:
+                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
+            }
+        }
+
+        return *result;
+    }
+
+    /*!
+    @brief return a reference to the pointed to value
+
+    @note This version does not throw if a value is not present, but tries to
+          create nested values instead. For instance, calling this function
+          with pointer `"/this/that"` on a null value is equivalent to calling
+          `operator[]("this").operator[]("that")` on that value, effectively
+          changing the null value to an object.
+
+    @param[in] ptr  a JSON value
+
+    @return reference to the JSON value pointed to by the JSON pointer
+
+    @complexity Linear in the length of the JSON pointer.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
+    {
+        using size_type = typename BasicJsonType::size_type;
+        for (const auto& reference_token : reference_tokens)
+        {
+            // convert null values to arrays or objects before continuing
+            if (ptr->is_null())
+            {
+                // check if reference token is a number
+                const bool nums =
+                    std::all_of(reference_token.begin(), reference_token.end(),
+                                [](const unsigned char x)
+                {
+                    return std::isdigit(x);
+                });
+
+                // change value to array for numbers or "-" or to object otherwise
+                *ptr = (nums or reference_token == "-")
+                       ? detail::value_t::array
+                       : detail::value_t::object;
+            }
+
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // use unchecked object access
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    // error condition (cf. RFC 6901, Sect. 4)
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+                    {
+                        JSON_THROW(detail::parse_error::create(106, 0,
+                                                               "array index '" + reference_token +
+                                                               "' must not begin with '0'"));
+                    }
+
+                    if (reference_token == "-")
+                    {
+                        // explicitly treat "-" as index beyond the end
+                        ptr = &ptr->operator[](ptr->m_value.array->size());
+                    }
+                    else
+                    {
+                        // convert array index to number; unchecked access
+                        JSON_TRY
+                        {
+                            ptr = &ptr->operator[](
+                                static_cast<size_type>(array_index(reference_token)));
+                        }
+                        JSON_CATCH(std::invalid_argument&)
+                        {
+                            JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+                        }
+                    }
+                    break;
+                }
+
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    BasicJsonType& get_checked(BasicJsonType* ptr) const
+    {
+        using size_type = typename BasicJsonType::size_type;
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // note: at performs range check
+                    ptr = &ptr->at(reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        JSON_THROW(detail::out_of_range::create(402,
+                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+                                                                ") is out of range"));
+                    }
+
+                    // error condition (cf. RFC 6901, Sect. 4)
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+                    {
+                        JSON_THROW(detail::parse_error::create(106, 0,
+                                                               "array index '" + reference_token +
+                                                               "' must not begin with '0'"));
+                    }
+
+                    // note: at performs range check
+                    JSON_TRY
+                    {
+                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+                    }
+                    JSON_CATCH(std::invalid_argument&)
+                    {
+                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+                    }
+                    break;
+                }
+
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @brief return a const reference to the pointed to value
+
+    @param[in] ptr  a JSON value
+
+    @return const reference to the JSON value pointed to by the JSON
+    pointer
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
+    {
+        using size_type = typename BasicJsonType::size_type;
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // use unchecked object access
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" cannot be used for const access
+                        JSON_THROW(detail::out_of_range::create(402,
+                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+                                                                ") is out of range"));
+                    }
+
+                    // error condition (cf. RFC 6901, Sect. 4)
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+                    {
+                        JSON_THROW(detail::parse_error::create(106, 0,
+                                                               "array index '" + reference_token +
+                                                               "' must not begin with '0'"));
+                    }
+
+                    // use unchecked array access
+                    JSON_TRY
+                    {
+                        ptr = &ptr->operator[](
+                            static_cast<size_type>(array_index(reference_token)));
+                    }
+                    JSON_CATCH(std::invalid_argument&)
+                    {
+                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+                    }
+                    break;
+                }
+
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+    */
+    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
+    {
+        using size_type = typename BasicJsonType::size_type;
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    // note: at performs range check
+                    ptr = &ptr->at(reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        JSON_THROW(detail::out_of_range::create(402,
+                                                                "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+                                                                ") is out of range"));
+                    }
+
+                    // error condition (cf. RFC 6901, Sect. 4)
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+                    {
+                        JSON_THROW(detail::parse_error::create(106, 0,
+                                                               "array index '" + reference_token +
+                                                               "' must not begin with '0'"));
+                    }
+
+                    // note: at performs range check
+                    JSON_TRY
+                    {
+                        ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
+                    }
+                    JSON_CATCH(std::invalid_argument&)
+                    {
+                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+                    }
+                    break;
+                }
+
+                default:
+                    JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
+            }
+        }
+
+        return *ptr;
+    }
+
+    /*!
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    */
+    bool contains(const BasicJsonType* ptr) const
+    {
+        using size_type = typename BasicJsonType::size_type;
+        for (const auto& reference_token : reference_tokens)
+        {
+            switch (ptr->type())
+            {
+                case detail::value_t::object:
+                {
+                    if (not ptr->contains(reference_token))
+                    {
+                        // we did not find the key in the object
+                        return false;
+                    }
+
+                    ptr = &ptr->operator[](reference_token);
+                    break;
+                }
+
+                case detail::value_t::array:
+                {
+                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+                    {
+                        // "-" always fails the range check
+                        return false;
+                    }
+
+                    // error condition (cf. RFC 6901, Sect. 4)
+                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
+                    {
+                        JSON_THROW(detail::parse_error::create(106, 0,
+                                                               "array index '" + reference_token +
+                                                               "' must not begin with '0'"));
+                    }
+
+                    JSON_TRY
+                    {
+                        const auto idx = static_cast<size_type>(array_index(reference_token));
+                        if (idx >= ptr->size())
+                        {
+                            // index out of range
+                            return false;
+                        }
+
+                        ptr = &ptr->operator[](idx);
+                        break;
+                    }
+                    JSON_CATCH(std::invalid_argument&)
+                    {
+                        JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
+                    }
+                    break;
+                }
+
+                default:
+                {
+                    // we do not expect primitive values if there is still a
+                    // reference token to process
+                    return false;
+                }
+            }
+        }
+
+        // no reference token left means we found a primitive value
+        return true;
+    }
+
+    /*!
+    @brief split the string input to reference tokens
+
+    @note This function is only called by the json_pointer constructor.
+          All exceptions below are documented there.
+
+    @throw parse_error.107  if the pointer is not empty or begins with '/'
+    @throw parse_error.108  if character '~' is not followed by '0' or '1'
+    */
+    static std::vector<std::string> split(const std::string& reference_string)
+    {
+        std::vector<std::string> result;
+
+        // special case: empty reference string -> no reference tokens
+        if (reference_string.empty())
+        {
+            return result;
+        }
+
+        // check if nonempty reference string begins with slash
+        if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
+        {
+            JSON_THROW(detail::parse_error::create(107, 1,
+                                                   "JSON pointer must be empty or begin with '/' - was: '" +
+                                                   reference_string + "'"));
+        }
+
+        // extract the reference tokens:
+        // - slash: position of the last read slash (or end of string)
+        // - start: position after the previous slash
+        for (
+            // search for the first slash after the first character
+            std::size_t slash = reference_string.find_first_of('/', 1),
+            // set the beginning of the first reference token
+            start = 1;
+            // we can stop if start == 0 (if slash == std::string::npos)
+            start != 0;
+            // set the beginning of the next reference token
+            // (will eventually be 0 if slash == std::string::npos)
+            start = (slash == std::string::npos) ? 0 : slash + 1,
+            // find next slash
+            slash = reference_string.find_first_of('/', start))
+        {
+            // use the text between the beginning of the reference token
+            // (start) and the last slash (slash).
+            auto reference_token = reference_string.substr(start, slash - start);
+
+            // check reference tokens are properly escaped
+            for (std::size_t pos = reference_token.find_first_of('~');
+                    pos != std::string::npos;
+                    pos = reference_token.find_first_of('~', pos + 1))
+            {
+                assert(reference_token[pos] == '~');
+
+                // ~ must be followed by 0 or 1
+                if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or
+                                         (reference_token[pos + 1] != '0' and
+                                          reference_token[pos + 1] != '1')))
+                {
+                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
+                }
+            }
+
+            // finally, store the reference token
+            unescape(reference_token);
+            result.push_back(reference_token);
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief replace all occurrences of a substring by another string
+
+    @param[in,out] s  the string to manipulate; changed so that all
+                   occurrences of @a f are replaced with @a t
+    @param[in]     f  the substring to replace with @a t
+    @param[in]     t  the string to replace @a f
+
+    @pre The search string @a f must not be empty. **This precondition is
+    enforced with an assertion.**
+
+    @since version 2.0.0
+    */
+    static void replace_substring(std::string& s, const std::string& f,
+                                  const std::string& t)
+    {
+        assert(not f.empty());
+        for (auto pos = s.find(f);                // find first occurrence of f
+                pos != std::string::npos;         // make sure f was found
+                s.replace(pos, f.size(), t),      // replace with t, and
+                pos = s.find(f, pos + t.size()))  // find next occurrence of f
+        {}
+    }
+
+    /// escape "~" to "~0" and "/" to "~1"
+    static std::string escape(std::string s)
+    {
+        replace_substring(s, "~", "~0");
+        replace_substring(s, "/", "~1");
+        return s;
+    }
+
+    /// unescape "~1" to tilde and "~0" to slash (order is important!)
+    static void unescape(std::string& s)
+    {
+        replace_substring(s, "~1", "/");
+        replace_substring(s, "~0", "~");
+    }
+
+    /*!
+    @param[in] reference_string  the reference string to the current value
+    @param[in] value             the value to consider
+    @param[in,out] result        the result object to insert values to
+
+    @note Empty objects or arrays are flattened to `null`.
+    */
+    static void flatten(const std::string& reference_string,
+                        const BasicJsonType& value,
+                        BasicJsonType& result)
+    {
+        switch (value.type())
+        {
+            case detail::value_t::array:
+            {
+                if (value.m_value.array->empty())
+                {
+                    // flatten empty array as null
+                    result[reference_string] = nullptr;
+                }
+                else
+                {
+                    // iterate array and use index as reference string
+                    for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
+                    {
+                        flatten(reference_string + "/" + std::to_string(i),
+                                value.m_value.array->operator[](i), result);
+                    }
+                }
+                break;
+            }
+
+            case detail::value_t::object:
+            {
+                if (value.m_value.object->empty())
+                {
+                    // flatten empty object as null
+                    result[reference_string] = nullptr;
+                }
+                else
+                {
+                    // iterate object and use keys as reference string
+                    for (const auto& element : *value.m_value.object)
+                    {
+                        flatten(reference_string + "/" + escape(element.first), element.second, result);
+                    }
+                }
+                break;
+            }
+
+            default:
+            {
+                // add primitive value with its reference string
+                result[reference_string] = value;
+                break;
+            }
+        }
+    }
+
+    /*!
+    @param[in] value  flattened JSON
+
+    @return unflattened JSON
+
+    @throw parse_error.109 if array index is not a number
+    @throw type_error.314  if value is not an object
+    @throw type_error.315  if object values are not primitive
+    @throw type_error.313  if value cannot be unflattened
+    */
+    static BasicJsonType
+    unflatten(const BasicJsonType& value)
+    {
+        if (JSON_HEDLEY_UNLIKELY(not value.is_object()))
+        {
+            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
+        }
+
+        BasicJsonType result;
+
+        // iterate the JSON object values
+        for (const auto& element : *value.m_value.object)
+        {
+            if (JSON_HEDLEY_UNLIKELY(not element.second.is_primitive()))
+            {
+                JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
+            }
+
+            // assign value to reference pointed to by JSON pointer; Note that if
+            // the JSON pointer is "" (i.e., points to the whole value), function
+            // get_and_create returns a reference to result itself. An assignment
+            // will then create a primitive value.
+            json_pointer(element.first).get_and_create(result) = element.second;
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief compares two JSON pointers for equality
+
+    @param[in] lhs  JSON pointer to compare
+    @param[in] rhs  JSON pointer to compare
+    @return whether @a lhs is equal to @a rhs
+
+    @complexity Linear in the length of the JSON pointer
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+    */
+    friend bool operator==(json_pointer const& lhs,
+                           json_pointer const& rhs) noexcept
+    {
+        return lhs.reference_tokens == rhs.reference_tokens;
+    }
+
+    /*!
+    @brief compares two JSON pointers for inequality
+
+    @param[in] lhs  JSON pointer to compare
+    @param[in] rhs  JSON pointer to compare
+    @return whether @a lhs is not equal @a rhs
+
+    @complexity Linear in the length of the JSON pointer
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+    */
+    friend bool operator!=(json_pointer const& lhs,
+                           json_pointer const& rhs) noexcept
+    {
+        return not (lhs == rhs);
+    }
+
+    /// the reference tokens
+    std::vector<std::string> reference_tokens;
+};
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/json_ref.hpp>
+
+
+#include <initializer_list>
+#include <utility>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename BasicJsonType>
+class json_ref
+{
+  public:
+    using value_type = BasicJsonType;
+
+    json_ref(value_type&& value)
+        : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
+    {}
+
+    json_ref(const value_type& value)
+        : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
+    {}
+
+    json_ref(std::initializer_list<json_ref> init)
+        : owned_value(init), value_ref(&owned_value), is_rvalue(true)
+    {}
+
+    template <
+        class... Args,
+        enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
+    json_ref(Args && ... args)
+        : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
+          is_rvalue(true) {}
+
+    // class should be movable only
+    json_ref(json_ref&&) = default;
+    json_ref(const json_ref&) = delete;
+    json_ref& operator=(const json_ref&) = delete;
+    json_ref& operator=(json_ref&&) = delete;
+    ~json_ref() = default;
+
+    value_type moved_or_copied() const
+    {
+        if (is_rvalue)
+        {
+            return std::move(*value_ref);
+        }
+        return *value_ref;
+    }
+
+    value_type const& operator*() const
+    {
+        return *static_cast<value_type const*>(value_ref);
+    }
+
+    value_type const* operator->() const
+    {
+        return static_cast<value_type const*>(value_ref);
+    }
+
+  private:
+    mutable value_type owned_value = nullptr;
+    value_type* value_ref = nullptr;
+    const bool is_rvalue;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+
+#include <algorithm> // reverse
+#include <array> // array
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstring> // memcpy
+#include <limits> // numeric_limits
+#include <string> // string
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+
+#include <algorithm> // copy
+#include <cstddef> // size_t
+#include <ios> // streamsize
+#include <iterator> // back_inserter
+#include <memory> // shared_ptr, make_shared
+#include <ostream> // basic_ostream
+#include <string> // basic_string
+#include <vector> // vector
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// abstract output adapter interface
+template<typename CharType> struct output_adapter_protocol
+{
+    virtual void write_character(CharType c) = 0;
+    virtual void write_characters(const CharType* s, std::size_t length) = 0;
+    virtual ~output_adapter_protocol() = default;
+};
+
+/// a type to simplify interfaces
+template<typename CharType>
+using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
+
+/// output adapter for byte vectors
+template<typename CharType>
+class output_vector_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
+        : v(vec)
+    {}
+
+    void write_character(CharType c) override
+    {
+        v.push_back(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        std::copy(s, s + length, std::back_inserter(v));
+    }
+
+  private:
+    std::vector<CharType>& v;
+};
+
+/// output adapter for output streams
+template<typename CharType>
+class output_stream_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
+        : stream(s)
+    {}
+
+    void write_character(CharType c) override
+    {
+        stream.put(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        stream.write(s, static_cast<std::streamsize>(length));
+    }
+
+  private:
+    std::basic_ostream<CharType>& stream;
+};
+
+/// output adapter for basic_string
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_string_adapter : public output_adapter_protocol<CharType>
+{
+  public:
+    explicit output_string_adapter(StringType& s) noexcept
+        : str(s)
+    {}
+
+    void write_character(CharType c) override
+    {
+        str.push_back(c);
+    }
+
+    JSON_HEDLEY_NON_NULL(2)
+    void write_characters(const CharType* s, std::size_t length) override
+    {
+        str.append(s, length);
+    }
+
+  private:
+    StringType& str;
+};
+
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_adapter
+{
+  public:
+    output_adapter(std::vector<CharType>& vec)
+        : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
+
+    output_adapter(std::basic_ostream<CharType>& s)
+        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
+
+    output_adapter(StringType& s)
+        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
+
+    operator output_adapter_t<CharType>()
+    {
+        return oa;
+    }
+
+  private:
+    output_adapter_t<CharType> oa = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// binary writer //
+///////////////////
+
+/*!
+@brief serialization to CBOR and MessagePack values
+*/
+template<typename BasicJsonType, typename CharType>
+class binary_writer
+{
+    using string_t = typename BasicJsonType::string_t;
+
+  public:
+    /*!
+    @brief create a binary writer
+
+    @param[in] adapter  output adapter to write to
+    */
+    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
+    {
+        assert(oa);
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @pre       j.type() == value_t::object
+    */
+    void write_bson(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::object:
+            {
+                write_bson_object(*j.m_value.object);
+                break;
+            }
+
+            default:
+            {
+                JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
+            }
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    */
+    void write_cbor(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                oa->write_character(to_char_type(0xF6));
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                oa->write_character(j.m_value.boolean
+                                    ? to_char_type(0xF5)
+                                    : to_char_type(0xF4));
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // CBOR does not differentiate between positive signed
+                    // integers and unsigned integers. Therefore, we used the
+                    // code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_integer <= 0x17)
+                    {
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x18));
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x19));
+                        write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x1A));
+                        write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                    }
+                    else
+                    {
+                        oa->write_character(to_char_type(0x1B));
+                        write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                    }
+                }
+                else
+                {
+                    // The conversions below encode the sign in the first
+                    // byte, and the value is converted to a positive number.
+                    const auto positive_number = -1 - j.m_value.number_integer;
+                    if (j.m_value.number_integer >= -24)
+                    {
+                        write_number(static_cast<std::uint8_t>(0x20 + positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x38));
+                        write_number(static_cast<std::uint8_t>(positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x39));
+                        write_number(static_cast<std::uint16_t>(positive_number));
+                    }
+                    else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        oa->write_character(to_char_type(0x3A));
+                        write_number(static_cast<std::uint32_t>(positive_number));
+                    }
+                    else
+                    {
+                        oa->write_character(to_char_type(0x3B));
+                        write_number(static_cast<std::uint64_t>(positive_number));
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x18));
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x19));
+                    write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x1A));
+                    write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
+                }
+                else
+                {
+                    oa->write_character(to_char_type(0x1B));
+                    write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
+                write_number(j.m_value.number_float);
+                break;
+            }
+
+            case value_t::string:
+            {
+                // step 1: write control byte and the string length
+                const auto N = j.m_value.string->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x60 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x78));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x79));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x7A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x7B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write the string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                // step 1: write control byte and the array size
+                const auto N = j.m_value.array->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0x80 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x98));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x99));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x9A));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0x9B));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_cbor(el);
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                // step 1: write control byte and the object size
+                const auto N = j.m_value.object->size();
+                if (N <= 0x17)
+                {
+                    write_number(static_cast<std::uint8_t>(0xA0 + N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xB8));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xB9));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xBA));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+                // LCOV_EXCL_START
+                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    oa->write_character(to_char_type(0xBB));
+                    write_number(static_cast<std::uint64_t>(N));
+                }
+                // LCOV_EXCL_STOP
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_cbor(el.first);
+                    write_cbor(el.second);
+                }
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    */
+    void write_msgpack(const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::null: // nil
+            {
+                oa->write_character(to_char_type(0xC0));
+                break;
+            }
+
+            case value_t::boolean: // true and false
+            {
+                oa->write_character(j.m_value.boolean
+                                    ? to_char_type(0xC3)
+                                    : to_char_type(0xC2));
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                if (j.m_value.number_integer >= 0)
+                {
+                    // MessagePack does not differentiate between positive
+                    // signed integers and unsigned integers. Therefore, we used
+                    // the code from the value_t::number_unsigned case here.
+                    if (j.m_value.number_unsigned < 128)
+                    {
+                        // positive fixnum
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                    {
+                        // uint 8
+                        oa->write_character(to_char_type(0xCC));
+                        write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                    {
+                        // uint 16
+                        oa->write_character(to_char_type(0xCD));
+                        write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                    {
+                        // uint 32
+                        oa->write_character(to_char_type(0xCE));
+                        write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                    {
+                        // uint 64
+                        oa->write_character(to_char_type(0xCF));
+                        write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                    }
+                }
+                else
+                {
+                    if (j.m_value.number_integer >= -32)
+                    {
+                        // negative fixnum
+                        write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
+                             j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+                    {
+                        // int 8
+                        oa->write_character(to_char_type(0xD0));
+                        write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
+                             j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+                    {
+                        // int 16
+                        oa->write_character(to_char_type(0xD1));
+                        write_number(static_cast<std::int16_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
+                             j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+                    {
+                        // int 32
+                        oa->write_character(to_char_type(0xD2));
+                        write_number(static_cast<std::int32_t>(j.m_value.number_integer));
+                    }
+                    else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
+                             j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+                    {
+                        // int 64
+                        oa->write_character(to_char_type(0xD3));
+                        write_number(static_cast<std::int64_t>(j.m_value.number_integer));
+                    }
+                }
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned < 128)
+                {
+                    // positive fixnum
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    // uint 8
+                    oa->write_character(to_char_type(0xCC));
+                    write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // uint 16
+                    oa->write_character(to_char_type(0xCD));
+                    write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // uint 32
+                    oa->write_character(to_char_type(0xCE));
+                    write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+                }
+                else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+                {
+                    // uint 64
+                    oa->write_character(to_char_type(0xCF));
+                    write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+                }
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
+                write_number(j.m_value.number_float);
+                break;
+            }
+
+            case value_t::string:
+            {
+                // step 1: write control byte and the string length
+                const auto N = j.m_value.string->size();
+                if (N <= 31)
+                {
+                    // fixstr
+                    write_number(static_cast<std::uint8_t>(0xA0 | N));
+                }
+                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    // str 8
+                    oa->write_character(to_char_type(0xD9));
+                    write_number(static_cast<std::uint8_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // str 16
+                    oa->write_character(to_char_type(0xDA));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // str 32
+                    oa->write_character(to_char_type(0xDB));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write the string
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                // step 1: write control byte and the array size
+                const auto N = j.m_value.array->size();
+                if (N <= 15)
+                {
+                    // fixarray
+                    write_number(static_cast<std::uint8_t>(0x90 | N));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // array 16
+                    oa->write_character(to_char_type(0xDC));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // array 32
+                    oa->write_character(to_char_type(0xDD));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_msgpack(el);
+                }
+                break;
+            }
+
+            case value_t::object:
+            {
+                // step 1: write control byte and the object size
+                const auto N = j.m_value.object->size();
+                if (N <= 15)
+                {
+                    // fixmap
+                    write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
+                }
+                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+                {
+                    // map 16
+                    oa->write_character(to_char_type(0xDE));
+                    write_number(static_cast<std::uint16_t>(N));
+                }
+                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+                {
+                    // map 32
+                    oa->write_character(to_char_type(0xDF));
+                    write_number(static_cast<std::uint32_t>(N));
+                }
+
+                // step 2: write each element
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_msgpack(el.first);
+                    write_msgpack(el.second);
+                }
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @param[in] use_count   whether to use '#' prefixes (optimized format)
+    @param[in] use_type    whether to use '$' prefixes (optimized format)
+    @param[in] add_prefix  whether prefixes need to be used for this value
+    */
+    void write_ubjson(const BasicJsonType& j, const bool use_count,
+                      const bool use_type, const bool add_prefix = true)
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('Z'));
+                }
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(j.m_value.boolean
+                                        ? to_char_type('T')
+                                        : to_char_type('F'));
+                }
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
+                break;
+            }
+
+            case value_t::string:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('S'));
+                }
+                write_number_with_ubjson_prefix(j.m_value.string->size(), true);
+                oa->write_characters(
+                    reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+                    j.m_value.string->size());
+                break;
+            }
+
+            case value_t::array:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('['));
+                }
+
+                bool prefix_required = true;
+                if (use_type and not j.m_value.array->empty())
+                {
+                    assert(use_count);
+                    const CharType first_prefix = ubjson_prefix(j.front());
+                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
+                                                         [this, first_prefix](const BasicJsonType & v)
+                    {
+                        return ubjson_prefix(v) == first_prefix;
+                    });
+
+                    if (same_prefix)
+                    {
+                        prefix_required = false;
+                        oa->write_character(to_char_type('$'));
+                        oa->write_character(first_prefix);
+                    }
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.array->size(), true);
+                }
+
+                for (const auto& el : *j.m_value.array)
+                {
+                    write_ubjson(el, use_count, use_type, prefix_required);
+                }
+
+                if (not use_count)
+                {
+                    oa->write_character(to_char_type(']'));
+                }
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                if (add_prefix)
+                {
+                    oa->write_character(to_char_type('{'));
+                }
+
+                bool prefix_required = true;
+                if (use_type and not j.m_value.object->empty())
+                {
+                    assert(use_count);
+                    const CharType first_prefix = ubjson_prefix(j.front());
+                    const bool same_prefix = std::all_of(j.begin(), j.end(),
+                                                         [this, first_prefix](const BasicJsonType & v)
+                    {
+                        return ubjson_prefix(v) == first_prefix;
+                    });
+
+                    if (same_prefix)
+                    {
+                        prefix_required = false;
+                        oa->write_character(to_char_type('$'));
+                        oa->write_character(first_prefix);
+                    }
+                }
+
+                if (use_count)
+                {
+                    oa->write_character(to_char_type('#'));
+                    write_number_with_ubjson_prefix(j.m_value.object->size(), true);
+                }
+
+                for (const auto& el : *j.m_value.object)
+                {
+                    write_number_with_ubjson_prefix(el.first.size(), true);
+                    oa->write_characters(
+                        reinterpret_cast<const CharType*>(el.first.c_str()),
+                        el.first.size());
+                    write_ubjson(el.second, use_count, use_type, prefix_required);
+                }
+
+                if (not use_count)
+                {
+                    oa->write_character(to_char_type('}'));
+                }
+
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+  private:
+    //////////
+    // BSON //
+    //////////
+
+    /*!
+    @return The size of a BSON document entry header, including the id marker
+            and the entry name size (and its null-terminator).
+    */
+    static std::size_t calc_bson_entry_header_size(const string_t& name)
+    {
+        const auto it = name.find(static_cast<typename string_t::value_type>(0));
+        if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
+        {
+            JSON_THROW(out_of_range::create(409,
+                                            "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
+        }
+
+        return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
+    }
+
+    /*!
+    @brief Writes the given @a element_type and @a name to the output adapter
+    */
+    void write_bson_entry_header(const string_t& name,
+                                 const std::uint8_t element_type)
+    {
+        oa->write_character(to_char_type(element_type)); // boolean
+        oa->write_characters(
+            reinterpret_cast<const CharType*>(name.c_str()),
+            name.size() + 1u);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and boolean value @a value
+    */
+    void write_bson_boolean(const string_t& name,
+                            const bool value)
+    {
+        write_bson_entry_header(name, 0x08);
+        oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and double value @a value
+    */
+    void write_bson_double(const string_t& name,
+                           const double value)
+    {
+        write_bson_entry_header(name, 0x01);
+        write_number<double, true>(value);
+    }
+
+    /*!
+    @return The size of the BSON-encoded string in @a value
+    */
+    static std::size_t calc_bson_string_size(const string_t& value)
+    {
+        return sizeof(std::int32_t) + value.size() + 1ul;
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and string value @a value
+    */
+    void write_bson_string(const string_t& name,
+                           const string_t& value)
+    {
+        write_bson_entry_header(name, 0x02);
+
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
+        oa->write_characters(
+            reinterpret_cast<const CharType*>(value.c_str()),
+            value.size() + 1);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and null value
+    */
+    void write_bson_null(const string_t& name)
+    {
+        write_bson_entry_header(name, 0x0A);
+    }
+
+    /*!
+    @return The size of the BSON-encoded integer @a value
+    */
+    static std::size_t calc_bson_integer_size(const std::int64_t value)
+    {
+        return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
+               ? sizeof(std::int32_t)
+               : sizeof(std::int64_t);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and integer @a value
+    */
+    void write_bson_integer(const string_t& name,
+                            const std::int64_t value)
+    {
+        if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
+        {
+            write_bson_entry_header(name, 0x10); // int32
+            write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
+        }
+        else
+        {
+            write_bson_entry_header(name, 0x12); // int64
+            write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
+        }
+    }
+
+    /*!
+    @return The size of the BSON-encoded unsigned integer in @a j
+    */
+    static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
+    {
+        return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+               ? sizeof(std::int32_t)
+               : sizeof(std::int64_t);
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and unsigned @a value
+    */
+    void write_bson_unsigned(const string_t& name,
+                             const std::uint64_t value)
+    {
+        if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+        {
+            write_bson_entry_header(name, 0x10 /* int32 */);
+            write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
+        }
+        else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+        {
+            write_bson_entry_header(name, 0x12 /* int64 */);
+            write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
+        }
+        else
+        {
+            JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
+        }
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and object @a value
+    */
+    void write_bson_object_entry(const string_t& name,
+                                 const typename BasicJsonType::object_t& value)
+    {
+        write_bson_entry_header(name, 0x03); // object
+        write_bson_object(value);
+    }
+
+    /*!
+    @return The size of the BSON-encoded array @a value
+    */
+    static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
+    {
+        std::size_t array_index = 0ul;
+
+        const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), 0ul, [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
+        {
+            return result + calc_bson_element_size(std::to_string(array_index++), el);
+        });
+
+        return sizeof(std::int32_t) + embedded_document_size + 1ul;
+    }
+
+    /*!
+    @brief Writes a BSON element with key @a name and array @a value
+    */
+    void write_bson_array(const string_t& name,
+                          const typename BasicJsonType::array_t& value)
+    {
+        write_bson_entry_header(name, 0x04); // array
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
+
+        std::size_t array_index = 0ul;
+
+        for (const auto& el : value)
+        {
+            write_bson_element(std::to_string(array_index++), el);
+        }
+
+        oa->write_character(to_char_type(0x00));
+    }
+
+    /*!
+    @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
+    @return The calculated size for the BSON document entry for @a j with the given @a name.
+    */
+    static std::size_t calc_bson_element_size(const string_t& name,
+            const BasicJsonType& j)
+    {
+        const auto header_size = calc_bson_entry_header_size(name);
+        switch (j.type())
+        {
+            case value_t::object:
+                return header_size + calc_bson_object_size(*j.m_value.object);
+
+            case value_t::array:
+                return header_size + calc_bson_array_size(*j.m_value.array);
+
+            case value_t::boolean:
+                return header_size + 1ul;
+
+            case value_t::number_float:
+                return header_size + 8ul;
+
+            case value_t::number_integer:
+                return header_size + calc_bson_integer_size(j.m_value.number_integer);
+
+            case value_t::number_unsigned:
+                return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
+
+            case value_t::string:
+                return header_size + calc_bson_string_size(*j.m_value.string);
+
+            case value_t::null:
+                return header_size + 0ul;
+
+            // LCOV_EXCL_START
+            default:
+                assert(false);
+                return 0ul;
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    /*!
+    @brief Serializes the JSON value @a j to BSON and associates it with the
+           key @a name.
+    @param name The name to associate with the JSON entity @a j within the
+                current BSON document
+    @return The size of the BSON entry
+    */
+    void write_bson_element(const string_t& name,
+                            const BasicJsonType& j)
+    {
+        switch (j.type())
+        {
+            case value_t::object:
+                return write_bson_object_entry(name, *j.m_value.object);
+
+            case value_t::array:
+                return write_bson_array(name, *j.m_value.array);
+
+            case value_t::boolean:
+                return write_bson_boolean(name, j.m_value.boolean);
+
+            case value_t::number_float:
+                return write_bson_double(name, j.m_value.number_float);
+
+            case value_t::number_integer:
+                return write_bson_integer(name, j.m_value.number_integer);
+
+            case value_t::number_unsigned:
+                return write_bson_unsigned(name, j.m_value.number_unsigned);
+
+            case value_t::string:
+                return write_bson_string(name, *j.m_value.string);
+
+            case value_t::null:
+                return write_bson_null(name);
+
+            // LCOV_EXCL_START
+            default:
+                assert(false);
+                return;
+                // LCOV_EXCL_STOP
+        }
+    }
+
+    /*!
+    @brief Calculates the size of the BSON serialization of the given
+           JSON-object @a j.
+    @param[in] j  JSON value to serialize
+    @pre       j.type() == value_t::object
+    */
+    static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
+    {
+        std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
+                                    [](size_t result, const typename BasicJsonType::object_t::value_type & el)
+        {
+            return result += calc_bson_element_size(el.first, el.second);
+        });
+
+        return sizeof(std::int32_t) + document_size + 1ul;
+    }
+
+    /*!
+    @param[in] j  JSON value to serialize
+    @pre       j.type() == value_t::object
+    */
+    void write_bson_object(const typename BasicJsonType::object_t& value)
+    {
+        write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
+
+        for (const auto& el : value)
+        {
+            write_bson_element(el.first, el.second);
+        }
+
+        oa->write_character(to_char_type(0x00));
+    }
+
+    //////////
+    // CBOR //
+    //////////
+
+    static constexpr CharType get_cbor_float_prefix(float /*unused*/)
+    {
+        return to_char_type(0xFA);  // Single-Precision Float
+    }
+
+    static constexpr CharType get_cbor_float_prefix(double /*unused*/)
+    {
+        return to_char_type(0xFB);  // Double-Precision Float
+    }
+
+    /////////////
+    // MsgPack //
+    /////////////
+
+    static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
+    {
+        return to_char_type(0xCA);  // float 32
+    }
+
+    static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
+    {
+        return to_char_type(0xCB);  // float 64
+    }
+
+    ////////////
+    // UBJSON //
+    ////////////
+
+    // UBJSON: write number (floating point)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_floating_point<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix)
+    {
+        if (add_prefix)
+        {
+            oa->write_character(get_ubjson_float_prefix(n));
+        }
+        write_number(n);
+    }
+
+    // UBJSON: write number (unsigned integer)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_unsigned<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix)
+    {
+        if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('i'));  // int8
+            }
+            write_number(static_cast<std::uint8_t>(n));
+        }
+        else if (n <= (std::numeric_limits<std::uint8_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('U'));  // uint8
+            }
+            write_number(static_cast<std::uint8_t>(n));
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('I'));  // int16
+            }
+            write_number(static_cast<std::int16_t>(n));
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('l'));  // int32
+            }
+            write_number(static_cast<std::int32_t>(n));
+        }
+        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('L'));  // int64
+            }
+            write_number(static_cast<std::int64_t>(n));
+        }
+        else
+        {
+            JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
+        }
+    }
+
+    // UBJSON: write number (signed integer)
+    template<typename NumberType, typename std::enable_if<
+                 std::is_signed<NumberType>::value and
+                 not std::is_floating_point<NumberType>::value, int>::type = 0>
+    void write_number_with_ubjson_prefix(const NumberType n,
+                                         const bool add_prefix)
+    {
+        if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('i'));  // int8
+            }
+            write_number(static_cast<std::int8_t>(n));
+        }
+        else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('U'));  // uint8
+            }
+            write_number(static_cast<std::uint8_t>(n));
+        }
+        else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('I'));  // int16
+            }
+            write_number(static_cast<std::int16_t>(n));
+        }
+        else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('l'));  // int32
+            }
+            write_number(static_cast<std::int32_t>(n));
+        }
+        else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
+        {
+            if (add_prefix)
+            {
+                oa->write_character(to_char_type('L'));  // int64
+            }
+            write_number(static_cast<std::int64_t>(n));
+        }
+        // LCOV_EXCL_START
+        else
+        {
+            JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
+        }
+        // LCOV_EXCL_STOP
+    }
+
+    /*!
+    @brief determine the type prefix of container values
+
+    @note This function does not need to be 100% accurate when it comes to
+          integer limits. In case a number exceeds the limits of int64_t,
+          this will be detected by a later call to function
+          write_number_with_ubjson_prefix. Therefore, we return 'L' for any
+          value that does not fit the previous limits.
+    */
+    CharType ubjson_prefix(const BasicJsonType& j) const noexcept
+    {
+        switch (j.type())
+        {
+            case value_t::null:
+                return 'Z';
+
+            case value_t::boolean:
+                return j.m_value.boolean ? 'T' : 'F';
+
+            case value_t::number_integer:
+            {
+                if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+                {
+                    return 'i';
+                }
+                if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+                {
+                    return 'U';
+                }
+                if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+                {
+                    return 'I';
+                }
+                if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+                {
+                    return 'l';
+                }
+                // no check and assume int64_t (see note above)
+                return 'L';
+            }
+
+            case value_t::number_unsigned:
+            {
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+                {
+                    return 'i';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
+                {
+                    return 'U';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+                {
+                    return 'I';
+                }
+                if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+                {
+                    return 'l';
+                }
+                // no check and assume int64_t (see note above)
+                return 'L';
+            }
+
+            case value_t::number_float:
+                return get_ubjson_float_prefix(j.m_value.number_float);
+
+            case value_t::string:
+                return 'S';
+
+            case value_t::array:
+                return '[';
+
+            case value_t::object:
+                return '{';
+
+            default:  // discarded values
+                return 'N';
+        }
+    }
+
+    static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
+    {
+        return 'd';  // float 32
+    }
+
+    static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
+    {
+        return 'D';  // float 64
+    }
+
+    ///////////////////////
+    // Utility functions //
+    ///////////////////////
+
+    /*
+    @brief write a number to output input
+    @param[in] n number of type @a NumberType
+    @tparam NumberType the type of the number
+    @tparam OutputIsLittleEndian Set to true if output data is
+                                 required to be little endian
+
+    @note This function needs to respect the system's endianess, because bytes
+          in CBOR, MessagePack, and UBJSON are stored in network order (big
+          endian) and therefore need reordering on little endian systems.
+    */
+    template<typename NumberType, bool OutputIsLittleEndian = false>
+    void write_number(const NumberType n)
+    {
+        // step 1: write number to array of length NumberType
+        std::array<CharType, sizeof(NumberType)> vec;
+        std::memcpy(vec.data(), &n, sizeof(NumberType));
+
+        // step 2: write array to output (with possible reordering)
+        if (is_little_endian != OutputIsLittleEndian)
+        {
+            // reverse byte order prior to conversion if necessary
+            std::reverse(vec.begin(), vec.end());
+        }
+
+        oa->write_characters(vec.data(), sizeof(NumberType));
+    }
+
+  public:
+    // The following to_char_type functions are implement the conversion
+    // between uint8_t and CharType. In case CharType is not unsigned,
+    // such a conversion is required to allow values greater than 128.
+    // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
+    template < typename C = CharType,
+               enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
+    static constexpr CharType to_char_type(std::uint8_t x) noexcept
+    {
+        return *reinterpret_cast<char*>(&x);
+    }
+
+    template < typename C = CharType,
+               enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
+    static CharType to_char_type(std::uint8_t x) noexcept
+    {
+        static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
+        static_assert(std::is_pod<CharType>::value, "CharType must be POD");
+        CharType result;
+        std::memcpy(&result, &x, sizeof(x));
+        return result;
+    }
+
+    template<typename C = CharType,
+             enable_if_t<std::is_unsigned<C>::value>* = nullptr>
+    static constexpr CharType to_char_type(std::uint8_t x) noexcept
+    {
+        return x;
+    }
+
+    template < typename InputCharType, typename C = CharType,
+               enable_if_t <
+                   std::is_signed<C>::value and
+                   std::is_signed<char>::value and
+                   std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
+                   > * = nullptr >
+    static constexpr CharType to_char_type(InputCharType x) noexcept
+    {
+        return x;
+    }
+
+  private:
+    /// whether we can assume little endianess
+    const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
+
+    /// the output
+    output_adapter_t<CharType> oa = nullptr;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/output/serializer.hpp>
+
+
+#include <algorithm> // reverse, remove, fill, find, none_of
+#include <array> // array
+#include <cassert> // assert
+#include <ciso646> // and, or
+#include <clocale> // localeconv, lconv
+#include <cmath> // labs, isfinite, isnan, signbit
+#include <cstddef> // size_t, ptrdiff_t
+#include <cstdint> // uint8_t
+#include <cstdio> // snprintf
+#include <limits> // numeric_limits
+#include <string> // string
+#include <type_traits> // is_same
+#include <utility> // move
+
+// #include <nlohmann/detail/conversions/to_chars.hpp>
+
+
+#include <array> // array
+#include <cassert> // assert
+#include <ciso646> // or, and, not
+#include <cmath>   // signbit, isfinite
+#include <cstdint> // intN_t, uintN_t
+#include <cstring> // memcpy, memmove
+#include <limits> // numeric_limits
+#include <type_traits> // conditional
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/*!
+@brief implements the Grisu2 algorithm for binary to decimal floating-point
+conversion.
+
+This implementation is a slightly modified version of the reference
+implementation which may be obtained from
+http://florian.loitsch.com/publications (bench.tar.gz).
+
+The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
+
+For a detailed description of the algorithm see:
+
+[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
+    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
+    Language Design and Implementation, PLDI 2010
+[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
+    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
+    Design and Implementation, PLDI 1996
+*/
+namespace dtoa_impl
+{
+
+template <typename Target, typename Source>
+Target reinterpret_bits(const Source source)
+{
+    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
+
+    Target target;
+    std::memcpy(&target, &source, sizeof(Source));
+    return target;
+}
+
+struct diyfp // f * 2^e
+{
+    static constexpr int kPrecision = 64; // = q
+
+    std::uint64_t f = 0;
+    int e = 0;
+
+    constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
+
+    /*!
+    @brief returns x - y
+    @pre x.e == y.e and x.f >= y.f
+    */
+    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
+    {
+        assert(x.e == y.e);
+        assert(x.f >= y.f);
+
+        return {x.f - y.f, x.e};
+    }
+
+    /*!
+    @brief returns x * y
+    @note The result is rounded. (Only the upper q bits are returned.)
+    */
+    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
+    {
+        static_assert(kPrecision == 64, "internal error");
+
+        // Computes:
+        //  f = round((x.f * y.f) / 2^q)
+        //  e = x.e + y.e + q
+
+        // Emulate the 64-bit * 64-bit multiplication:
+        //
+        // p = u * v
+        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
+        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
+        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
+        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
+        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
+        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
+        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
+        //
+        // (Since Q might be larger than 2^32 - 1)
+        //
+        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
+        //
+        // (Q_hi + H does not overflow a 64-bit int)
+        //
+        //   = p_lo + 2^64 p_hi
+
+        const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
+        const std::uint64_t u_hi = x.f >> 32u;
+        const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
+        const std::uint64_t v_hi = y.f >> 32u;
+
+        const std::uint64_t p0 = u_lo * v_lo;
+        const std::uint64_t p1 = u_lo * v_hi;
+        const std::uint64_t p2 = u_hi * v_lo;
+        const std::uint64_t p3 = u_hi * v_hi;
+
+        const std::uint64_t p0_hi = p0 >> 32u;
+        const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
+        const std::uint64_t p1_hi = p1 >> 32u;
+        const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
+        const std::uint64_t p2_hi = p2 >> 32u;
+
+        std::uint64_t Q = p0_hi + p1_lo + p2_lo;
+
+        // The full product might now be computed as
+        //
+        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
+        // p_lo = p0_lo + (Q << 32)
+        //
+        // But in this particular case here, the full p_lo is not required.
+        // Effectively we only need to add the highest bit in p_lo to p_hi (and
+        // Q_hi + 1 does not overflow).
+
+        Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
+
+        const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
+
+        return {h, x.e + y.e + 64};
+    }
+
+    /*!
+    @brief normalize x such that the significand is >= 2^(q-1)
+    @pre x.f != 0
+    */
+    static diyfp normalize(diyfp x) noexcept
+    {
+        assert(x.f != 0);
+
+        while ((x.f >> 63u) == 0)
+        {
+            x.f <<= 1u;
+            x.e--;
+        }
+
+        return x;
+    }
+
+    /*!
+    @brief normalize x such that the result has the exponent E
+    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
+    */
+    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
+    {
+        const int delta = x.e - target_exponent;
+
+        assert(delta >= 0);
+        assert(((x.f << delta) >> delta) == x.f);
+
+        return {x.f << delta, target_exponent};
+    }
+};
+
+struct boundaries
+{
+    diyfp w;
+    diyfp minus;
+    diyfp plus;
+};
+
+/*!
+Compute the (normalized) diyfp representing the input number 'value' and its
+boundaries.
+
+@pre value must be finite and positive
+*/
+template <typename FloatType>
+boundaries compute_boundaries(FloatType value)
+{
+    assert(std::isfinite(value));
+    assert(value > 0);
+
+    // Convert the IEEE representation into a diyfp.
+    //
+    // If v is denormal:
+    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
+    // If v is normalized:
+    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
+
+    static_assert(std::numeric_limits<FloatType>::is_iec559,
+                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
+
+    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
+    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
+    constexpr int      kMinExp    = 1 - kBias;
+    constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
+
+    using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
+
+    const std::uint64_t bits = reinterpret_bits<bits_type>(value);
+    const std::uint64_t E = bits >> (kPrecision - 1);
+    const std::uint64_t F = bits & (kHiddenBit - 1);
+
+    const bool is_denormal = E == 0;
+    const diyfp v = is_denormal
+                    ? diyfp(F, kMinExp)
+                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
+
+    // Compute the boundaries m- and m+ of the floating-point value
+    // v = f * 2^e.
+    //
+    // Determine v- and v+, the floating-point predecessor and successor if v,
+    // respectively.
+    //
+    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
+    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
+    //
+    //      v+ = v + 2^e
+    //
+    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
+    // between m- and m+ round to v, regardless of how the input rounding
+    // algorithm breaks ties.
+    //
+    //      ---+-------------+-------------+-------------+-------------+---  (A)
+    //         v-            m-            v             m+            v+
+    //
+    //      -----------------+------+------+-------------+-------------+---  (B)
+    //                       v-     m-     v             m+            v+
+
+    const bool lower_boundary_is_closer = F == 0 and E > 1;
+    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
+    const diyfp m_minus = lower_boundary_is_closer
+                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
+                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
+
+    // Determine the normalized w+ = m+.
+    const diyfp w_plus = diyfp::normalize(m_plus);
+
+    // Determine w- = m- such that e_(w-) = e_(w+).
+    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
+
+    return {diyfp::normalize(v), w_minus, w_plus};
+}
+
+// Given normalized diyfp w, Grisu needs to find a (normalized) cached
+// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
+// within a certain range [alpha, gamma] (Definition 3.2 from [1])
+//
+//      alpha <= e = e_c + e_w + q <= gamma
+//
+// or
+//
+//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
+//                          <= f_c * f_w * 2^gamma
+//
+// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
+//
+//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
+//
+// or
+//
+//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
+//
+// The choice of (alpha,gamma) determines the size of the table and the form of
+// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
+// in practice:
+//
+// The idea is to cut the number c * w = f * 2^e into two parts, which can be
+// processed independently: An integral part p1, and a fractional part p2:
+//
+//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
+//              = (f div 2^-e) + (f mod 2^-e) * 2^e
+//              = p1 + p2 * 2^e
+//
+// The conversion of p1 into decimal form requires a series of divisions and
+// modulos by (a power of) 10. These operations are faster for 32-bit than for
+// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
+// achieved by choosing
+//
+//      -e >= 32   or   e <= -32 := gamma
+//
+// In order to convert the fractional part
+//
+//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
+//
+// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
+// d[-i] are extracted in order:
+//
+//      (10 * p2) div 2^-e = d[-1]
+//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
+//
+// The multiplication by 10 must not overflow. It is sufficient to choose
+//
+//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
+//
+// Since p2 = f mod 2^-e < 2^-e,
+//
+//      -e <= 60   or   e >= -60 := alpha
+
+constexpr int kAlpha = -60;
+constexpr int kGamma = -32;
+
+struct cached_power // c = f * 2^e ~= 10^k
+{
+    std::uint64_t f;
+    int e;
+    int k;
+};
+
+/*!
+For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
+power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
+satisfies (Definition 3.2 from [1])
+
+     alpha <= e_c + e + q <= gamma.
+*/
+inline cached_power get_cached_power_for_binary_exponent(int e)
+{
+    // Now
+    //
+    //      alpha <= e_c + e + q <= gamma                                    (1)
+    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
+    //
+    // and since the c's are normalized, 2^(q-1) <= f_c,
+    //
+    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
+    //      ==> 2^(alpha - e - 1) <= c
+    //
+    // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
+    //
+    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
+    //        = ceil( (alpha - e - 1) * log_10(2) )
+    //
+    // From the paper:
+    // "In theory the result of the procedure could be wrong since c is rounded,
+    //  and the computation itself is approximated [...]. In practice, however,
+    //  this simple function is sufficient."
+    //
+    // For IEEE double precision floating-point numbers converted into
+    // normalized diyfp's w = f * 2^e, with q = 64,
+    //
+    //      e >= -1022      (min IEEE exponent)
+    //           -52        (p - 1)
+    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
+    //           -11        (normalize the diyfp)
+    //         = -1137
+    //
+    // and
+    //
+    //      e <= +1023      (max IEEE exponent)
+    //           -52        (p - 1)
+    //           -11        (normalize the diyfp)
+    //         = 960
+    //
+    // This binary exponent range [-1137,960] results in a decimal exponent
+    // range [-307,324]. One does not need to store a cached power for each
+    // k in this range. For each such k it suffices to find a cached power
+    // such that the exponent of the product lies in [alpha,gamma].
+    // This implies that the difference of the decimal exponents of adjacent
+    // table entries must be less than or equal to
+    //
+    //      floor( (gamma - alpha) * log_10(2) ) = 8.
+    //
+    // (A smaller distance gamma-alpha would require a larger table.)
+
+    // NB:
+    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
+
+    constexpr int kCachedPowersMinDecExp = -300;
+    constexpr int kCachedPowersDecStep = 8;
+
+    static constexpr std::array<cached_power, 79> kCachedPowers =
+    {
+        {
+            { 0xAB70FE17C79AC6CA, -1060, -300 },
+            { 0xFF77B1FCBEBCDC4F, -1034, -292 },
+            { 0xBE5691EF416BD60C, -1007, -284 },
+            { 0x8DD01FAD907FFC3C,  -980, -276 },
+            { 0xD3515C2831559A83,  -954, -268 },
+            { 0x9D71AC8FADA6C9B5,  -927, -260 },
+            { 0xEA9C227723EE8BCB,  -901, -252 },
+            { 0xAECC49914078536D,  -874, -244 },
+            { 0x823C12795DB6CE57,  -847, -236 },
+            { 0xC21094364DFB5637,  -821, -228 },
+            { 0x9096EA6F3848984F,  -794, -220 },
+            { 0xD77485CB25823AC7,  -768, -212 },
+            { 0xA086CFCD97BF97F4,  -741, -204 },
+            { 0xEF340A98172AACE5,  -715, -196 },
+            { 0xB23867FB2A35B28E,  -688, -188 },
+            { 0x84C8D4DFD2C63F3B,  -661, -180 },
+            { 0xC5DD44271AD3CDBA,  -635, -172 },
+            { 0x936B9FCEBB25C996,  -608, -164 },
+            { 0xDBAC6C247D62A584,  -582, -156 },
+            { 0xA3AB66580D5FDAF6,  -555, -148 },
+            { 0xF3E2F893DEC3F126,  -529, -140 },
+            { 0xB5B5ADA8AAFF80B8,  -502, -132 },
+            { 0x87625F056C7C4A8B,  -475, -124 },
+            { 0xC9BCFF6034C13053,  -449, -116 },
+            { 0x964E858C91BA2655,  -422, -108 },
+            { 0xDFF9772470297EBD,  -396, -100 },
+            { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
+            { 0xF8A95FCF88747D94,  -343,  -84 },
+            { 0xB94470938FA89BCF,  -316,  -76 },
+            { 0x8A08F0F8BF0F156B,  -289,  -68 },
+            { 0xCDB02555653131B6,  -263,  -60 },
+            { 0x993FE2C6D07B7FAC,  -236,  -52 },
+            { 0xE45C10C42A2B3B06,  -210,  -44 },
+            { 0xAA242499697392D3,  -183,  -36 },
+            { 0xFD87B5F28300CA0E,  -157,  -28 },
+            { 0xBCE5086492111AEB,  -130,  -20 },
+            { 0x8CBCCC096F5088CC,  -103,  -12 },
+            { 0xD1B71758E219652C,   -77,   -4 },
+            { 0x9C40000000000000,   -50,    4 },
+            { 0xE8D4A51000000000,   -24,   12 },
+            { 0xAD78EBC5AC620000,     3,   20 },
+            { 0x813F3978F8940984,    30,   28 },
+            { 0xC097CE7BC90715B3,    56,   36 },
+            { 0x8F7E32CE7BEA5C70,    83,   44 },
+            { 0xD5D238A4ABE98068,   109,   52 },
+            { 0x9F4F2726179A2245,   136,   60 },
+            { 0xED63A231D4C4FB27,   162,   68 },
+            { 0xB0DE65388CC8ADA8,   189,   76 },
+            { 0x83C7088E1AAB65DB,   216,   84 },
+            { 0xC45D1DF942711D9A,   242,   92 },
+            { 0x924D692CA61BE758,   269,  100 },
+            { 0xDA01EE641A708DEA,   295,  108 },
+            { 0xA26DA3999AEF774A,   322,  116 },
+            { 0xF209787BB47D6B85,   348,  124 },
+            { 0xB454E4A179DD1877,   375,  132 },
+            { 0x865B86925B9BC5C2,   402,  140 },
+            { 0xC83553C5C8965D3D,   428,  148 },
+            { 0x952AB45CFA97A0B3,   455,  156 },
+            { 0xDE469FBD99A05FE3,   481,  164 },
+            { 0xA59BC234DB398C25,   508,  172 },
+            { 0xF6C69A72A3989F5C,   534,  180 },
+            { 0xB7DCBF5354E9BECE,   561,  188 },
+            { 0x88FCF317F22241E2,   588,  196 },
+            { 0xCC20CE9BD35C78A5,   614,  204 },
+            { 0x98165AF37B2153DF,   641,  212 },
+            { 0xE2A0B5DC971F303A,   667,  220 },
+            { 0xA8D9D1535CE3B396,   694,  228 },
+            { 0xFB9B7CD9A4A7443C,   720,  236 },
+            { 0xBB764C4CA7A44410,   747,  244 },
+            { 0x8BAB8EEFB6409C1A,   774,  252 },
+            { 0xD01FEF10A657842C,   800,  260 },
+            { 0x9B10A4E5E9913129,   827,  268 },
+            { 0xE7109BFBA19C0C9D,   853,  276 },
+            { 0xAC2820D9623BF429,   880,  284 },
+            { 0x80444B5E7AA7CF85,   907,  292 },
+            { 0xBF21E44003ACDD2D,   933,  300 },
+            { 0x8E679C2F5E44FF8F,   960,  308 },
+            { 0xD433179D9C8CB841,   986,  316 },
+            { 0x9E19DB92B4E31BA9,  1013,  324 },
+        }
+    };
+
+    // This computation gives exactly the same results for k as
+    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
+    // for |e| <= 1500, but doesn't require floating-point operations.
+    // NB: log_10(2) ~= 78913 / 2^18
+    assert(e >= -1500);
+    assert(e <=  1500);
+    const int f = kAlpha - e - 1;
+    const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
+
+    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
+    assert(index >= 0);
+    assert(static_cast<std::size_t>(index) < kCachedPowers.size());
+
+    const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
+    assert(kAlpha <= cached.e + e + 64);
+    assert(kGamma >= cached.e + e + 64);
+
+    return cached;
+}
+
+/*!
+For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
+For n == 0, returns 1 and sets pow10 := 1.
+*/
+inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
+{
+    // LCOV_EXCL_START
+    if (n >= 1000000000)
+    {
+        pow10 = 1000000000;
+        return 10;
+    }
+    // LCOV_EXCL_STOP
+    else if (n >= 100000000)
+    {
+        pow10 = 100000000;
+        return  9;
+    }
+    else if (n >= 10000000)
+    {
+        pow10 = 10000000;
+        return  8;
+    }
+    else if (n >= 1000000)
+    {
+        pow10 = 1000000;
+        return  7;
+    }
+    else if (n >= 100000)
+    {
+        pow10 = 100000;
+        return  6;
+    }
+    else if (n >= 10000)
+    {
+        pow10 = 10000;
+        return  5;
+    }
+    else if (n >= 1000)
+    {
+        pow10 = 1000;
+        return  4;
+    }
+    else if (n >= 100)
+    {
+        pow10 = 100;
+        return  3;
+    }
+    else if (n >= 10)
+    {
+        pow10 = 10;
+        return  2;
+    }
+    else
+    {
+        pow10 = 1;
+        return 1;
+    }
+}
+
+inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
+                         std::uint64_t rest, std::uint64_t ten_k)
+{
+    assert(len >= 1);
+    assert(dist <= delta);
+    assert(rest <= delta);
+    assert(ten_k > 0);
+
+    //               <--------------------------- delta ---->
+    //                                  <---- dist --------->
+    // --------------[------------------+-------------------]--------------
+    //               M-                 w                   M+
+    //
+    //                                  ten_k
+    //                                <------>
+    //                                       <---- rest ---->
+    // --------------[------------------+----+--------------]--------------
+    //                                  w    V
+    //                                       = buf * 10^k
+    //
+    // ten_k represents a unit-in-the-last-place in the decimal representation
+    // stored in buf.
+    // Decrement buf by ten_k while this takes buf closer to w.
+
+    // The tests are written in this order to avoid overflow in unsigned
+    // integer arithmetic.
+
+    while (rest < dist
+            and delta - rest >= ten_k
+            and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
+    {
+        assert(buf[len - 1] != '0');
+        buf[len - 1]--;
+        rest += ten_k;
+    }
+}
+
+/*!
+Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
+M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
+*/
+inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
+                             diyfp M_minus, diyfp w, diyfp M_plus)
+{
+    static_assert(kAlpha >= -60, "internal error");
+    static_assert(kGamma <= -32, "internal error");
+
+    // Generates the digits (and the exponent) of a decimal floating-point
+    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
+    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
+    //
+    //               <--------------------------- delta ---->
+    //                                  <---- dist --------->
+    // --------------[------------------+-------------------]--------------
+    //               M-                 w                   M+
+    //
+    // Grisu2 generates the digits of M+ from left to right and stops as soon as
+    // V is in [M-,M+].
+
+    assert(M_plus.e >= kAlpha);
+    assert(M_plus.e <= kGamma);
+
+    std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
+    std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
+
+    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
+    //
+    //      M+ = f * 2^e
+    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
+    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
+    //         = p1 + p2 * 2^e
+
+    const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
+
+    auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
+    std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
+
+    // 1)
+    //
+    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
+
+    assert(p1 > 0);
+
+    std::uint32_t pow10;
+    const int k = find_largest_pow10(p1, pow10);
+
+    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
+    //
+    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
+    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
+    //
+    //      M+ = p1                                             + p2 * 2^e
+    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
+    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
+    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
+    //
+    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
+    //
+    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
+    //
+    // but stop as soon as
+    //
+    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
+
+    int n = k;
+    while (n > 0)
+    {
+        // Invariants:
+        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
+        //      pow10 = 10^(n-1) <= p1 < 10^n
+        //
+        const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
+        const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
+        //
+        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
+        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
+        //
+        assert(d <= 9);
+        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+        //
+        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
+        //
+        p1 = r;
+        n--;
+        //
+        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
+        //      pow10 = 10^n
+        //
+
+        // Now check if enough digits have been generated.
+        // Compute
+        //
+        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
+        //
+        // Note:
+        // Since rest and delta share the same exponent e, it suffices to
+        // compare the significands.
+        const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
+        if (rest <= delta)
+        {
+            // V = buffer * 10^n, with M- <= V <= M+.
+
+            decimal_exponent += n;
+
+            // We may now just stop. But instead look if the buffer could be
+            // decremented to bring V closer to w.
+            //
+            // pow10 = 10^n is now 1 ulp in the decimal representation V.
+            // The rounding procedure works with diyfp's with an implicit
+            // exponent of e.
+            //
+            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
+            //
+            const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
+            grisu2_round(buffer, length, dist, delta, rest, ten_n);
+
+            return;
+        }
+
+        pow10 /= 10;
+        //
+        //      pow10 = 10^(n-1) <= p1 < 10^n
+        // Invariants restored.
+    }
+
+    // 2)
+    //
+    // The digits of the integral part have been generated:
+    //
+    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
+    //         = buffer            + p2 * 2^e
+    //
+    // Now generate the digits of the fractional part p2 * 2^e.
+    //
+    // Note:
+    // No decimal point is generated: the exponent is adjusted instead.
+    //
+    // p2 actually represents the fraction
+    //
+    //      p2 * 2^e
+    //          = p2 / 2^-e
+    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
+    //
+    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
+    //
+    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
+    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
+    //
+    // using
+    //
+    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
+    //                = (                   d) * 2^-e + (                   r)
+    //
+    // or
+    //      10^m * p2 * 2^e = d + r * 2^e
+    //
+    // i.e.
+    //
+    //      M+ = buffer + p2 * 2^e
+    //         = buffer + 10^-m * (d + r * 2^e)
+    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
+    //
+    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
+
+    assert(p2 > delta);
+
+    int m = 0;
+    for (;;)
+    {
+        // Invariant:
+        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
+        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
+        //
+        assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
+        p2 *= 10;
+        const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
+        const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
+        //
+        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
+        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
+        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
+        //
+        assert(d <= 9);
+        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+        //
+        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
+        //
+        p2 = r;
+        m++;
+        //
+        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
+        // Invariant restored.
+
+        // Check if enough digits have been generated.
+        //
+        //      10^-m * p2 * 2^e <= delta * 2^e
+        //              p2 * 2^e <= 10^m * delta * 2^e
+        //                    p2 <= 10^m * delta
+        delta *= 10;
+        dist  *= 10;
+        if (p2 <= delta)
+        {
+            break;
+        }
+    }
+
+    // V = buffer * 10^-m, with M- <= V <= M+.
+
+    decimal_exponent -= m;
+
+    // 1 ulp in the decimal representation is now 10^-m.
+    // Since delta and dist are now scaled by 10^m, we need to do the
+    // same with ulp in order to keep the units in sync.
+    //
+    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
+    //
+    const std::uint64_t ten_m = one.f;
+    grisu2_round(buffer, length, dist, delta, p2, ten_m);
+
+    // By construction this algorithm generates the shortest possible decimal
+    // number (Loitsch, Theorem 6.2) which rounds back to w.
+    // For an input number of precision p, at least
+    //
+    //      N = 1 + ceil(p * log_10(2))
+    //
+    // decimal digits are sufficient to identify all binary floating-point
+    // numbers (Matula, "In-and-Out conversions").
+    // This implies that the algorithm does not produce more than N decimal
+    // digits.
+    //
+    //      N = 17 for p = 53 (IEEE double precision)
+    //      N = 9  for p = 24 (IEEE single precision)
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline void grisu2(char* buf, int& len, int& decimal_exponent,
+                   diyfp m_minus, diyfp v, diyfp m_plus)
+{
+    assert(m_plus.e == m_minus.e);
+    assert(m_plus.e == v.e);
+
+    //  --------(-----------------------+-----------------------)--------    (A)
+    //          m-                      v                       m+
+    //
+    //  --------------------(-----------+-----------------------)--------    (B)
+    //                      m-          v                       m+
+    //
+    // First scale v (and m- and m+) such that the exponent is in the range
+    // [alpha, gamma].
+
+    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
+
+    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
+
+    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
+    const diyfp w       = diyfp::mul(v,       c_minus_k);
+    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
+    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
+
+    //  ----(---+---)---------------(---+---)---------------(---+---)----
+    //          w-                      w                       w+
+    //          = c*m-                  = c*v                   = c*m+
+    //
+    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
+    // w+ are now off by a small amount.
+    // In fact:
+    //
+    //      w - v * 10^k < 1 ulp
+    //
+    // To account for this inaccuracy, add resp. subtract 1 ulp.
+    //
+    //  --------+---[---------------(---+---)---------------]---+--------
+    //          w-  M-                  w                   M+  w+
+    //
+    // Now any number in [M-, M+] (bounds included) will round to w when input,
+    // regardless of how the input rounding algorithm breaks ties.
+    //
+    // And digit_gen generates the shortest possible such number in [M-, M+].
+    // Note that this does not mean that Grisu2 always generates the shortest
+    // possible number in the interval (m-, m+).
+    const diyfp M_minus(w_minus.f + 1, w_minus.e);
+    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
+
+    decimal_exponent = -cached.k; // = -(-k) = k
+
+    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+template <typename FloatType>
+JSON_HEDLEY_NON_NULL(1)
+void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
+{
+    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
+                  "internal error: not enough precision");
+
+    assert(std::isfinite(value));
+    assert(value > 0);
+
+    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
+    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
+    // decimal representations are not exactly "short".
+    //
+    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
+    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
+    // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
+    // does.
+    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
+    // representation using the corresponding std::from_chars function recovers value exactly". That
+    // indicates that single precision floating-point numbers should be recovered using
+    // 'std::strtof'.
+    //
+    // NB: If the neighbors are computed for single-precision numbers, there is a single float
+    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
+    //     value is off by 1 ulp.
+#if 0
+    const boundaries w = compute_boundaries(static_cast<double>(value));
+#else
+    const boundaries w = compute_boundaries(value);
+#endif
+
+    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
+}
+
+/*!
+@brief appends a decimal representation of e to buf
+@return a pointer to the element following the exponent.
+@pre -1000 < e < 1000
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* append_exponent(char* buf, int e)
+{
+    assert(e > -1000);
+    assert(e <  1000);
+
+    if (e < 0)
+    {
+        e = -e;
+        *buf++ = '-';
+    }
+    else
+    {
+        *buf++ = '+';
+    }
+
+    auto k = static_cast<std::uint32_t>(e);
+    if (k < 10)
+    {
+        // Always print at least two digits in the exponent.
+        // This is for compatibility with printf("%g").
+        *buf++ = '0';
+        *buf++ = static_cast<char>('0' + k);
+    }
+    else if (k < 100)
+    {
+        *buf++ = static_cast<char>('0' + k / 10);
+        k %= 10;
+        *buf++ = static_cast<char>('0' + k);
+    }
+    else
+    {
+        *buf++ = static_cast<char>('0' + k / 100);
+        k %= 100;
+        *buf++ = static_cast<char>('0' + k / 10);
+        k %= 10;
+        *buf++ = static_cast<char>('0' + k);
+    }
+
+    return buf;
+}
+
+/*!
+@brief prettify v = buf * 10^decimal_exponent
+
+If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
+notation. Otherwise it will be printed in exponential notation.
+
+@pre min_exp < 0
+@pre max_exp > 0
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* format_buffer(char* buf, int len, int decimal_exponent,
+                           int min_exp, int max_exp)
+{
+    assert(min_exp < 0);
+    assert(max_exp > 0);
+
+    const int k = len;
+    const int n = len + decimal_exponent;
+
+    // v = buf * 10^(n-k)
+    // k is the length of the buffer (number of decimal digits)
+    // n is the position of the decimal point relative to the start of the buffer.
+
+    if (k <= n and n <= max_exp)
+    {
+        // digits[000]
+        // len <= max_exp + 2
+
+        std::memset(buf + k, '0', static_cast<size_t>(n - k));
+        // Make it look like a floating-point number (#362, #378)
+        buf[n + 0] = '.';
+        buf[n + 1] = '0';
+        return buf + (n + 2);
+    }
+
+    if (0 < n and n <= max_exp)
+    {
+        // dig.its
+        // len <= max_digits10 + 1
+
+        assert(k > n);
+
+        std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
+        buf[n] = '.';
+        return buf + (k + 1);
+    }
+
+    if (min_exp < n and n <= 0)
+    {
+        // 0.[000]digits
+        // len <= 2 + (-min_exp - 1) + max_digits10
+
+        std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
+        buf[0] = '0';
+        buf[1] = '.';
+        std::memset(buf + 2, '0', static_cast<size_t>(-n));
+        return buf + (2 + (-n) + k);
+    }
+
+    if (k == 1)
+    {
+        // dE+123
+        // len <= 1 + 5
+
+        buf += 1;
+    }
+    else
+    {
+        // d.igitsE+123
+        // len <= max_digits10 + 1 + 5
+
+        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
+        buf[1] = '.';
+        buf += 1 + k;
+    }
+
+    *buf++ = 'e';
+    return append_exponent(buf, n - 1);
+}
+
+} // namespace dtoa_impl
+
+/*!
+@brief generates a decimal representation of the floating-point number value in [first, last).
+
+The format of the resulting decimal representation is similar to printf's %g
+format. Returns an iterator pointing past-the-end of the decimal representation.
+
+@note The input number must be finite, i.e. NaN's and Inf's are not supported.
+@note The buffer must be large enough.
+@note The result is NOT null-terminated.
+*/
+template <typename FloatType>
+JSON_HEDLEY_NON_NULL(1, 2)
+JSON_HEDLEY_RETURNS_NON_NULL
+char* to_chars(char* first, const char* last, FloatType value)
+{
+    static_cast<void>(last); // maybe unused - fix warning
+    assert(std::isfinite(value));
+
+    // Use signbit(value) instead of (value < 0) since signbit works for -0.
+    if (std::signbit(value))
+    {
+        value = -value;
+        *first++ = '-';
+    }
+
+    if (value == 0) // +-0
+    {
+        *first++ = '0';
+        // Make it look like a floating-point number (#362, #378)
+        *first++ = '.';
+        *first++ = '0';
+        return first;
+    }
+
+    assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
+
+    // Compute v = buffer * 10^decimal_exponent.
+    // The decimal digits are stored in the buffer, which needs to be interpreted
+    // as an unsigned decimal integer.
+    // len is the length of the buffer, i.e. the number of decimal digits.
+    int len = 0;
+    int decimal_exponent = 0;
+    dtoa_impl::grisu2(first, len, decimal_exponent, value);
+
+    assert(len <= std::numeric_limits<FloatType>::max_digits10);
+
+    // Format the buffer like printf("%.*g", prec, value)
+    constexpr int kMinExp = -4;
+    // Use digits10 here to increase compatibility with version 2.
+    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
+
+    assert(last - first >= kMaxExp + 2);
+    assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
+    assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
+
+    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// serialization //
+///////////////////
+
+/// how to treat decoding errors
+enum class error_handler_t
+{
+    strict,  ///< throw a type_error exception in case of invalid UTF-8
+    replace, ///< replace invalid UTF-8 sequences with U+FFFD
+    ignore   ///< ignore invalid UTF-8 sequences
+};
+
+template<typename BasicJsonType>
+class serializer
+{
+    using string_t = typename BasicJsonType::string_t;
+    using number_float_t = typename BasicJsonType::number_float_t;
+    using number_integer_t = typename BasicJsonType::number_integer_t;
+    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+    static constexpr std::uint8_t UTF8_ACCEPT = 0;
+    static constexpr std::uint8_t UTF8_REJECT = 1;
+
+  public:
+    /*!
+    @param[in] s  output stream to serialize to
+    @param[in] ichar  indentation character to use
+    @param[in] error_handler_  how to react on decoding errors
+    */
+    serializer(output_adapter_t<char> s, const char ichar,
+               error_handler_t error_handler_ = error_handler_t::strict)
+        : o(std::move(s))
+        , loc(std::localeconv())
+        , thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
+        , decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
+        , indent_char(ichar)
+        , indent_string(512, indent_char)
+        , error_handler(error_handler_)
+    {}
+
+    // delete because of pointer members
+    serializer(const serializer&) = delete;
+    serializer& operator=(const serializer&) = delete;
+    serializer(serializer&&) = delete;
+    serializer& operator=(serializer&&) = delete;
+    ~serializer() = default;
+
+    /*!
+    @brief internal implementation of the serialization function
+
+    This function is called by the public member function dump and organizes
+    the serialization internally. The indentation level is propagated as
+    additional parameter. In case of arrays and objects, the function is
+    called recursively.
+
+    - strings and object keys are escaped using `escape_string()`
+    - integer numbers are converted implicitly via `operator<<`
+    - floating-point numbers are converted to a string using `"%g"` format
+
+    @param[in] val             value to serialize
+    @param[in] pretty_print    whether the output shall be pretty-printed
+    @param[in] indent_step     the indent level
+    @param[in] current_indent  the current indent level (only used internally)
+    */
+    void dump(const BasicJsonType& val, const bool pretty_print,
+              const bool ensure_ascii,
+              const unsigned int indent_step,
+              const unsigned int current_indent = 0)
+    {
+        switch (val.m_type)
+        {
+            case value_t::object:
+            {
+                if (val.m_value.object->empty())
+                {
+                    o->write_characters("{}", 2);
+                    return;
+                }
+
+                if (pretty_print)
+                {
+                    o->write_characters("{\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    // first n-1 elements
+                    auto i = val.m_value.object->cbegin();
+                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+                    {
+                        o->write_characters(indent_string.c_str(), new_indent);
+                        o->write_character('\"');
+                        dump_escaped(i->first, ensure_ascii);
+                        o->write_characters("\": ", 3);
+                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
+                        o->write_characters(",\n", 2);
+                    }
+
+                    // last element
+                    assert(i != val.m_value.object->cend());
+                    assert(std::next(i) == val.m_value.object->cend());
+                    o->write_characters(indent_string.c_str(), new_indent);
+                    o->write_character('\"');
+                    dump_escaped(i->first, ensure_ascii);
+                    o->write_characters("\": ", 3);
+                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
+
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character('}');
+                }
+                else
+                {
+                    o->write_character('{');
+
+                    // first n-1 elements
+                    auto i = val.m_value.object->cbegin();
+                    for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+                    {
+                        o->write_character('\"');
+                        dump_escaped(i->first, ensure_ascii);
+                        o->write_characters("\":", 2);
+                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
+                        o->write_character(',');
+                    }
+
+                    // last element
+                    assert(i != val.m_value.object->cend());
+                    assert(std::next(i) == val.m_value.object->cend());
+                    o->write_character('\"');
+                    dump_escaped(i->first, ensure_ascii);
+                    o->write_characters("\":", 2);
+                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
+
+                    o->write_character('}');
+                }
+
+                return;
+            }
+
+            case value_t::array:
+            {
+                if (val.m_value.array->empty())
+                {
+                    o->write_characters("[]", 2);
+                    return;
+                }
+
+                if (pretty_print)
+                {
+                    o->write_characters("[\n", 2);
+
+                    // variable to hold indentation for recursive calls
+                    const auto new_indent = current_indent + indent_step;
+                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+                    {
+                        indent_string.resize(indent_string.size() * 2, ' ');
+                    }
+
+                    // first n-1 elements
+                    for (auto i = val.m_value.array->cbegin();
+                            i != val.m_value.array->cend() - 1; ++i)
+                    {
+                        o->write_characters(indent_string.c_str(), new_indent);
+                        dump(*i, true, ensure_ascii, indent_step, new_indent);
+                        o->write_characters(",\n", 2);
+                    }
+
+                    // last element
+                    assert(not val.m_value.array->empty());
+                    o->write_characters(indent_string.c_str(), new_indent);
+                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
+
+                    o->write_character('\n');
+                    o->write_characters(indent_string.c_str(), current_indent);
+                    o->write_character(']');
+                }
+                else
+                {
+                    o->write_character('[');
+
+                    // first n-1 elements
+                    for (auto i = val.m_value.array->cbegin();
+                            i != val.m_value.array->cend() - 1; ++i)
+                    {
+                        dump(*i, false, ensure_ascii, indent_step, current_indent);
+                        o->write_character(',');
+                    }
+
+                    // last element
+                    assert(not val.m_value.array->empty());
+                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
+
+                    o->write_character(']');
+                }
+
+                return;
+            }
+
+            case value_t::string:
+            {
+                o->write_character('\"');
+                dump_escaped(*val.m_value.string, ensure_ascii);
+                o->write_character('\"');
+                return;
+            }
+
+            case value_t::boolean:
+            {
+                if (val.m_value.boolean)
+                {
+                    o->write_characters("true", 4);
+                }
+                else
+                {
+                    o->write_characters("false", 5);
+                }
+                return;
+            }
+
+            case value_t::number_integer:
+            {
+                dump_integer(val.m_value.number_integer);
+                return;
+            }
+
+            case value_t::number_unsigned:
+            {
+                dump_integer(val.m_value.number_unsigned);
+                return;
+            }
+
+            case value_t::number_float:
+            {
+                dump_float(val.m_value.number_float);
+                return;
+            }
+
+            case value_t::discarded:
+            {
+                o->write_characters("<discarded>", 11);
+                return;
+            }
+
+            case value_t::null:
+            {
+                o->write_characters("null", 4);
+                return;
+            }
+
+            default:            // LCOV_EXCL_LINE
+                assert(false);  // LCOV_EXCL_LINE
+        }
+    }
+
+  private:
+    /*!
+    @brief dump escaped string
+
+    Escape a string by replacing certain special characters by a sequence of an
+    escape character (backslash) and another character and other control
+    characters by a sequence of "\u" followed by a four-digit hex
+    representation. The escaped string is written to output stream @a o.
+
+    @param[in] s  the string to escape
+    @param[in] ensure_ascii  whether to escape non-ASCII characters with
+                             \uXXXX sequences
+
+    @complexity Linear in the length of string @a s.
+    */
+    void dump_escaped(const string_t& s, const bool ensure_ascii)
+    {
+        std::uint32_t codepoint;
+        std::uint8_t state = UTF8_ACCEPT;
+        std::size_t bytes = 0;  // number of bytes written to string_buffer
+
+        // number of bytes written at the point of the last valid byte
+        std::size_t bytes_after_last_accept = 0;
+        std::size_t undumped_chars = 0;
+
+        for (std::size_t i = 0; i < s.size(); ++i)
+        {
+            const auto byte = static_cast<uint8_t>(s[i]);
+
+            switch (decode(state, codepoint, byte))
+            {
+                case UTF8_ACCEPT:  // decode found a new code point
+                {
+                    switch (codepoint)
+                    {
+                        case 0x08: // backspace
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'b';
+                            break;
+                        }
+
+                        case 0x09: // horizontal tab
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 't';
+                            break;
+                        }
+
+                        case 0x0A: // newline
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'n';
+                            break;
+                        }
+
+                        case 0x0C: // formfeed
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'f';
+                            break;
+                        }
+
+                        case 0x0D: // carriage return
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = 'r';
+                            break;
+                        }
+
+                        case 0x22: // quotation mark
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = '\"';
+                            break;
+                        }
+
+                        case 0x5C: // reverse solidus
+                        {
+                            string_buffer[bytes++] = '\\';
+                            string_buffer[bytes++] = '\\';
+                            break;
+                        }
+
+                        default:
+                        {
+                            // escape control characters (0x00..0x1F) or, if
+                            // ensure_ascii parameter is used, non-ASCII characters
+                            if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
+                            {
+                                if (codepoint <= 0xFFFF)
+                                {
+                                    (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
+                                                    static_cast<std::uint16_t>(codepoint));
+                                    bytes += 6;
+                                }
+                                else
+                                {
+                                    (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
+                                                    static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
+                                                    static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
+                                    bytes += 12;
+                                }
+                            }
+                            else
+                            {
+                                // copy byte to buffer (all previous bytes
+                                // been copied have in default case above)
+                                string_buffer[bytes++] = s[i];
+                            }
+                            break;
+                        }
+                    }
+
+                    // write buffer and reset index; there must be 13 bytes
+                    // left, as this is the maximal number of bytes to be
+                    // written ("\uxxxx\uxxxx\0") for one code point
+                    if (string_buffer.size() - bytes < 13)
+                    {
+                        o->write_characters(string_buffer.data(), bytes);
+                        bytes = 0;
+                    }
+
+                    // remember the byte position of this accept
+                    bytes_after_last_accept = bytes;
+                    undumped_chars = 0;
+                    break;
+                }
+
+                case UTF8_REJECT:  // decode found invalid UTF-8 byte
+                {
+                    switch (error_handler)
+                    {
+                        case error_handler_t::strict:
+                        {
+                            std::string sn(3, '\0');
+                            (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
+                            JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
+                        }
+
+                        case error_handler_t::ignore:
+                        case error_handler_t::replace:
+                        {
+                            // in case we saw this character the first time, we
+                            // would like to read it again, because the byte
+                            // may be OK for itself, but just not OK for the
+                            // previous sequence
+                            if (undumped_chars > 0)
+                            {
+                                --i;
+                            }
+
+                            // reset length buffer to the last accepted index;
+                            // thus removing/ignoring the invalid characters
+                            bytes = bytes_after_last_accept;
+
+                            if (error_handler == error_handler_t::replace)
+                            {
+                                // add a replacement character
+                                if (ensure_ascii)
+                                {
+                                    string_buffer[bytes++] = '\\';
+                                    string_buffer[bytes++] = 'u';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'f';
+                                    string_buffer[bytes++] = 'd';
+                                }
+                                else
+                                {
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
+                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
+                                }
+
+                                // write buffer and reset index; there must be 13 bytes
+                                // left, as this is the maximal number of bytes to be
+                                // written ("\uxxxx\uxxxx\0") for one code point
+                                if (string_buffer.size() - bytes < 13)
+                                {
+                                    o->write_characters(string_buffer.data(), bytes);
+                                    bytes = 0;
+                                }
+
+                                bytes_after_last_accept = bytes;
+                            }
+
+                            undumped_chars = 0;
+
+                            // continue processing the string
+                            state = UTF8_ACCEPT;
+                            break;
+                        }
+
+                        default:            // LCOV_EXCL_LINE
+                            assert(false);  // LCOV_EXCL_LINE
+                    }
+                    break;
+                }
+
+                default:  // decode found yet incomplete multi-byte code point
+                {
+                    if (not ensure_ascii)
+                    {
+                        // code point will not be escaped - copy byte to buffer
+                        string_buffer[bytes++] = s[i];
+                    }
+                    ++undumped_chars;
+                    break;
+                }
+            }
+        }
+
+        // we finished processing the string
+        if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
+        {
+            // write buffer
+            if (bytes > 0)
+            {
+                o->write_characters(string_buffer.data(), bytes);
+            }
+        }
+        else
+        {
+            // we finish reading, but do not accept: string was incomplete
+            switch (error_handler)
+            {
+                case error_handler_t::strict:
+                {
+                    std::string sn(3, '\0');
+                    (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
+                    JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
+                }
+
+                case error_handler_t::ignore:
+                {
+                    // write all accepted bytes
+                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
+                    break;
+                }
+
+                case error_handler_t::replace:
+                {
+                    // write all accepted bytes
+                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
+                    // add a replacement character
+                    if (ensure_ascii)
+                    {
+                        o->write_characters("\\ufffd", 6);
+                    }
+                    else
+                    {
+                        o->write_characters("\xEF\xBF\xBD", 3);
+                    }
+                    break;
+                }
+
+                default:            // LCOV_EXCL_LINE
+                    assert(false);  // LCOV_EXCL_LINE
+            }
+        }
+    }
+
+    /*!
+    @brief count digits
+
+    Count the number of decimal (base 10) digits for an input unsigned integer.
+
+    @param[in] x  unsigned integer number to count its digits
+    @return    number of decimal digits
+    */
+    inline unsigned int count_digits(number_unsigned_t x) noexcept
+    {
+        unsigned int n_digits = 1;
+        for (;;)
+        {
+            if (x < 10)
+            {
+                return n_digits;
+            }
+            if (x < 100)
+            {
+                return n_digits + 1;
+            }
+            if (x < 1000)
+            {
+                return n_digits + 2;
+            }
+            if (x < 10000)
+            {
+                return n_digits + 3;
+            }
+            x = x / 10000u;
+            n_digits += 4;
+        }
+    }
+
+    /*!
+    @brief dump an integer
+
+    Dump a given integer to output stream @a o. Works internally with
+    @a number_buffer.
+
+    @param[in] x  integer number (signed or unsigned) to dump
+    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
+    */
+    template<typename NumberType, detail::enable_if_t<
+                 std::is_same<NumberType, number_unsigned_t>::value or
+                 std::is_same<NumberType, number_integer_t>::value,
+                 int> = 0>
+    void dump_integer(NumberType x)
+    {
+        static constexpr std::array<std::array<char, 2>, 100> digits_to_99
+        {
+            {
+                {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
+                {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
+                {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
+                {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
+                {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
+                {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
+                {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
+                {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
+                {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
+                {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
+            }
+        };
+
+        // special case for "0"
+        if (x == 0)
+        {
+            o->write_character('0');
+            return;
+        }
+
+        // use a pointer to fill the buffer
+        auto buffer_ptr = number_buffer.begin();
+
+        const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
+        number_unsigned_t abs_value;
+
+        unsigned int n_chars;
+
+        if (is_negative)
+        {
+            *buffer_ptr = '-';
+            abs_value = remove_sign(x);
+
+            // account one more byte for the minus sign
+            n_chars = 1 + count_digits(abs_value);
+        }
+        else
+        {
+            abs_value = static_cast<number_unsigned_t>(x);
+            n_chars = count_digits(abs_value);
+        }
+
+        // spare 1 byte for '\0'
+        assert(n_chars < number_buffer.size() - 1);
+
+        // jump to the end to generate the string from backward
+        // so we later avoid reversing the result
+        buffer_ptr += n_chars;
+
+        // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
+        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
+        while (abs_value >= 100)
+        {
+            const auto digits_index = static_cast<unsigned>((abs_value % 100));
+            abs_value /= 100;
+            *(--buffer_ptr) = digits_to_99[digits_index][1];
+            *(--buffer_ptr) = digits_to_99[digits_index][0];
+        }
+
+        if (abs_value >= 10)
+        {
+            const auto digits_index = static_cast<unsigned>(abs_value);
+            *(--buffer_ptr) = digits_to_99[digits_index][1];
+            *(--buffer_ptr) = digits_to_99[digits_index][0];
+        }
+        else
+        {
+            *(--buffer_ptr) = static_cast<char>('0' + abs_value);
+        }
+
+        o->write_characters(number_buffer.data(), n_chars);
+    }
+
+    /*!
+    @brief dump a floating-point number
+
+    Dump a given floating-point number to output stream @a o. Works internally
+    with @a number_buffer.
+
+    @param[in] x  floating-point number to dump
+    */
+    void dump_float(number_float_t x)
+    {
+        // NaN / inf
+        if (not std::isfinite(x))
+        {
+            o->write_characters("null", 4);
+            return;
+        }
+
+        // If number_float_t is an IEEE-754 single or double precision number,
+        // use the Grisu2 algorithm to produce short numbers which are
+        // guaranteed to round-trip, using strtof and strtod, resp.
+        //
+        // NB: The test below works if <long double> == <double>.
+        static constexpr bool is_ieee_single_or_double
+            = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
+              (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
+
+        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
+    }
+
+    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
+    {
+        char* begin = number_buffer.data();
+        char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
+
+        o->write_characters(begin, static_cast<size_t>(end - begin));
+    }
+
+    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
+    {
+        // get number of digits for a float -> text -> float round-trip
+        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
+
+        // the actual conversion
+        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
+
+        // negative value indicates an error
+        assert(len > 0);
+        // check if buffer was large enough
+        assert(static_cast<std::size_t>(len) < number_buffer.size());
+
+        // erase thousands separator
+        if (thousands_sep != '\0')
+        {
+            const auto end = std::remove(number_buffer.begin(),
+                                         number_buffer.begin() + len, thousands_sep);
+            std::fill(end, number_buffer.end(), '\0');
+            assert((end - number_buffer.begin()) <= len);
+            len = (end - number_buffer.begin());
+        }
+
+        // convert decimal point to '.'
+        if (decimal_point != '\0' and decimal_point != '.')
+        {
+            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
+            if (dec_pos != number_buffer.end())
+            {
+                *dec_pos = '.';
+            }
+        }
+
+        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
+
+        // determine if need to append ".0"
+        const bool value_is_int_like =
+            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
+                         [](char c)
+        {
+            return c == '.' or c == 'e';
+        });
+
+        if (value_is_int_like)
+        {
+            o->write_characters(".0", 2);
+        }
+    }
+
+    /*!
+    @brief check whether a string is UTF-8 encoded
+
+    The function checks each byte of a string whether it is UTF-8 encoded. The
+    result of the check is stored in the @a state parameter. The function must
+    be called initially with state 0 (accept). State 1 means the string must
+    be rejected, because the current byte is not allowed. If the string is
+    completely processed, but the state is non-zero, the string ended
+    prematurely; that is, the last byte indicated more bytes should have
+    followed.
+
+    @param[in,out] state  the state of the decoding
+    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
+    @param[in] byte       next byte to decode
+    @return               new state
+
+    @note The function has been edited: a std::array is used.
+
+    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+    */
+    static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
+    {
+        static const std::array<std::uint8_t, 400> utf8d =
+        {
+            {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
+                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
+                7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
+                8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
+                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
+                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
+                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
+                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
+                1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
+                1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
+                1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
+            }
+        };
+
+        const std::uint8_t type = utf8d[byte];
+
+        codep = (state != UTF8_ACCEPT)
+                ? (byte & 0x3fu) | (codep << 6u)
+                : (0xFFu >> type) & (byte);
+
+        state = utf8d[256u + state * 16u + type];
+        return state;
+    }
+
+    /*
+     * Overload to make the compiler happy while it is instantiating
+     * dump_integer for number_unsigned_t.
+     * Must never be called.
+     */
+    number_unsigned_t remove_sign(number_unsigned_t x)
+    {
+        assert(false); // LCOV_EXCL_LINE
+        return x; // LCOV_EXCL_LINE
+    }
+
+    /*
+     * Helper function for dump_integer
+     *
+     * This function takes a negative signed integer and returns its absolute
+     * value as unsigned integer. The plus/minus shuffling is necessary as we can
+     * not directly remove the sign of an arbitrary signed integer as the
+     * absolute values of INT_MIN and INT_MAX are usually not the same. See
+     * #1708 for details.
+     */
+    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
+    {
+        assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
+        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
+    }
+
+  private:
+    /// the output of the serializer
+    output_adapter_t<char> o = nullptr;
+
+    /// a (hopefully) large enough character buffer
+    std::array<char, 64> number_buffer{{}};
+
+    /// the locale
+    const std::lconv* loc = nullptr;
+    /// the locale's thousand separator character
+    const char thousands_sep = '\0';
+    /// the locale's decimal point character
+    const char decimal_point = '\0';
+
+    /// string buffer
+    std::array<char, 512> string_buffer{{}};
+
+    /// the indentation character
+    const char indent_char;
+    /// the indentation string
+    string_t indent_string;
+
+    /// error_handler how to react on decoding errors
+    const error_handler_t error_handler;
+};
+}  // namespace detail
+}  // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+
+/*!
+@brief a class to store JSON values
+
+@tparam ObjectType type for JSON objects (`std::map` by default; will be used
+in @ref object_t)
+@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
+in @ref array_t)
+@tparam StringType type for JSON strings and object keys (`std::string` by
+default; will be used in @ref string_t)
+@tparam BooleanType type for JSON booleans (`bool` by default; will be used
+in @ref boolean_t)
+@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
+default; will be used in @ref number_integer_t)
+@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
+`uint64_t` by default; will be used in @ref number_unsigned_t)
+@tparam NumberFloatType type for JSON floating-point numbers (`double` by
+default; will be used in @ref number_float_t)
+@tparam AllocatorType type of the allocator to use (`std::allocator` by
+default)
+@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
+and `from_json()` (@ref adl_serializer by default)
+
+@requirement The class satisfies the following concept requirements:
+- Basic
+ - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
+   JSON values can be default constructed. The result will be a JSON null
+   value.
+ - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
+   A JSON value can be constructed from an rvalue argument.
+ - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
+   A JSON value can be copy-constructed from an lvalue expression.
+ - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
+   A JSON value van be assigned from an rvalue argument.
+ - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
+   A JSON value can be copy-assigned from an lvalue expression.
+ - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
+   JSON values can be destructed.
+- Layout
+ - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
+   JSON values have
+   [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+   All non-static data members are private and standard layout types, the
+   class has no virtual functions or (virtual) base classes.
+- Library-wide
+ - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
+   JSON values can be compared with `==`, see @ref
+   operator==(const_reference,const_reference).
+ - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
+   JSON values can be compared with `<`, see @ref
+   operator<(const_reference,const_reference).
+ - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
+   Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
+   other compatible types, using unqualified function call @ref swap().
+ - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
+   JSON values can be compared against `std::nullptr_t` objects which are used
+   to model the `null` value.
+- Container
+ - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
+   JSON values can be used like STL containers and provide iterator access.
+ - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
+   JSON values can be used like STL containers and provide reverse iterator
+   access.
+
+@invariant The member variables @a m_value and @a m_type have the following
+relationship:
+- If `m_type == value_t::object`, then `m_value.object != nullptr`.
+- If `m_type == value_t::array`, then `m_value.array != nullptr`.
+- If `m_type == value_t::string`, then `m_value.string != nullptr`.
+The invariants are checked by member function assert_invariant().
+
+@internal
+@note ObjectType trick from http://stackoverflow.com/a/9860911
+@endinternal
+
+@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
+Format](http://rfc7159.net/rfc7159)
+
+@since version 1.0.0
+
+@nosubgrouping
+*/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+class basic_json
+{
+  private:
+    template<detail::value_t> friend struct detail::external_constructor;
+    friend ::nlohmann::json_pointer<basic_json>;
+    friend ::nlohmann::detail::parser<basic_json>;
+    friend ::nlohmann::detail::serializer<basic_json>;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::iter_impl;
+    template<typename BasicJsonType, typename CharType>
+    friend class ::nlohmann::detail::binary_writer;
+    template<typename BasicJsonType, typename SAX>
+    friend class ::nlohmann::detail::binary_reader;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::json_sax_dom_parser;
+    template<typename BasicJsonType>
+    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
+
+    /// workaround type for MSVC
+    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
+
+    // convenience aliases for types residing in namespace detail;
+    using lexer = ::nlohmann::detail::lexer<basic_json>;
+    using parser = ::nlohmann::detail::parser<basic_json>;
+
+    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
+    template<typename BasicJsonType>
+    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
+    template<typename BasicJsonType>
+    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
+    template<typename Iterator>
+    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
+    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
+
+    template<typename CharType>
+    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
+
+    using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
+    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
+
+    using serializer = ::nlohmann::detail::serializer<basic_json>;
+
+  public:
+    using value_t = detail::value_t;
+    /// JSON Pointer, see @ref nlohmann::json_pointer
+    using json_pointer = ::nlohmann::json_pointer<basic_json>;
+    template<typename T, typename SFINAE>
+    using json_serializer = JSONSerializer<T, SFINAE>;
+    /// how to treat decoding errors
+    using error_handler_t = detail::error_handler_t;
+    /// helper type for initializer lists of basic_json values
+    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+
+    using input_format_t = detail::input_format_t;
+    /// SAX interface type, see @ref nlohmann::json_sax
+    using json_sax_t = json_sax<basic_json>;
+
+    ////////////////
+    // exceptions //
+    ////////////////
+
+    /// @name exceptions
+    /// Classes to implement user-defined exceptions.
+    /// @{
+
+    /// @copydoc detail::exception
+    using exception = detail::exception;
+    /// @copydoc detail::parse_error
+    using parse_error = detail::parse_error;
+    /// @copydoc detail::invalid_iterator
+    using invalid_iterator = detail::invalid_iterator;
+    /// @copydoc detail::type_error
+    using type_error = detail::type_error;
+    /// @copydoc detail::out_of_range
+    using out_of_range = detail::out_of_range;
+    /// @copydoc detail::other_error
+    using other_error = detail::other_error;
+
+    /// @}
+
+
+    /////////////////////
+    // container types //
+    /////////////////////
+
+    /// @name container types
+    /// The canonic container types to use @ref basic_json like any other STL
+    /// container.
+    /// @{
+
+    /// the type of elements in a basic_json container
+    using value_type = basic_json;
+
+    /// the type of an element reference
+    using reference = value_type&;
+    /// the type of an element const reference
+    using const_reference = const value_type&;
+
+    /// a type to represent differences between iterators
+    using difference_type = std::ptrdiff_t;
+    /// a type to represent container sizes
+    using size_type = std::size_t;
+
+    /// the allocator type
+    using allocator_type = AllocatorType<basic_json>;
+
+    /// the type of an element pointer
+    using pointer = typename std::allocator_traits<allocator_type>::pointer;
+    /// the type of an element const pointer
+    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+
+    /// an iterator for a basic_json container
+    using iterator = iter_impl<basic_json>;
+    /// a const iterator for a basic_json container
+    using const_iterator = iter_impl<const basic_json>;
+    /// a reverse iterator for a basic_json container
+    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
+    /// a const reverse iterator for a basic_json container
+    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
+
+    /// @}
+
+
+    /*!
+    @brief returns the allocator associated with the container
+    */
+    static allocator_type get_allocator()
+    {
+        return allocator_type();
+    }
+
+    /*!
+    @brief returns version information on the library
+
+    This function returns a JSON object with information about the library,
+    including the version number and information on the platform and compiler.
+
+    @return JSON object holding version information
+    key         | description
+    ----------- | ---------------
+    `compiler`  | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
+    `copyright` | The copyright line for the library as string.
+    `name`      | The name of the library as string.
+    `platform`  | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
+    `url`       | The URL of the project as string.
+    `version`   | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
+
+    @liveexample{The following code shows an example output of the `meta()`
+    function.,meta}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @complexity Constant.
+
+    @since 2.1.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json meta()
+    {
+        basic_json result;
+
+        result["copyright"] = "(C) 2013-2017 Niels Lohmann";
+        result["name"] = "JSON for Modern C++";
+        result["url"] = "https://github.com/nlohmann/json";
+        result["version"]["string"] =
+            std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
+            std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
+            std::to_string(NLOHMANN_JSON_VERSION_PATCH);
+        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
+        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
+        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
+
+#ifdef _WIN32
+        result["platform"] = "win32";
+#elif defined __linux__
+        result["platform"] = "linux";
+#elif defined __APPLE__
+        result["platform"] = "apple";
+#elif defined __unix__
+        result["platform"] = "unix";
+#else
+        result["platform"] = "unknown";
+#endif
+
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
+#elif defined(__clang__)
+        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
+#elif defined(__GNUC__) || defined(__GNUG__)
+        result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
+#elif defined(__HP_cc) || defined(__HP_aCC)
+        result["compiler"] = "hp"
+#elif defined(__IBMCPP__)
+        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
+#elif defined(_MSC_VER)
+        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
+#elif defined(__PGI)
+        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
+#elif defined(__SUNPRO_CC)
+        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
+#else
+        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
+#endif
+
+#ifdef __cplusplus
+        result["compiler"]["c++"] = std::to_string(__cplusplus);
+#else
+        result["compiler"]["c++"] = "unknown";
+#endif
+        return result;
+    }
+
+
+    ///////////////////////////
+    // JSON value data types //
+    ///////////////////////////
+
+    /// @name JSON value data types
+    /// The data types to store a JSON value. These types are derived from
+    /// the template arguments passed to class @ref basic_json.
+    /// @{
+
+#if defined(JSON_HAS_CPP_14)
+    // Use transparent comparator if possible, combined with perfect forwarding
+    // on find() and count() calls prevents unnecessary string construction.
+    using object_comparator_t = std::less<>;
+#else
+    using object_comparator_t = std::less<StringType>;
+#endif
+
+    /*!
+    @brief a type for an object
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
+    > An object is an unordered collection of zero or more name/value pairs,
+    > where a name is a string and a value is a string, number, boolean, null,
+    > object, or array.
+
+    To store objects in C++, a type is defined by the template parameters
+    described below.
+
+    @tparam ObjectType  the container to store objects (e.g., `std::map` or
+    `std::unordered_map`)
+    @tparam StringType the type of the keys or names (e.g., `std::string`).
+    The comparison function `std::less<StringType>` is used to order elements
+    inside the container.
+    @tparam AllocatorType the allocator to use for objects (e.g.,
+    `std::allocator`)
+
+    #### Default type
+
+    With the default values for @a ObjectType (`std::map`), @a StringType
+    (`std::string`), and @a AllocatorType (`std::allocator`), the default
+    value for @a object_t is:
+
+    @code {.cpp}
+    std::map<
+      std::string, // key_type
+      basic_json, // value_type
+      std::less<std::string>, // key_compare
+      std::allocator<std::pair<const std::string, basic_json>> // allocator_type
+    >
+    @endcode
+
+    #### Behavior
+
+    The choice of @a object_t influences the behavior of the JSON class. With
+    the default type, objects have the following behavior:
+
+    - When all names are unique, objects will be interoperable in the sense
+      that all software implementations receiving that object will agree on
+      the name-value mappings.
+    - When the names within an object are not unique, it is unspecified which
+      one of the values for a given key will be chosen. For instance,
+      `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
+      `{"key": 2}`.
+    - Internally, name/value pairs are stored in lexicographical order of the
+      names. Objects will also be serialized (see @ref dump) in this order.
+      For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
+      and serialized as `{"a": 2, "b": 1}`.
+    - When comparing objects, the order of the name/value pairs is irrelevant.
+      This makes objects interoperable in the sense that they will not be
+      affected by these differences. For instance, `{"b": 1, "a": 2}` and
+      `{"a": 2, "b": 1}` will be treated as equal.
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+    > An implementation may set limits on the maximum depth of nesting.
+
+    In this class, the object's limit of nesting is not explicitly constrained.
+    However, a maximum depth of nesting may be introduced by the compiler or
+    runtime environment. A theoretical limit can be queried by calling the
+    @ref max_size function of a JSON object.
+
+    #### Storage
+
+    Objects are stored as pointers in a @ref basic_json type. That is, for any
+    access to object values, a pointer of type `object_t*` must be
+    dereferenced.
+
+    @sa @ref array_t -- type for an array value
+
+    @since version 1.0.0
+
+    @note The order name/value pairs are added to the object is *not*
+    preserved by the library. Therefore, iterating an object may return
+    name/value pairs in a different order than they were originally stored. In
+    fact, keys will be traversed in alphabetical order as `std::map` with
+    `std::less` is used by default. Please note this behavior conforms to [RFC
+    7159](http://rfc7159.net/rfc7159), because any order implements the
+    specified "unordered" nature of JSON objects.
+    */
+    using object_t = ObjectType<StringType,
+          basic_json,
+          object_comparator_t,
+          AllocatorType<std::pair<const StringType,
+          basic_json>>>;
+
+    /*!
+    @brief a type for an array
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
+    > An array is an ordered sequence of zero or more values.
+
+    To store objects in C++, a type is defined by the template parameters
+    explained below.
+
+    @tparam ArrayType  container type to store arrays (e.g., `std::vector` or
+    `std::list`)
+    @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
+
+    #### Default type
+
+    With the default values for @a ArrayType (`std::vector`) and @a
+    AllocatorType (`std::allocator`), the default value for @a array_t is:
+
+    @code {.cpp}
+    std::vector<
+      basic_json, // value_type
+      std::allocator<basic_json> // allocator_type
+    >
+    @endcode
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+    > An implementation may set limits on the maximum depth of nesting.
+
+    In this class, the array's limit of nesting is not explicitly constrained.
+    However, a maximum depth of nesting may be introduced by the compiler or
+    runtime environment. A theoretical limit can be queried by calling the
+    @ref max_size function of a JSON array.
+
+    #### Storage
+
+    Arrays are stored as pointers in a @ref basic_json type. That is, for any
+    access to array values, a pointer of type `array_t*` must be dereferenced.
+
+    @sa @ref object_t -- type for an object value
+
+    @since version 1.0.0
+    */
+    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
+
+    /*!
+    @brief a type for a string
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
+    > A string is a sequence of zero or more Unicode characters.
+
+    To store objects in C++, a type is defined by the template parameter
+    described below. Unicode values are split by the JSON class into
+    byte-sized characters during deserialization.
+
+    @tparam StringType  the container to store strings (e.g., `std::string`).
+    Note this container is used for keys/names in objects, see @ref object_t.
+
+    #### Default type
+
+    With the default values for @a StringType (`std::string`), the default
+    value for @a string_t is:
+
+    @code {.cpp}
+    std::string
+    @endcode
+
+    #### Encoding
+
+    Strings are stored in UTF-8 encoding. Therefore, functions like
+    `std::string::size()` or `std::string::length()` return the number of
+    bytes in the string rather than the number of characters or glyphs.
+
+    #### String comparison
+
+    [RFC 7159](http://rfc7159.net/rfc7159) states:
+    > Software implementations are typically required to test names of object
+    > members for equality. Implementations that transform the textual
+    > representation into sequences of Unicode code units and then perform the
+    > comparison numerically, code unit by code unit, are interoperable in the
+    > sense that implementations will agree in all cases on equality or
+    > inequality of two strings. For example, implementations that compare
+    > strings with escaped characters unconverted may incorrectly find that
+    > `"a\\b"` and `"a\u005Cb"` are not equal.
+
+    This implementation is interoperable as it does compare strings code unit
+    by code unit.
+
+    #### Storage
+
+    String values are stored as pointers in a @ref basic_json type. That is,
+    for any access to string values, a pointer of type `string_t*` must be
+    dereferenced.
+
+    @since version 1.0.0
+    */
+    using string_t = StringType;
+
+    /*!
+    @brief a type for a boolean
+
+    [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
+    type which differentiates the two literals `true` and `false`.
+
+    To store objects in C++, a type is defined by the template parameter @a
+    BooleanType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a BooleanType (`bool`), the default value for
+    @a boolean_t is:
+
+    @code {.cpp}
+    bool
+    @endcode
+
+    #### Storage
+
+    Boolean values are stored directly inside a @ref basic_json type.
+
+    @since version 1.0.0
+    */
+    using boolean_t = BooleanType;
+
+    /*!
+    @brief a type for a number (integer)
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+    > The representation of numbers is similar to that used in most
+    > programming languages. A number is represented in base 10 using decimal
+    > digits. It contains an integer component that may be prefixed with an
+    > optional minus sign, which may be followed by a fraction part and/or an
+    > exponent part. Leading zeros are not allowed. (...) Numeric values that
+    > cannot be represented in the grammar below (such as Infinity and NaN)
+    > are not permitted.
+
+    This description includes both integer and floating-point numbers.
+    However, C++ allows more precise storage if it is known whether the number
+    is a signed integer, an unsigned integer or a floating-point number.
+    Therefore, three different types, @ref number_integer_t, @ref
+    number_unsigned_t and @ref number_float_t are used.
+
+    To store integer numbers in C++, a type is defined by the template
+    parameter @a NumberIntegerType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberIntegerType (`int64_t`), the default
+    value for @a number_integer_t is:
+
+    @code {.cpp}
+    int64_t
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in integer literals lead to an interpretation as octal
+      number. Internally, the value will be stored as decimal number. For
+      instance, the C++ integer literal `010` will be serialized to `8`.
+      During deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+    > An implementation may set limits on the range and precision of numbers.
+
+    When the default type is used, the maximal integer number that can be
+    stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
+    that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
+    that are out of range will yield over/underflow when used in a
+    constructor. During deserialization, too large or small integer numbers
+    will be automatically be stored as @ref number_unsigned_t or @ref
+    number_float_t.
+
+    [RFC 7159](http://rfc7159.net/rfc7159) further states:
+    > Note that when such software is used, numbers that are integers and are
+    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+    > that implementations will agree exactly on their numeric values.
+
+    As this range is a subrange of the exactly supported range [INT64_MIN,
+    INT64_MAX], this class's integer type is interoperable.
+
+    #### Storage
+
+    Integer number values are stored directly inside a @ref basic_json type.
+
+    @sa @ref number_float_t -- type for number values (floating-point)
+
+    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
+    @since version 1.0.0
+    */
+    using number_integer_t = NumberIntegerType;
+
+    /*!
+    @brief a type for a number (unsigned)
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+    > The representation of numbers is similar to that used in most
+    > programming languages. A number is represented in base 10 using decimal
+    > digits. It contains an integer component that may be prefixed with an
+    > optional minus sign, which may be followed by a fraction part and/or an
+    > exponent part. Leading zeros are not allowed. (...) Numeric values that
+    > cannot be represented in the grammar below (such as Infinity and NaN)
+    > are not permitted.
+
+    This description includes both integer and floating-point numbers.
+    However, C++ allows more precise storage if it is known whether the number
+    is a signed integer, an unsigned integer or a floating-point number.
+    Therefore, three different types, @ref number_integer_t, @ref
+    number_unsigned_t and @ref number_float_t are used.
+
+    To store unsigned integer numbers in C++, a type is defined by the
+    template parameter @a NumberUnsignedType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberUnsignedType (`uint64_t`), the
+    default value for @a number_unsigned_t is:
+
+    @code {.cpp}
+    uint64_t
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in integer literals lead to an interpretation as octal
+      number. Internally, the value will be stored as decimal number. For
+      instance, the C++ integer literal `010` will be serialized to `8`.
+      During deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+    > An implementation may set limits on the range and precision of numbers.
+
+    When the default type is used, the maximal integer number that can be
+    stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
+    number that can be stored is `0`. Integer numbers that are out of range
+    will yield over/underflow when used in a constructor. During
+    deserialization, too large or small integer numbers will be automatically
+    be stored as @ref number_integer_t or @ref number_float_t.
+
+    [RFC 7159](http://rfc7159.net/rfc7159) further states:
+    > Note that when such software is used, numbers that are integers and are
+    > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+    > that implementations will agree exactly on their numeric values.
+
+    As this range is a subrange (when considered in conjunction with the
+    number_integer_t type) of the exactly supported range [0, UINT64_MAX],
+    this class's integer type is interoperable.
+
+    #### Storage
+
+    Integer number values are stored directly inside a @ref basic_json type.
+
+    @sa @ref number_float_t -- type for number values (floating-point)
+    @sa @ref number_integer_t -- type for number values (integer)
+
+    @since version 2.0.0
+    */
+    using number_unsigned_t = NumberUnsignedType;
+
+    /*!
+    @brief a type for a number (floating-point)
+
+    [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+    > The representation of numbers is similar to that used in most
+    > programming languages. A number is represented in base 10 using decimal
+    > digits. It contains an integer component that may be prefixed with an
+    > optional minus sign, which may be followed by a fraction part and/or an
+    > exponent part. Leading zeros are not allowed. (...) Numeric values that
+    > cannot be represented in the grammar below (such as Infinity and NaN)
+    > are not permitted.
+
+    This description includes both integer and floating-point numbers.
+    However, C++ allows more precise storage if it is known whether the number
+    is a signed integer, an unsigned integer or a floating-point number.
+    Therefore, three different types, @ref number_integer_t, @ref
+    number_unsigned_t and @ref number_float_t are used.
+
+    To store floating-point numbers in C++, a type is defined by the template
+    parameter @a NumberFloatType which chooses the type to use.
+
+    #### Default type
+
+    With the default values for @a NumberFloatType (`double`), the default
+    value for @a number_float_t is:
+
+    @code {.cpp}
+    double
+    @endcode
+
+    #### Default behavior
+
+    - The restrictions about leading zeros is not enforced in C++. Instead,
+      leading zeros in floating-point literals will be ignored. Internally,
+      the value will be stored as decimal number. For instance, the C++
+      floating-point literal `01.2` will be serialized to `1.2`. During
+      deserialization, leading zeros yield an error.
+    - Not-a-number (NaN) values will be serialized to `null`.
+
+    #### Limits
+
+    [RFC 7159](http://rfc7159.net/rfc7159) states:
+    > This specification allows implementations to set limits on the range and
+    > precision of numbers accepted. Since software that implements IEEE
+    > 754-2008 binary64 (double precision) numbers is generally available and
+    > widely used, good interoperability can be achieved by implementations
+    > that expect no more precision or range than these provide, in the sense
+    > that implementations will approximate JSON numbers within the expected
+    > precision.
+
+    This implementation does exactly follow this approach, as it uses double
+    precision floating-point numbers. Note values smaller than
+    `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
+    will be stored as NaN internally and be serialized to `null`.
+
+    #### Storage
+
+    Floating-point number values are stored directly inside a @ref basic_json
+    type.
+
+    @sa @ref number_integer_t -- type for number values (integer)
+
+    @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
+    @since version 1.0.0
+    */
+    using number_float_t = NumberFloatType;
+
+    /// @}
+
+  private:
+
+    /// helper for exception-safe object creation
+    template<typename T, typename... Args>
+    JSON_HEDLEY_RETURNS_NON_NULL
+    static T* create(Args&& ... args)
+    {
+        AllocatorType<T> alloc;
+        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
+
+        auto deleter = [&](T * object)
+        {
+            AllocatorTraits::deallocate(alloc, object, 1);
+        };
+        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
+        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
+        assert(object != nullptr);
+        return object.release();
+    }
+
+    ////////////////////////
+    // JSON value storage //
+    ////////////////////////
+
+    /*!
+    @brief a JSON value
+
+    The actual storage for a JSON value of the @ref basic_json class. This
+    union combines the different storage types for the JSON value types
+    defined in @ref value_t.
+
+    JSON type | value_t type    | used type
+    --------- | --------------- | ------------------------
+    object    | object          | pointer to @ref object_t
+    array     | array           | pointer to @ref array_t
+    string    | string          | pointer to @ref string_t
+    boolean   | boolean         | @ref boolean_t
+    number    | number_integer  | @ref number_integer_t
+    number    | number_unsigned | @ref number_unsigned_t
+    number    | number_float    | @ref number_float_t
+    null      | null            | *no value is stored*
+
+    @note Variable-length types (objects, arrays, and strings) are stored as
+    pointers. The size of the union should not exceed 64 bits if the default
+    value types are used.
+
+    @since version 1.0.0
+    */
+    union json_value
+    {
+        /// object (stored with pointer to save storage)
+        object_t* object;
+        /// array (stored with pointer to save storage)
+        array_t* array;
+        /// string (stored with pointer to save storage)
+        string_t* string;
+        /// boolean
+        boolean_t boolean;
+        /// number (integer)
+        number_integer_t number_integer;
+        /// number (unsigned integer)
+        number_unsigned_t number_unsigned;
+        /// number (floating-point)
+        number_float_t number_float;
+
+        /// default constructor (for null values)
+        json_value() = default;
+        /// constructor for booleans
+        json_value(boolean_t v) noexcept : boolean(v) {}
+        /// constructor for numbers (integer)
+        json_value(number_integer_t v) noexcept : number_integer(v) {}
+        /// constructor for numbers (unsigned)
+        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
+        /// constructor for numbers (floating-point)
+        json_value(number_float_t v) noexcept : number_float(v) {}
+        /// constructor for empty values of a given type
+        json_value(value_t t)
+        {
+            switch (t)
+            {
+                case value_t::object:
+                {
+                    object = create<object_t>();
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    array = create<array_t>();
+                    break;
+                }
+
+                case value_t::string:
+                {
+                    string = create<string_t>("");
+                    break;
+                }
+
+                case value_t::boolean:
+                {
+                    boolean = boolean_t(false);
+                    break;
+                }
+
+                case value_t::number_integer:
+                {
+                    number_integer = number_integer_t(0);
+                    break;
+                }
+
+                case value_t::number_unsigned:
+                {
+                    number_unsigned = number_unsigned_t(0);
+                    break;
+                }
+
+                case value_t::number_float:
+                {
+                    number_float = number_float_t(0.0);
+                    break;
+                }
+
+                case value_t::null:
+                {
+                    object = nullptr;  // silence warning, see #821
+                    break;
+                }
+
+                default:
+                {
+                    object = nullptr;  // silence warning, see #821
+                    if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
+                    {
+                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.7.3")); // LCOV_EXCL_LINE
+                    }
+                    break;
+                }
+            }
+        }
+
+        /// constructor for strings
+        json_value(const string_t& value)
+        {
+            string = create<string_t>(value);
+        }
+
+        /// constructor for rvalue strings
+        json_value(string_t&& value)
+        {
+            string = create<string_t>(std::move(value));
+        }
+
+        /// constructor for objects
+        json_value(const object_t& value)
+        {
+            object = create<object_t>(value);
+        }
+
+        /// constructor for rvalue objects
+        json_value(object_t&& value)
+        {
+            object = create<object_t>(std::move(value));
+        }
+
+        /// constructor for arrays
+        json_value(const array_t& value)
+        {
+            array = create<array_t>(value);
+        }
+
+        /// constructor for rvalue arrays
+        json_value(array_t&& value)
+        {
+            array = create<array_t>(std::move(value));
+        }
+
+        void destroy(value_t t) noexcept
+        {
+            // flatten the current json_value to a heap-allocated stack
+            std::vector<basic_json> stack;
+
+            // move the top-level items to stack
+            if (t == value_t::array)
+            {
+                stack.reserve(array->size());
+                std::move(array->begin(), array->end(), std::back_inserter(stack));
+            }
+            else if (t == value_t::object)
+            {
+                stack.reserve(object->size());
+                for (auto&& it : *object)
+                {
+                    stack.push_back(std::move(it.second));
+                }
+            }
+
+            while (not stack.empty())
+            {
+                // move the last item to local variable to be processed
+                basic_json current_item(std::move(stack.back()));
+                stack.pop_back();
+
+                // if current_item is array/object, move
+                // its children to the stack to be processed later
+                if (current_item.is_array())
+                {
+                    std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(),
+                              std::back_inserter(stack));
+
+                    current_item.m_value.array->clear();
+                }
+                else if (current_item.is_object())
+                {
+                    for (auto&& it : *current_item.m_value.object)
+                    {
+                        stack.push_back(std::move(it.second));
+                    }
+
+                    current_item.m_value.object->clear();
+                }
+
+                // it's now safe that current_item get destructed
+                // since it doesn't have any children
+            }
+
+            switch (t)
+            {
+                case value_t::object:
+                {
+                    AllocatorType<object_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    AllocatorType<array_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
+                    break;
+                }
+
+                case value_t::string:
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
+                    break;
+                }
+
+                default:
+                {
+                    break;
+                }
+            }
+        }
+    };
+
+    /*!
+    @brief checks the class invariants
+
+    This function asserts the class invariants. It needs to be called at the
+    end of every constructor to make sure that created objects respect the
+    invariant. Furthermore, it has to be called each time the type of a JSON
+    value is changed, because the invariant expresses a relationship between
+    @a m_type and @a m_value.
+    */
+    void assert_invariant() const noexcept
+    {
+        assert(m_type != value_t::object or m_value.object != nullptr);
+        assert(m_type != value_t::array or m_value.array != nullptr);
+        assert(m_type != value_t::string or m_value.string != nullptr);
+    }
+
+  public:
+    //////////////////////////
+    // JSON parser callback //
+    //////////////////////////
+
+    /*!
+    @brief parser event types
+
+    The parser callback distinguishes the following events:
+    - `object_start`: the parser read `{` and started to process a JSON object
+    - `key`: the parser read a key of a value in an object
+    - `object_end`: the parser read `}` and finished processing a JSON object
+    - `array_start`: the parser read `[` and started to process a JSON array
+    - `array_end`: the parser read `]` and finished processing a JSON array
+    - `value`: the parser finished reading a JSON value
+
+    @image html callback_events.png "Example when certain parse events are triggered"
+
+    @sa @ref parser_callback_t for more information and examples
+    */
+    using parse_event_t = typename parser::parse_event_t;
+
+    /*!
+    @brief per-element parser callback type
+
+    With a parser callback function, the result of parsing a JSON text can be
+    influenced. When passed to @ref parse, it is called on certain events
+    (passed as @ref parse_event_t via parameter @a event) with a set recursion
+    depth @a depth and context JSON value @a parsed. The return value of the
+    callback function is a boolean indicating whether the element that emitted
+    the callback shall be kept or not.
+
+    We distinguish six scenarios (determined by the event type) in which the
+    callback function can be called. The following table describes the values
+    of the parameters @a depth, @a event, and @a parsed.
+
+    parameter @a event | description | parameter @a depth | parameter @a parsed
+    ------------------ | ----------- | ------------------ | -------------------
+    parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
+    parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
+    parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
+    parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
+    parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
+    parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
+
+    @image html callback_events.png "Example when certain parse events are triggered"
+
+    Discarding a value (i.e., returning `false`) has different effects
+    depending on the context in which function was called:
+
+    - Discarded values in structured types are skipped. That is, the parser
+      will behave as if the discarded value was never read.
+    - In case a value outside a structured type is skipped, it is replaced
+      with `null`. This case happens if the top-level element is skipped.
+
+    @param[in] depth  the depth of the recursion during parsing
+
+    @param[in] event  an event of type parse_event_t indicating the context in
+    the callback function has been called
+
+    @param[in,out] parsed  the current intermediate parse result; note that
+    writing to this value has no effect for parse_event_t::key events
+
+    @return Whether the JSON value which called the function during parsing
+    should be kept (`true`) or not (`false`). In the latter case, it is either
+    skipped completely or replaced by an empty discarded object.
+
+    @sa @ref parse for examples
+
+    @since version 1.0.0
+    */
+    using parser_callback_t = typename parser::parser_callback_t;
+
+    //////////////////
+    // constructors //
+    //////////////////
+
+    /// @name constructors and destructors
+    /// Constructors of class @ref basic_json, copy/move constructor, copy
+    /// assignment, static functions creating objects, and the destructor.
+    /// @{
+
+    /*!
+    @brief create an empty value with a given type
+
+    Create an empty JSON value with a given type. The value will be default
+    initialized with an empty value which depends on the type:
+
+    Value type  | initial value
+    ----------- | -------------
+    null        | `null`
+    boolean     | `false`
+    string      | `""`
+    number      | `0`
+    object      | `{}`
+    array       | `[]`
+
+    @param[in] v  the type of the value to create
+
+    @complexity Constant.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows the constructor for different @ref
+    value_t values,basic_json__value_t}
+
+    @sa @ref clear() -- restores the postcondition of this constructor
+
+    @since version 1.0.0
+    */
+    basic_json(const value_t v)
+        : m_type(v), m_value(v)
+    {
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a null object
+
+    Create a `null` JSON value. It either takes a null pointer as parameter
+    (explicitly creating `null`) or no parameter (implicitly creating `null`).
+    The passed null pointer itself is not read -- it is only used to choose
+    the right constructor.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this constructor never throws
+    exceptions.
+
+    @liveexample{The following code shows the constructor with and without a
+    null pointer parameter.,basic_json__nullptr_t}
+
+    @since version 1.0.0
+    */
+    basic_json(std::nullptr_t = nullptr) noexcept
+        : basic_json(value_t::null)
+    {
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a JSON value
+
+    This is a "catch all" constructor for all compatible JSON types; that is,
+    types for which a `to_json()` method exists. The constructor forwards the
+    parameter @a val to that method (to `json_serializer<U>::to_json` method
+    with `U = uncvref_t<CompatibleType>`, to be exact).
+
+    Template type @a CompatibleType includes, but is not limited to, the
+    following types:
+    - **arrays**: @ref array_t and all kinds of compatible containers such as
+      `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
+      `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
+      `std::multiset`, and `std::unordered_multiset` with a `value_type` from
+      which a @ref basic_json value can be constructed.
+    - **objects**: @ref object_t and all kinds of compatible associative
+      containers such as `std::map`, `std::unordered_map`, `std::multimap`,
+      and `std::unordered_multimap` with a `key_type` compatible to
+      @ref string_t and a `value_type` from which a @ref basic_json value can
+      be constructed.
+    - **strings**: @ref string_t, string literals, and all compatible string
+      containers can be used.
+    - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
+      @ref number_float_t, and all convertible number types such as `int`,
+      `size_t`, `int64_t`, `float` or `double` can be used.
+    - **boolean**: @ref boolean_t / `bool` can be used.
+
+    See the examples below.
+
+    @tparam CompatibleType a type such that:
+    - @a CompatibleType is not derived from `std::istream`,
+    - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
+         constructors),
+    - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
+    - @a CompatibleType is not a @ref basic_json nested type (e.g.,
+         @ref json_pointer, @ref iterator, etc ...)
+    - @ref @ref json_serializer<U> has a
+         `to_json(basic_json_t&, CompatibleType&&)` method
+
+    @tparam U = `uncvref_t<CompatibleType>`
+
+    @param[in] val the value to be forwarded to the respective constructor
+
+    @complexity Usually linear in the size of the passed @a val, also
+                depending on the implementation of the called `to_json()`
+                method.
+
+    @exceptionsafety Depends on the called constructor. For types directly
+    supported by the library (i.e., all types for which no `to_json()` function
+    was provided), strong guarantee holds: if an exception is thrown, there are
+    no changes to any JSON value.
+
+    @liveexample{The following code shows the constructor with several
+    compatible types.,basic_json__CompatibleType}
+
+    @since version 2.1.0
+    */
+    template <typename CompatibleType,
+              typename U = detail::uncvref_t<CompatibleType>,
+              detail::enable_if_t<
+                  not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
+    basic_json(CompatibleType && val) noexcept(noexcept(
+                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
+                                           std::forward<CompatibleType>(val))))
+    {
+        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a JSON value from an existing one
+
+    This is a constructor for existing @ref basic_json types.
+    It does not hijack copy/move constructors, since the parameter has different
+    template arguments than the current ones.
+
+    The constructor tries to convert the internal @ref m_value of the parameter.
+
+    @tparam BasicJsonType a type such that:
+    - @a BasicJsonType is a @ref basic_json type.
+    - @a BasicJsonType has different template arguments than @ref basic_json_t.
+
+    @param[in] val the @ref basic_json value to be converted.
+
+    @complexity Usually linear in the size of the passed @a val, also
+                depending on the implementation of the called `to_json()`
+                method.
+
+    @exceptionsafety Depends on the called constructor. For types directly
+    supported by the library (i.e., all types for which no `to_json()` function
+    was provided), strong guarantee holds: if an exception is thrown, there are
+    no changes to any JSON value.
+
+    @since version 3.2.0
+    */
+    template <typename BasicJsonType,
+              detail::enable_if_t<
+                  detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
+    basic_json(const BasicJsonType& val)
+    {
+        using other_boolean_t = typename BasicJsonType::boolean_t;
+        using other_number_float_t = typename BasicJsonType::number_float_t;
+        using other_number_integer_t = typename BasicJsonType::number_integer_t;
+        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+        using other_string_t = typename BasicJsonType::string_t;
+        using other_object_t = typename BasicJsonType::object_t;
+        using other_array_t = typename BasicJsonType::array_t;
+
+        switch (val.type())
+        {
+            case value_t::boolean:
+                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
+                break;
+            case value_t::number_float:
+                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
+                break;
+            case value_t::number_integer:
+                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
+                break;
+            case value_t::number_unsigned:
+                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
+                break;
+            case value_t::string:
+                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
+                break;
+            case value_t::object:
+                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
+                break;
+            case value_t::array:
+                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
+                break;
+            case value_t::null:
+                *this = nullptr;
+                break;
+            case value_t::discarded:
+                m_type = value_t::discarded;
+                break;
+            default:            // LCOV_EXCL_LINE
+                assert(false);  // LCOV_EXCL_LINE
+        }
+        assert_invariant();
+    }
+
+    /*!
+    @brief create a container (array or object) from an initializer list
+
+    Creates a JSON value of type array or object from the passed initializer
+    list @a init. In case @a type_deduction is `true` (default), the type of
+    the JSON value to be created is deducted from the initializer list @a init
+    according to the following rules:
+
+    1. If the list is empty, an empty JSON object value `{}` is created.
+    2. If the list consists of pairs whose first element is a string, a JSON
+       object value is created where the first elements of the pairs are
+       treated as keys and the second elements are as values.
+    3. In all other cases, an array is created.
+
+    The rules aim to create the best fit between a C++ initializer list and
+    JSON values. The rationale is as follows:
+
+    1. The empty initializer list is written as `{}` which is exactly an empty
+       JSON object.
+    2. C++ has no way of describing mapped types other than to list a list of
+       pairs. As JSON requires that keys must be of type string, rule 2 is the
+       weakest constraint one can pose on initializer lists to interpret them
+       as an object.
+    3. In all other cases, the initializer list could not be interpreted as
+       JSON object type, so interpreting it as JSON array type is safe.
+
+    With the rules described above, the following JSON values cannot be
+    expressed by an initializer list:
+
+    - the empty array (`[]`): use @ref array(initializer_list_t)
+      with an empty initializer list in this case
+    - arrays whose elements satisfy rule 2: use @ref
+      array(initializer_list_t) with the same initializer list
+      in this case
+
+    @note When used without parentheses around an empty initializer list, @ref
+    basic_json() is called instead of this function, yielding the JSON null
+    value.
+
+    @param[in] init  initializer list with JSON values
+
+    @param[in] type_deduction internal parameter; when set to `true`, the type
+    of the JSON value is deducted from the initializer list @a init; when set
+    to `false`, the type provided via @a manual_type is forced. This mode is
+    used by the functions @ref array(initializer_list_t) and
+    @ref object(initializer_list_t).
+
+    @param[in] manual_type internal parameter; when @a type_deduction is set
+    to `false`, the created JSON value will use the provided type (only @ref
+    value_t::array and @ref value_t::object are valid); when @a type_deduction
+    is set to `true`, this parameter has no effect
+
+    @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
+    `value_t::object`, but @a init contains an element which is not a pair
+    whose first element is a string. In this case, the constructor could not
+    create an object. If @a type_deduction would have be `true`, an array
+    would have been created. See @ref object(initializer_list_t)
+    for an example.
+
+    @complexity Linear in the size of the initializer list @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The example below shows how JSON values are created from
+    initializer lists.,basic_json__list_init_t}
+
+    @sa @ref array(initializer_list_t) -- create a JSON array
+    value from an initializer list
+    @sa @ref object(initializer_list_t) -- create a JSON object
+    value from an initializer list
+
+    @since version 1.0.0
+    */
+    basic_json(initializer_list_t init,
+               bool type_deduction = true,
+               value_t manual_type = value_t::array)
+    {
+        // check if each element is an array with two elements whose first
+        // element is a string
+        bool is_an_object = std::all_of(init.begin(), init.end(),
+                                        [](const detail::json_ref<basic_json>& element_ref)
+        {
+            return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string();
+        });
+
+        // adjust type if type deduction is not wanted
+        if (not type_deduction)
+        {
+            // if array is wanted, do not create an object though possible
+            if (manual_type == value_t::array)
+            {
+                is_an_object = false;
+            }
+
+            // if object is wanted but impossible, throw an exception
+            if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object and not is_an_object))
+            {
+                JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
+            }
+        }
+
+        if (is_an_object)
+        {
+            // the initializer list is a list of pairs -> create object
+            m_type = value_t::object;
+            m_value = value_t::object;
+
+            std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
+            {
+                auto element = element_ref.moved_or_copied();
+                m_value.object->emplace(
+                    std::move(*((*element.m_value.array)[0].m_value.string)),
+                    std::move((*element.m_value.array)[1]));
+            });
+        }
+        else
+        {
+            // the initializer list describes an array -> create array
+            m_type = value_t::array;
+            m_value.array = create<array_t>(init.begin(), init.end());
+        }
+
+        assert_invariant();
+    }
+
+    /*!
+    @brief explicitly create an array from an initializer list
+
+    Creates a JSON array value from a given initializer list. That is, given a
+    list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
+    initializer list is empty, the empty array `[]` is created.
+
+    @note This function is only needed to express two edge cases that cannot
+    be realized with the initializer list constructor (@ref
+    basic_json(initializer_list_t, bool, value_t)). These cases
+    are:
+    1. creating an array whose elements are all pairs whose first element is a
+    string -- in this case, the initializer list constructor would create an
+    object, taking the first elements as keys
+    2. creating an empty array -- passing the empty initializer list to the
+    initializer list constructor yields an empty object
+
+    @param[in] init  initializer list with JSON values to create an array from
+    (optional)
+
+    @return JSON array value
+
+    @complexity Linear in the size of @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows an example for the `array`
+    function.,array}
+
+    @sa @ref basic_json(initializer_list_t, bool, value_t) --
+    create a JSON value from an initializer list
+    @sa @ref object(initializer_list_t) -- create a JSON object
+    value from an initializer list
+
+    @since version 1.0.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json array(initializer_list_t init = {})
+    {
+        return basic_json(init, false, value_t::array);
+    }
+
+    /*!
+    @brief explicitly create an object from an initializer list
+
+    Creates a JSON object value from a given initializer list. The initializer
+    lists elements must be pairs, and their first elements must be strings. If
+    the initializer list is empty, the empty object `{}` is created.
+
+    @note This function is only added for symmetry reasons. In contrast to the
+    related function @ref array(initializer_list_t), there are
+    no cases which can only be expressed by this function. That is, any
+    initializer list @a init can also be passed to the initializer list
+    constructor @ref basic_json(initializer_list_t, bool, value_t).
+
+    @param[in] init  initializer list to create an object from (optional)
+
+    @return JSON object value
+
+    @throw type_error.301 if @a init is not a list of pairs whose first
+    elements are strings. In this case, no object can be created. When such a
+    value is passed to @ref basic_json(initializer_list_t, bool, value_t),
+    an array would have been created from the passed initializer list @a init.
+    See example below.
+
+    @complexity Linear in the size of @a init.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows an example for the `object`
+    function.,object}
+
+    @sa @ref basic_json(initializer_list_t, bool, value_t) --
+    create a JSON value from an initializer list
+    @sa @ref array(initializer_list_t) -- create a JSON array
+    value from an initializer list
+
+    @since version 1.0.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json object(initializer_list_t init = {})
+    {
+        return basic_json(init, false, value_t::object);
+    }
+
+    /*!
+    @brief construct an array with count copies of given value
+
+    Constructs a JSON array value by creating @a cnt copies of a passed value.
+    In case @a cnt is `0`, an empty array is created.
+
+    @param[in] cnt  the number of JSON copies of @a val to create
+    @param[in] val  the JSON value to copy
+
+    @post `std::distance(begin(),end()) == cnt` holds.
+
+    @complexity Linear in @a cnt.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The following code shows examples for the @ref
+    basic_json(size_type\, const basic_json&)
+    constructor.,basic_json__size_type_basic_json}
+
+    @since version 1.0.0
+    */
+    basic_json(size_type cnt, const basic_json& val)
+        : m_type(value_t::array)
+    {
+        m_value.array = create<array_t>(cnt, val);
+        assert_invariant();
+    }
+
+    /*!
+    @brief construct a JSON container given an iterator range
+
+    Constructs the JSON value with the contents of the range `[first, last)`.
+    The semantics depends on the different types a JSON value can have:
+    - In case of a null type, invalid_iterator.206 is thrown.
+    - In case of other primitive types (number, boolean, or string), @a first
+      must be `begin()` and @a last must be `end()`. In this case, the value is
+      copied. Otherwise, invalid_iterator.204 is thrown.
+    - In case of structured types (array, object), the constructor behaves as
+      similar versions for `std::vector` or `std::map`; that is, a JSON array
+      or object is constructed from the values in the range.
+
+    @tparam InputIT an input iterator type (@ref iterator or @ref
+    const_iterator)
+
+    @param[in] first begin of the range to copy from (included)
+    @param[in] last end of the range to copy from (excluded)
+
+    @pre Iterators @a first and @a last must be initialized. **This
+         precondition is enforced with an assertion (see warning).** If
+         assertions are switched off, a violation of this precondition yields
+         undefined behavior.
+
+    @pre Range `[first, last)` is valid. Usually, this precondition cannot be
+         checked efficiently. Only certain edge cases are detected; see the
+         description of the exceptions below. A violation of this precondition
+         yields undefined behavior.
+
+    @warning A precondition is enforced with a runtime assertion that will
+             result in calling `std::abort` if this precondition is not met.
+             Assertions can be disabled by defining `NDEBUG` at compile time.
+             See https://en.cppreference.com/w/cpp/error/assert for more
+             information.
+
+    @throw invalid_iterator.201 if iterators @a first and @a last are not
+    compatible (i.e., do not belong to the same JSON value). In this case,
+    the range `[first, last)` is undefined.
+    @throw invalid_iterator.204 if iterators @a first and @a last belong to a
+    primitive type (number, boolean, or string), but @a first does not point
+    to the first element any more. In this case, the range `[first, last)` is
+    undefined. See example code below.
+    @throw invalid_iterator.206 if iterators @a first and @a last belong to a
+    null value. In this case, the range `[first, last)` is undefined.
+
+    @complexity Linear in distance between @a first and @a last.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @liveexample{The example below shows several ways to create JSON values by
+    specifying a subrange with iterators.,basic_json__InputIt_InputIt}
+
+    @since version 1.0.0
+    */
+    template<class InputIT, typename std::enable_if<
+                 std::is_same<InputIT, typename basic_json_t::iterator>::value or
+                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
+    basic_json(InputIT first, InputIT last)
+    {
+        assert(first.m_object != nullptr);
+        assert(last.m_object != nullptr);
+
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
+        }
+
+        // copy type from first iterator
+        m_type = first.m_object->m_type;
+
+        // check if iterator range is complete for primitive values
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            {
+                if (JSON_HEDLEY_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
+                                         or not last.m_it.primitive_iterator.is_end()))
+                {
+                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
+                }
+                break;
+            }
+
+            default:
+                break;
+        }
+
+        switch (m_type)
+        {
+            case value_t::number_integer:
+            {
+                m_value.number_integer = first.m_object->m_value.number_integer;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value.number_float = first.m_object->m_value.number_float;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value.boolean = first.m_object->m_value.boolean;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value = *first.m_object->m_value.string;
+                break;
+            }
+
+            case value_t::object:
+            {
+                m_value.object = create<object_t>(first.m_it.object_iterator,
+                                                  last.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value.array = create<array_t>(first.m_it.array_iterator,
+                                                last.m_it.array_iterator);
+                break;
+            }
+
+            default:
+                JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
+                                                    std::string(first.m_object->type_name())));
+        }
+
+        assert_invariant();
+    }
+
+
+    ///////////////////////////////////////
+    // other constructors and destructor //
+    ///////////////////////////////////////
+
+    /// @private
+    basic_json(const detail::json_ref<basic_json>& ref)
+        : basic_json(ref.moved_or_copied())
+    {}
+
+    /*!
+    @brief copy constructor
+
+    Creates a copy of a given JSON value.
+
+    @param[in] other  the JSON value to copy
+
+    @post `*this == other`
+
+    @complexity Linear in the size of @a other.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes to any JSON value.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is linear.
+    - As postcondition, it holds: `other == basic_json(other)`.
+
+    @liveexample{The following code shows an example for the copy
+    constructor.,basic_json__basic_json}
+
+    @since version 1.0.0
+    */
+    basic_json(const basic_json& other)
+        : m_type(other.m_type)
+    {
+        // check of passed value is valid
+        other.assert_invariant();
+
+        switch (m_type)
+        {
+            case value_t::object:
+            {
+                m_value = *other.m_value.object;
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value = *other.m_value.array;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value = *other.m_value.string;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value = other.m_value.boolean;
+                break;
+            }
+
+            case value_t::number_integer:
+            {
+                m_value = other.m_value.number_integer;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value = other.m_value.number_unsigned;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value = other.m_value.number_float;
+                break;
+            }
+
+            default:
+                break;
+        }
+
+        assert_invariant();
+    }
+
+    /*!
+    @brief move constructor
+
+    Move constructor. Constructs a JSON value with the contents of the given
+    value @a other using move semantics. It "steals" the resources from @a
+    other and leaves it as JSON null value.
+
+    @param[in,out] other  value to move to this object
+
+    @post `*this` has the same value as @a other before the call.
+    @post @a other is a JSON null value.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this constructor never throws
+    exceptions.
+
+    @requirement This function helps `basic_json` satisfying the
+    [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
+    requirements.
+
+    @liveexample{The code below shows the move constructor explicitly called
+    via std::move.,basic_json__moveconstructor}
+
+    @since version 1.0.0
+    */
+    basic_json(basic_json&& other) noexcept
+        : m_type(std::move(other.m_type)),
+          m_value(std::move(other.m_value))
+    {
+        // check that passed value is valid
+        other.assert_invariant();
+
+        // invalidate payload
+        other.m_type = value_t::null;
+        other.m_value = {};
+
+        assert_invariant();
+    }
+
+    /*!
+    @brief copy assignment
+
+    Copy assignment operator. Copies a JSON value via the "copy and swap"
+    strategy: It is expressed in terms of the copy constructor, destructor,
+    and the `swap()` member function.
+
+    @param[in] other  value to copy from
+
+    @complexity Linear.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is linear.
+
+    @liveexample{The code below shows and example for the copy assignment. It
+    creates a copy of value `a` which is then swapped with `b`. Finally\, the
+    copy of `a` (which is the null value after the swap) is
+    destroyed.,basic_json__copyassignment}
+
+    @since version 1.0.0
+    */
+    basic_json& operator=(basic_json other) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value and
+        std::is_nothrow_move_assignable<value_t>::value and
+        std::is_nothrow_move_constructible<json_value>::value and
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        // check that passed value is valid
+        other.assert_invariant();
+
+        using std::swap;
+        swap(m_type, other.m_type);
+        swap(m_value, other.m_value);
+
+        assert_invariant();
+        return *this;
+    }
+
+    /*!
+    @brief destructor
+
+    Destroys the JSON value and frees all allocated memory.
+
+    @complexity Linear.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is linear.
+    - All stored elements are destroyed and all memory is freed.
+
+    @since version 1.0.0
+    */
+    ~basic_json() noexcept
+    {
+        assert_invariant();
+        m_value.destroy(m_type);
+    }
+
+    /// @}
+
+  public:
+    ///////////////////////
+    // object inspection //
+    ///////////////////////
+
+    /// @name object inspection
+    /// Functions to inspect the type of a JSON value.
+    /// @{
+
+    /*!
+    @brief serialization
+
+    Serialization function for JSON values. The function tries to mimic
+    Python's `json.dumps()` function, and currently supports its @a indent
+    and @a ensure_ascii parameters.
+
+    @param[in] indent If indent is nonnegative, then array elements and object
+    members will be pretty-printed with that indent level. An indent level of
+    `0` will only insert newlines. `-1` (the default) selects the most compact
+    representation.
+    @param[in] indent_char The character to use for indentation if @a indent is
+    greater than `0`. The default is ` ` (space).
+    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+    in the output are escaped with `\uXXXX` sequences, and the result consists
+    of ASCII characters only.
+    @param[in] error_handler  how to react on decoding errors; there are three
+    possible values: `strict` (throws and exception in case a decoding error
+    occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
+    and `ignore` (ignore invalid UTF-8 sequences during serialization).
+
+    @return string containing the serialization of the JSON value
+
+    @throw type_error.316 if a string stored inside the JSON value is not
+                          UTF-8 encoded
+
+    @complexity Linear.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @liveexample{The following example shows the effect of different @a indent\,
+    @a indent_char\, and @a ensure_ascii parameters to the result of the
+    serialization.,dump}
+
+    @see https://docs.python.org/2/library/json.html#json.dump
+
+    @since version 1.0.0; indentation character @a indent_char, option
+           @a ensure_ascii and exceptions added in version 3.0.0; error
+           handlers added in version 3.4.0.
+    */
+    string_t dump(const int indent = -1,
+                  const char indent_char = ' ',
+                  const bool ensure_ascii = false,
+                  const error_handler_t error_handler = error_handler_t::strict) const
+    {
+        string_t result;
+        serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
+
+        if (indent >= 0)
+        {
+            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
+        }
+        else
+        {
+            s.dump(*this, false, ensure_ascii, 0);
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief return the type of the JSON value (explicit)
+
+    Return the type of the JSON value as a value from the @ref value_t
+    enumeration.
+
+    @return the type of the JSON value
+            Value type                | return value
+            ------------------------- | -------------------------
+            null                      | value_t::null
+            boolean                   | value_t::boolean
+            string                    | value_t::string
+            number (integer)          | value_t::number_integer
+            number (unsigned integer) | value_t::number_unsigned
+            number (floating-point)   | value_t::number_float
+            object                    | value_t::object
+            array                     | value_t::array
+            discarded                 | value_t::discarded
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `type()` for all JSON
+    types.,type}
+
+    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
+    @sa @ref type_name() -- return the type as string
+
+    @since version 1.0.0
+    */
+    constexpr value_t type() const noexcept
+    {
+        return m_type;
+    }
+
+    /*!
+    @brief return whether type is primitive
+
+    This function returns true if and only if the JSON type is primitive
+    (string, number, boolean, or null).
+
+    @return `true` if type is primitive (string, number, boolean, or null),
+    `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_primitive()` for all JSON
+    types.,is_primitive}
+
+    @sa @ref is_structured() -- returns whether JSON value is structured
+    @sa @ref is_null() -- returns whether JSON value is `null`
+    @sa @ref is_string() -- returns whether JSON value is a string
+    @sa @ref is_boolean() -- returns whether JSON value is a boolean
+    @sa @ref is_number() -- returns whether JSON value is a number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_primitive() const noexcept
+    {
+        return is_null() or is_string() or is_boolean() or is_number();
+    }
+
+    /*!
+    @brief return whether type is structured
+
+    This function returns true if and only if the JSON type is structured
+    (array or object).
+
+    @return `true` if type is structured (array or object), `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_structured()` for all JSON
+    types.,is_structured}
+
+    @sa @ref is_primitive() -- returns whether value is primitive
+    @sa @ref is_array() -- returns whether value is an array
+    @sa @ref is_object() -- returns whether value is an object
+
+    @since version 1.0.0
+    */
+    constexpr bool is_structured() const noexcept
+    {
+        return is_array() or is_object();
+    }
+
+    /*!
+    @brief return whether value is null
+
+    This function returns true if and only if the JSON value is null.
+
+    @return `true` if type is null, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_null()` for all JSON
+    types.,is_null}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_null() const noexcept
+    {
+        return m_type == value_t::null;
+    }
+
+    /*!
+    @brief return whether value is a boolean
+
+    This function returns true if and only if the JSON value is a boolean.
+
+    @return `true` if type is boolean, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_boolean()` for all JSON
+    types.,is_boolean}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_boolean() const noexcept
+    {
+        return m_type == value_t::boolean;
+    }
+
+    /*!
+    @brief return whether value is a number
+
+    This function returns true if and only if the JSON value is a number. This
+    includes both integer (signed and unsigned) and floating-point values.
+
+    @return `true` if type is number (regardless whether integer, unsigned
+    integer or floating-type), `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number()` for all JSON
+    types.,is_number}
+
+    @sa @ref is_number_integer() -- check if value is an integer or unsigned
+    integer number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
+    number
+    @sa @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_number() const noexcept
+    {
+        return is_number_integer() or is_number_float();
+    }
+
+    /*!
+    @brief return whether value is an integer number
+
+    This function returns true if and only if the JSON value is a signed or
+    unsigned integer number. This excludes floating-point values.
+
+    @return `true` if type is an integer or unsigned integer number, `false`
+    otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number_integer()` for all
+    JSON types.,is_number_integer}
+
+    @sa @ref is_number() -- check if value is a number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
+    number
+    @sa @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_number_integer() const noexcept
+    {
+        return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
+    }
+
+    /*!
+    @brief return whether value is an unsigned integer number
+
+    This function returns true if and only if the JSON value is an unsigned
+    integer number. This excludes floating-point and signed integer values.
+
+    @return `true` if type is an unsigned integer number, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number_unsigned()` for all
+    JSON types.,is_number_unsigned}
+
+    @sa @ref is_number() -- check if value is a number
+    @sa @ref is_number_integer() -- check if value is an integer or unsigned
+    integer number
+    @sa @ref is_number_float() -- check if value is a floating-point number
+
+    @since version 2.0.0
+    */
+    constexpr bool is_number_unsigned() const noexcept
+    {
+        return m_type == value_t::number_unsigned;
+    }
+
+    /*!
+    @brief return whether value is a floating-point number
+
+    This function returns true if and only if the JSON value is a
+    floating-point number. This excludes signed and unsigned integer values.
+
+    @return `true` if type is a floating-point number, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_number_float()` for all
+    JSON types.,is_number_float}
+
+    @sa @ref is_number() -- check if value is number
+    @sa @ref is_number_integer() -- check if value is an integer number
+    @sa @ref is_number_unsigned() -- check if value is an unsigned integer
+    number
+
+    @since version 1.0.0
+    */
+    constexpr bool is_number_float() const noexcept
+    {
+        return m_type == value_t::number_float;
+    }
+
+    /*!
+    @brief return whether value is an object
+
+    This function returns true if and only if the JSON value is an object.
+
+    @return `true` if type is object, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_object()` for all JSON
+    types.,is_object}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_object() const noexcept
+    {
+        return m_type == value_t::object;
+    }
+
+    /*!
+    @brief return whether value is an array
+
+    This function returns true if and only if the JSON value is an array.
+
+    @return `true` if type is array, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_array()` for all JSON
+    types.,is_array}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_array() const noexcept
+    {
+        return m_type == value_t::array;
+    }
+
+    /*!
+    @brief return whether value is a string
+
+    This function returns true if and only if the JSON value is a string.
+
+    @return `true` if type is string, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_string()` for all JSON
+    types.,is_string}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_string() const noexcept
+    {
+        return m_type == value_t::string;
+    }
+
+    /*!
+    @brief return whether value is discarded
+
+    This function returns true if and only if the JSON value was discarded
+    during parsing with a callback function (see @ref parser_callback_t).
+
+    @note This function will always be `false` for JSON values after parsing.
+    That is, discarded values can only occur during parsing, but will be
+    removed when inside a structured value or replaced by null in other cases.
+
+    @return `true` if type is discarded, `false` otherwise.
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies `is_discarded()` for all JSON
+    types.,is_discarded}
+
+    @since version 1.0.0
+    */
+    constexpr bool is_discarded() const noexcept
+    {
+        return m_type == value_t::discarded;
+    }
+
+    /*!
+    @brief return the type of the JSON value (implicit)
+
+    Implicitly return the type of the JSON value as a value from the @ref
+    value_t enumeration.
+
+    @return the type of the JSON value
+
+    @complexity Constant.
+
+    @exceptionsafety No-throw guarantee: this member function never throws
+    exceptions.
+
+    @liveexample{The following code exemplifies the @ref value_t operator for
+    all JSON types.,operator__value_t}
+
+    @sa @ref type() -- return the type of the JSON value (explicit)
+    @sa @ref type_name() -- return the type as string
+
+    @since version 1.0.0
+    */
+    constexpr operator value_t() const noexcept
+    {
+        return m_type;
+    }
+
+    /// @}
+
+  private:
+    //////////////////
+    // value access //
+    //////////////////
+
+    /// get a boolean (explicit)
+    boolean_t get_impl(boolean_t* /*unused*/) const
+    {
+        if (JSON_HEDLEY_LIKELY(is_boolean()))
+        {
+            return m_value.boolean;
+        }
+
+        JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
+    }
+
+    /// get a pointer to the value (object)
+    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (object)
+    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
+    {
+        return is_object() ? m_value.object : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (array)
+    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
+    {
+        return is_array() ? m_value.array : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (string)
+    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
+    {
+        return is_string() ? m_value.string : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (boolean)
+    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
+    {
+        return is_boolean() ? &m_value.boolean : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (integer number)
+    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
+    {
+        return is_number_integer() ? &m_value.number_integer : nullptr;
+    }
+
+    /// get a pointer to the value (unsigned number)
+    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+
+    /// get a pointer to the value (unsigned number)
+    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
+    {
+        return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
+    /// get a pointer to the value (floating-point number)
+    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
+    {
+        return is_number_float() ? &m_value.number_float : nullptr;
+    }
+
+    /*!
+    @brief helper function to implement get_ref()
+
+    This function helps to implement get_ref() without code duplication for
+    const and non-const overloads
+
+    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
+
+    @throw type_error.303 if ReferenceType does not match underlying value
+    type of the current JSON
+    */
+    template<typename ReferenceType, typename ThisType>
+    static ReferenceType get_ref_impl(ThisType& obj)
+    {
+        // delegate the call to get_ptr<>()
+        auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
+
+        if (JSON_HEDLEY_LIKELY(ptr != nullptr))
+        {
+            return *ptr;
+        }
+
+        JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
+    }
+
+  public:
+    /// @name value access
+    /// Direct access to the stored value of a JSON value.
+    /// @{
+
+    /*!
+    @brief get special-case overload
+
+    This overloads avoids a lot of template boilerplate, it can be seen as the
+    identity method
+
+    @tparam BasicJsonType == @ref basic_json
+
+    @return a copy of *this
+
+    @complexity Constant.
+
+    @since version 2.1.0
+    */
+    template<typename BasicJsonType, detail::enable_if_t<
+                 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
+                 int> = 0>
+    basic_json get() const
+    {
+        return *this;
+    }
+
+    /*!
+    @brief get special-case overload
+
+    This overloads converts the current @ref basic_json in a different
+    @ref basic_json type
+
+    @tparam BasicJsonType == @ref basic_json
+
+    @return a copy of *this, converted into @tparam BasicJsonType
+
+    @complexity Depending on the implementation of the called `from_json()`
+                method.
+
+    @since version 3.2.0
+    */
+    template<typename BasicJsonType, detail::enable_if_t<
+                 not std::is_same<BasicJsonType, basic_json>::value and
+                 detail::is_basic_json<BasicJsonType>::value, int> = 0>
+    BasicJsonType get() const
+    {
+        return *this;
+    }
+
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value
+    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+    The value is converted by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    ValueType ret;
+    JSONSerializer<ValueType>::from_json(*this, ret);
+    return ret;
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json,
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `void from_json(const basic_json&, ValueType&)`, and
+    - @ref json_serializer<ValueType> does not have a `from_json()` method of
+      the form `ValueType from_json(const basic_json&)`
+
+    @tparam ValueTypeCV the provided value type
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @a ValueType
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,get__ValueType_const}
+
+    @since version 2.1.0
+    */
+    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
+             detail::enable_if_t <
+                 not detail::is_basic_json<ValueType>::value and
+                 detail::has_from_json<basic_json_t, ValueType>::value and
+                 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+                 int> = 0>
+    ValueType get() const noexcept(noexcept(
+                                       JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
+    {
+        // we cannot static_assert on ValueTypeCV being non-const, because
+        // there is support for get<const basic_json_t>(), which is why we
+        // still need the uncvref
+        static_assert(not std::is_reference<ValueTypeCV>::value,
+                      "get() cannot be used with reference types, you might want to use get_ref()");
+        static_assert(std::is_default_constructible<ValueType>::value,
+                      "types must be DefaultConstructible when used with get()");
+
+        ValueType ret;
+        JSONSerializer<ValueType>::from_json(*this, ret);
+        return ret;
+    }
+
+    /*!
+    @brief get a value (explicit); special case
+
+    Explicit type conversion between the JSON value and a compatible value
+    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+    The value is converted by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    return JSONSerializer<ValueTypeCV>::from_json(*this);
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json and
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `ValueType from_json(const basic_json&)`
+
+    @note If @ref json_serializer<ValueType> has both overloads of
+    `from_json()`, this one is chosen.
+
+    @tparam ValueTypeCV the provided value type
+    @tparam ValueType the returned value type
+
+    @return copy of the JSON value, converted to @a ValueType
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @since version 2.1.0
+    */
+    template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
+             detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
+                                 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+                                 int> = 0>
+    ValueType get() const noexcept(noexcept(
+                                       JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
+    {
+        static_assert(not std::is_reference<ValueTypeCV>::value,
+                      "get() cannot be used with reference types, you might want to use get_ref()");
+        return JSONSerializer<ValueType>::from_json(*this);
+    }
+
+    /*!
+    @brief get a value (explicit)
+
+    Explicit type conversion between the JSON value and a compatible value.
+    The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
+    `from_json()` method.
+
+    The function is equivalent to executing
+    @code {.cpp}
+    ValueType v;
+    JSONSerializer<ValueType>::from_json(*this, v);
+    @endcode
+
+    This overloads is chosen if:
+    - @a ValueType is not @ref basic_json,
+    - @ref json_serializer<ValueType> has a `from_json()` method of the form
+      `void from_json(const basic_json&, ValueType&)`, and
+
+    @tparam ValueType the input parameter type.
+
+    @return the input parameter, allowing chaining calls.
+
+    @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,get_to}
+
+    @since version 3.3.0
+    */
+    template<typename ValueType,
+             detail::enable_if_t <
+                 not detail::is_basic_json<ValueType>::value and
+                 detail::has_from_json<basic_json_t, ValueType>::value,
+                 int> = 0>
+    ValueType & get_to(ValueType& v) const noexcept(noexcept(
+                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
+    {
+        JSONSerializer<ValueType>::from_json(*this, v);
+        return v;
+    }
+
+    template <
+        typename T, std::size_t N,
+        typename Array = T (&)[N],
+        detail::enable_if_t <
+            detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
+    Array get_to(T (&v)[N]) const
+    noexcept(noexcept(JSONSerializer<Array>::from_json(
+                          std::declval<const basic_json_t&>(), v)))
+    {
+        JSONSerializer<Array>::from_json(*this, v);
+        return v;
+    }
+
+
+    /*!
+    @brief get a pointer value (implicit)
+
+    Implicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning Writing data to the pointee of the result yields an undefined
+    state.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+    @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
+    assertion.
+
+    @return pointer to the internally stored JSON value if the requested
+    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get_ptr}
+
+    @since version 1.0.0
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+    {
+        // delegate the call to get_impl_ptr<>()
+        return get_impl_ptr(static_cast<PointerType>(nullptr));
+    }
+
+    /*!
+    @brief get a pointer value (implicit)
+    @copydoc get_ptr()
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value and
+                 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
+    constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+    {
+        // delegate the call to get_impl_ptr<>() const
+        return get_impl_ptr(static_cast<PointerType>(nullptr));
+    }
+
+    /*!
+    @brief get a pointer value (explicit)
+
+    Explicit pointer access to the internally stored JSON value. No copies are
+    made.
+
+    @warning The pointer becomes invalid if the underlying JSON object
+    changes.
+
+    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+    @ref number_unsigned_t, or @ref number_float_t.
+
+    @return pointer to the internally stored JSON value if the requested
+    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how pointers to internal values of a
+    JSON value can be requested. Note that no type conversions are made and a
+    `nullptr` is returned if the value and the requested pointer type does not
+    match.,get__PointerType}
+
+    @sa @ref get_ptr() for explicit pointer-member access
+
+    @since version 1.0.0
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
+    {
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+    /*!
+    @brief get a pointer value (explicit)
+    @copydoc get()
+    */
+    template<typename PointerType, typename std::enable_if<
+                 std::is_pointer<PointerType>::value, int>::type = 0>
+    constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
+    {
+        // delegate the call to get_ptr
+        return get_ptr<PointerType>();
+    }
+
+    /*!
+    @brief get a reference value (implicit)
+
+    Implicit reference access to the internally stored JSON value. No copies
+    are made.
+
+    @warning Writing data to the referee of the result yields an undefined
+    state.
+
+    @tparam ReferenceType reference type; must be a reference to @ref array_t,
+    @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
+    @ref number_float_t. Enforced by static assertion.
+
+    @return reference to the internally stored JSON value if the requested
+    reference type @a ReferenceType fits to the JSON value; throws
+    type_error.303 otherwise
+
+    @throw type_error.303 in case passed type @a ReferenceType is incompatible
+    with the stored JSON value; see example below
+
+    @complexity Constant.
+
+    @liveexample{The example shows several calls to `get_ref()`.,get_ref}
+
+    @since version 1.1.0
+    */
+    template<typename ReferenceType, typename std::enable_if<
+                 std::is_reference<ReferenceType>::value, int>::type = 0>
+    ReferenceType get_ref()
+    {
+        // delegate call to get_ref_impl
+        return get_ref_impl<ReferenceType>(*this);
+    }
+
+    /*!
+    @brief get a reference value (implicit)
+    @copydoc get_ref()
+    */
+    template<typename ReferenceType, typename std::enable_if<
+                 std::is_reference<ReferenceType>::value and
+                 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
+    ReferenceType get_ref() const
+    {
+        // delegate call to get_ref_impl
+        return get_ref_impl<ReferenceType>(*this);
+    }
+
+    /*!
+    @brief get a value (implicit)
+
+    Implicit type conversion between the JSON value and a compatible value.
+    The call is realized by calling @ref get() const.
+
+    @tparam ValueType non-pointer type compatible to the JSON value, for
+    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+    `std::vector` types for JSON arrays. The character type of @ref string_t
+    as well as an initializer list of this type is excluded to avoid
+    ambiguities as these types implicitly convert to `std::string`.
+
+    @return copy of the JSON value, converted to type @a ValueType
+
+    @throw type_error.302 in case passed type @a ValueType is incompatible
+    to the JSON value type (e.g., the JSON value is of type boolean, but a
+    string is requested); see example below
+
+    @complexity Linear in the size of the JSON value.
+
+    @liveexample{The example below shows several conversions from JSON values
+    to other types. There a few things to note: (1) Floating-point numbers can
+    be converted to integers\, (2) A JSON array can be converted to a standard
+    `std::vector<short>`\, (3) A JSON object can be converted to C++
+    associative containers such as `std::unordered_map<std::string\,
+    json>`.,operator__ValueType}
+
+    @since version 1.0.0
+    */
+    template < typename ValueType, typename std::enable_if <
+                   not std::is_pointer<ValueType>::value and
+                   not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
+                   not std::is_same<ValueType, typename string_t::value_type>::value and
+                   not detail::is_basic_json<ValueType>::value
+
+#ifndef _MSC_VER  // fix for issue #167 operator<< ambiguity under VS2015
+                   and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
+#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
+                   and not std::is_same<ValueType, typename std::string_view>::value
+#endif
+#endif
+                   and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
+                   , int >::type = 0 >
+    operator ValueType() const
+    {
+        // delegate the call to get<>() const
+        return get<ValueType>();
+    }
+
+    /// @}
+
+
+    ////////////////////
+    // element access //
+    ////////////////////
+
+    /// @name element access
+    /// Access to the JSON value.
+    /// @{
+
+    /*!
+    @brief access specified array element with bounds checking
+
+    Returns a reference to the element at specified location @a idx, with
+    bounds checking.
+
+    @param[in] idx  index of the element to access
+
+    @return reference to the element at index @a idx
+
+    @throw type_error.304 if the JSON value is not an array; in this case,
+    calling `at` with an index makes no sense. See example below.
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
+    that is, `idx >= size()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how array elements can be read and
+    written using `at()`. It also demonstrates the different exceptions that
+    can be thrown.,at__size_type}
+    */
+    reference at(size_type idx)
+    {
+        // at only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            JSON_TRY
+            {
+                return m_value.array->at(idx);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
+        }
+    }
+
+    /*!
+    @brief access specified array element with bounds checking
+
+    Returns a const reference to the element at specified location @a idx,
+    with bounds checking.
+
+    @param[in] idx  index of the element to access
+
+    @return const reference to the element at index @a idx
+
+    @throw type_error.304 if the JSON value is not an array; in this case,
+    calling `at` with an index makes no sense. See example below.
+    @throw out_of_range.401 if the index @a idx is out of range of the array;
+    that is, `idx >= size()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how array elements can be read using
+    `at()`. It also demonstrates the different exceptions that can be thrown.,
+    at__size_type_const}
+    */
+    const_reference at(size_type idx) const
+    {
+        // at only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            JSON_TRY
+            {
+                return m_value.array->at(idx);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
+        }
+    }
+
+    /*!
+    @brief access specified object element with bounds checking
+
+    Returns a reference to the element at with specified key @a key, with
+    bounds checking.
+
+    @param[in] key  key of the element to access
+
+    @return reference to the element at key @a key
+
+    @throw type_error.304 if the JSON value is not an object; in this case,
+    calling `at` with a key makes no sense. See example below.
+    @throw out_of_range.403 if the key @a key is is not stored in the object;
+    that is, `find(key) == end()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Logarithmic in the size of the container.
+
+    @sa @ref operator[](const typename object_t::key_type&) for unchecked
+    access by reference
+    @sa @ref value() for access by value with a default value
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how object elements can be read and
+    written using `at()`. It also demonstrates the different exceptions that
+    can be thrown.,at__object_t_key_type}
+    */
+    reference at(const typename object_t::key_type& key)
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            JSON_TRY
+            {
+                return m_value.object->at(key);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
+        }
+    }
+
+    /*!
+    @brief access specified object element with bounds checking
+
+    Returns a const reference to the element at with specified key @a key,
+    with bounds checking.
+
+    @param[in] key  key of the element to access
+
+    @return const reference to the element at key @a key
+
+    @throw type_error.304 if the JSON value is not an object; in this case,
+    calling `at` with a key makes no sense. See example below.
+    @throw out_of_range.403 if the key @a key is is not stored in the object;
+    that is, `find(key) == end()`. See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Logarithmic in the size of the container.
+
+    @sa @ref operator[](const typename object_t::key_type&) for unchecked
+    access by reference
+    @sa @ref value() for access by value with a default value
+
+    @since version 1.0.0
+
+    @liveexample{The example below shows how object elements can be read using
+    `at()`. It also demonstrates the different exceptions that can be thrown.,
+    at__object_t_key_type_const}
+    */
+    const_reference at(const typename object_t::key_type& key) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            JSON_TRY
+            {
+                return m_value.object->at(key);
+            }
+            JSON_CATCH (std::out_of_range&)
+            {
+                // create better exception explanation
+                JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
+            }
+        }
+        else
+        {
+            JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
+        }
+    }
+
+    /*!
+    @brief access specified array element
+
+    Returns a reference to the element at specified location @a idx.
+
+    @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
+    then the array is silently filled up with `null` values to make `idx` a
+    valid reference to the last stored element.
+
+    @param[in] idx  index of the element to access
+
+    @return reference to the element at index @a idx
+
+    @throw type_error.305 if the JSON value is not an array or null; in that
+    cases, using the [] operator with an index makes no sense.
+
+    @complexity Constant if @a idx is in the range of the array. Otherwise
+    linear in `idx - size()`.
+
+    @liveexample{The example below shows how array elements can be read and
+    written using `[]` operator. Note the addition of `null`
+    values.,operatorarray__size_type}
+
+    @since version 1.0.0
+    */
+    reference operator[](size_type idx)
+    {
+        // implicitly convert null value to an empty array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value.array = create<array_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // fill up array with null values if given idx is outside range
+            if (idx >= m_value.array->size())
+            {
+                m_value.array->insert(m_value.array->end(),
+                                      idx - m_value.array->size() + 1,
+                                      basic_json());
+            }
+
+            return m_value.array->operator[](idx);
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief access specified array element
+
+    Returns a const reference to the element at specified location @a idx.
+
+    @param[in] idx  index of the element to access
+
+    @return const reference to the element at index @a idx
+
+    @throw type_error.305 if the JSON value is not an array; in that case,
+    using the [] operator with an index makes no sense.
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how array elements can be read using
+    the `[]` operator.,operatorarray__size_type_const}
+
+    @since version 1.0.0
+    */
+    const_reference operator[](size_type idx) const
+    {
+        // const operator[] only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            return m_value.array->operator[](idx);
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief access specified object element
+
+    Returns a reference to the element at with specified key @a key.
+
+    @note If @a key is not found in the object, then it is silently added to
+    the object and filled with a `null` value to make `key` a valid reference.
+    In case the value was `null` before, it is converted to an object.
+
+    @param[in] key  key of the element to access
+
+    @return reference to the element at key @a key
+
+    @throw type_error.305 if the JSON value is not an object or null; in that
+    cases, using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read and
+    written using the `[]` operator.,operatorarray__key_type}
+
+    @sa @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa @ref value() for access by value with a default value
+
+    @since version 1.0.0
+    */
+    reference operator[](const typename object_t::key_type& key)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        // operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            return m_value.object->operator[](key);
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief read-only access specified object element
+
+    Returns a const reference to the element at with specified key @a key. No
+    bounds checking is performed.
+
+    @warning If the element with key @a key does not exist, the behavior is
+    undefined.
+
+    @param[in] key  key of the element to access
+
+    @return const reference to the element at key @a key
+
+    @pre The element with key @a key must exist. **This precondition is
+         enforced with an assertion.**
+
+    @throw type_error.305 if the JSON value is not an object; in that case,
+    using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read using
+    the `[]` operator.,operatorarray__key_type_const}
+
+    @sa @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa @ref value() for access by value with a default value
+
+    @since version 1.0.0
+    */
+    const_reference operator[](const typename object_t::key_type& key) const
+    {
+        // const operator[] only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            assert(m_value.object->find(key) != m_value.object->end());
+            return m_value.object->find(key)->second;
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief access specified object element
+
+    Returns a reference to the element at with specified key @a key.
+
+    @note If @a key is not found in the object, then it is silently added to
+    the object and filled with a `null` value to make `key` a valid reference.
+    In case the value was `null` before, it is converted to an object.
+
+    @param[in] key  key of the element to access
+
+    @return reference to the element at key @a key
+
+    @throw type_error.305 if the JSON value is not an object or null; in that
+    cases, using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read and
+    written using the `[]` operator.,operatorarray__key_type}
+
+    @sa @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa @ref value() for access by value with a default value
+
+    @since version 1.1.0
+    */
+    template<typename T>
+    JSON_HEDLEY_NON_NULL(2)
+    reference operator[](T* key)
+    {
+        // implicitly convert null to object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            return m_value.object->operator[](key);
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief read-only access specified object element
+
+    Returns a const reference to the element at with specified key @a key. No
+    bounds checking is performed.
+
+    @warning If the element with key @a key does not exist, the behavior is
+    undefined.
+
+    @param[in] key  key of the element to access
+
+    @return const reference to the element at key @a key
+
+    @pre The element with key @a key must exist. **This precondition is
+         enforced with an assertion.**
+
+    @throw type_error.305 if the JSON value is not an object; in that case,
+    using the [] operator with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be read using
+    the `[]` operator.,operatorarray__key_type_const}
+
+    @sa @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa @ref value() for access by value with a default value
+
+    @since version 1.1.0
+    */
+    template<typename T>
+    JSON_HEDLEY_NON_NULL(2)
+    const_reference operator[](T* key) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            assert(m_value.object->find(key) != m_value.object->end());
+            return m_value.object->find(key)->second;
+        }
+
+        JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief access specified object element with default value
+
+    Returns either a copy of an object's element at the specified key @a key
+    or a given default value if no element with key @a key exists.
+
+    The function is basically equivalent to executing
+    @code {.cpp}
+    try {
+        return at(key);
+    } catch(out_of_range) {
+        return default_value;
+    }
+    @endcode
+
+    @note Unlike @ref at(const typename object_t::key_type&), this function
+    does not throw if the given key @a key was not found.
+
+    @note Unlike @ref operator[](const typename object_t::key_type& key), this
+    function does not implicitly add an element to the position defined by @a
+    key. This function is furthermore also applicable to const objects.
+
+    @param[in] key  key of the element to access
+    @param[in] default_value  the value to return if @a key is not found
+
+    @tparam ValueType type compatible to JSON values, for instance `int` for
+    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+    JSON arrays. Note the type of the expected value at @a key and the default
+    value @a default_value must be compatible.
+
+    @return copy of the element at key @a key or @a default_value if @a key
+    is not found
+
+    @throw type_error.302 if @a default_value does not match the type of the
+    value at @a key
+    @throw type_error.306 if the JSON value is not an object; in that case,
+    using `value()` with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be queried
+    with a default value.,basic_json__value}
+
+    @sa @ref at(const typename object_t::key_type&) for access by reference
+    with range checking
+    @sa @ref operator[](const typename object_t::key_type&) for unchecked
+    access by reference
+
+    @since version 1.0.0
+    */
+    template<class ValueType, typename std::enable_if<
+                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
+    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if key is found, return value and given default value otherwise
+            const auto it = find(key);
+            if (it != end())
+            {
+                return *it;
+            }
+
+            return default_value;
+        }
+
+        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief overload for a default value of type const char*
+    @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
+    */
+    string_t value(const typename object_t::key_type& key, const char* default_value) const
+    {
+        return value(key, string_t(default_value));
+    }
+
+    /*!
+    @brief access specified object element via JSON Pointer with default value
+
+    Returns either a copy of an object's element at the specified key @a key
+    or a given default value if no element with key @a key exists.
+
+    The function is basically equivalent to executing
+    @code {.cpp}
+    try {
+        return at(ptr);
+    } catch(out_of_range) {
+        return default_value;
+    }
+    @endcode
+
+    @note Unlike @ref at(const json_pointer&), this function does not throw
+    if the given key @a key was not found.
+
+    @param[in] ptr  a JSON pointer to the element to access
+    @param[in] default_value  the value to return if @a ptr found no value
+
+    @tparam ValueType type compatible to JSON values, for instance `int` for
+    JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+    JSON arrays. Note the type of the expected value at @a key and the default
+    value @a default_value must be compatible.
+
+    @return copy of the element at key @a key or @a default_value if @a key
+    is not found
+
+    @throw type_error.302 if @a default_value does not match the type of the
+    value at @a ptr
+    @throw type_error.306 if the JSON value is not an object; in that case,
+    using `value()` with a key makes no sense.
+
+    @complexity Logarithmic in the size of the container.
+
+    @liveexample{The example below shows how object elements can be queried
+    with a default value.,basic_json__value_ptr}
+
+    @sa @ref operator[](const json_pointer&) for unchecked access by reference
+
+    @since version 2.0.2
+    */
+    template<class ValueType, typename std::enable_if<
+                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
+    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
+    {
+        // at only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            // if pointer resolves a value, return it or use default value
+            JSON_TRY
+            {
+                return ptr.get_checked(this);
+            }
+            JSON_INTERNAL_CATCH (out_of_range&)
+            {
+                return default_value;
+            }
+        }
+
+        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief overload for a default value of type const char*
+    @copydoc basic_json::value(const json_pointer&, ValueType) const
+    */
+    JSON_HEDLEY_NON_NULL(3)
+    string_t value(const json_pointer& ptr, const char* default_value) const
+    {
+        return value(ptr, string_t(default_value));
+    }
+
+    /*!
+    @brief access the first element
+
+    Returns a reference to the first element in the container. For a JSON
+    container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
+
+    @return In case of a structured type (array or object), a reference to the
+    first element is returned. In case of number, string, or boolean values, a
+    reference to the value is returned.
+
+    @complexity Constant.
+
+    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
+    or an empty array or object (undefined behavior, **guarded by
+    assertions**).
+    @post The JSON value remains unchanged.
+
+    @throw invalid_iterator.214 when called on `null` value
+
+    @liveexample{The following code shows an example for `front()`.,front}
+
+    @sa @ref back() -- access the last element
+
+    @since version 1.0.0
+    */
+    reference front()
+    {
+        return *begin();
+    }
+
+    /*!
+    @copydoc basic_json::front()
+    */
+    const_reference front() const
+    {
+        return *cbegin();
+    }
+
+    /*!
+    @brief access the last element
+
+    Returns a reference to the last element in the container. For a JSON
+    container `c`, the expression `c.back()` is equivalent to
+    @code {.cpp}
+    auto tmp = c.end();
+    --tmp;
+    return *tmp;
+    @endcode
+
+    @return In case of a structured type (array or object), a reference to the
+    last element is returned. In case of number, string, or boolean values, a
+    reference to the value is returned.
+
+    @complexity Constant.
+
+    @pre The JSON value must not be `null` (would throw `std::out_of_range`)
+    or an empty array or object (undefined behavior, **guarded by
+    assertions**).
+    @post The JSON value remains unchanged.
+
+    @throw invalid_iterator.214 when called on a `null` value. See example
+    below.
+
+    @liveexample{The following code shows an example for `back()`.,back}
+
+    @sa @ref front() -- access the first element
+
+    @since version 1.0.0
+    */
+    reference back()
+    {
+        auto tmp = end();
+        --tmp;
+        return *tmp;
+    }
+
+    /*!
+    @copydoc basic_json::back()
+    */
+    const_reference back() const
+    {
+        auto tmp = cend();
+        --tmp;
+        return *tmp;
+    }
+
+    /*!
+    @brief remove element given an iterator
+
+    Removes the element specified by iterator @a pos. The iterator @a pos must
+    be valid and dereferenceable. Thus the `end()` iterator (which is valid,
+    but is not dereferenceable) cannot be used as a value for @a pos.
+
+    If called on a primitive type other than `null`, the resulting JSON value
+    will be `null`.
+
+    @param[in] pos iterator to the element to remove
+    @return Iterator following the last removed element. If the iterator @a
+    pos refers to the last element, the `end()` iterator is returned.
+
+    @tparam IteratorType an @ref iterator or @ref const_iterator
+
+    @post Invalidates iterators and references at or after the point of the
+    erase, including the `end()` iterator.
+
+    @throw type_error.307 if called on a `null` value; example: `"cannot use
+    erase() with null"`
+    @throw invalid_iterator.202 if called on an iterator which does not belong
+    to the current JSON value; example: `"iterator does not fit current
+    value"`
+    @throw invalid_iterator.205 if called on a primitive type with invalid
+    iterator (i.e., any iterator which is not `begin()`); example: `"iterator
+    out of range"`
+
+    @complexity The complexity depends on the type:
+    - objects: amortized constant
+    - arrays: linear in distance between @a pos and the end of the container
+    - strings: linear in the length of the string
+    - other types: constant
+
+    @liveexample{The example shows the result of `erase()` for different JSON
+    types.,erase__IteratorType}
+
+    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
+    the given range
+    @sa @ref erase(const typename object_t::key_type&) -- removes the element
+    from an object at the given key
+    @sa @ref erase(const size_type) -- removes the element from an array at
+    the given index
+
+    @since version 1.0.0
+    */
+    template<class IteratorType, typename std::enable_if<
+                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
+                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
+             = 0>
+    IteratorType erase(IteratorType pos)
+    {
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
+        }
+
+        IteratorType result = end();
+
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            {
+                if (JSON_HEDLEY_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
+                {
+                    JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
+                }
+
+                if (is_string())
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+                    m_value.string = nullptr;
+                }
+
+                m_type = value_t::null;
+                assert_invariant();
+                break;
+            }
+
+            case value_t::object:
+            {
+                result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
+                break;
+            }
+
+            default:
+                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief remove elements given an iterator range
+
+    Removes the element specified by the range `[first; last)`. The iterator
+    @a first does not need to be dereferenceable if `first == last`: erasing
+    an empty range is a no-op.
+
+    If called on a primitive type other than `null`, the resulting JSON value
+    will be `null`.
+
+    @param[in] first iterator to the beginning of the range to remove
+    @param[in] last iterator past the end of the range to remove
+    @return Iterator following the last removed element. If the iterator @a
+    second refers to the last element, the `end()` iterator is returned.
+
+    @tparam IteratorType an @ref iterator or @ref const_iterator
+
+    @post Invalidates iterators and references at or after the point of the
+    erase, including the `end()` iterator.
+
+    @throw type_error.307 if called on a `null` value; example: `"cannot use
+    erase() with null"`
+    @throw invalid_iterator.203 if called on iterators which does not belong
+    to the current JSON value; example: `"iterators do not fit current value"`
+    @throw invalid_iterator.204 if called on a primitive type with invalid
+    iterators (i.e., if `first != begin()` and `last != end()`); example:
+    `"iterators out of range"`
+
+    @complexity The complexity depends on the type:
+    - objects: `log(size()) + std::distance(first, last)`
+    - arrays: linear in the distance between @a first and @a last, plus linear
+      in the distance between @a last and end of the container
+    - strings: linear in the length of the string
+    - other types: constant
+
+    @liveexample{The example shows the result of `erase()` for different JSON
+    types.,erase__IteratorType_IteratorType}
+
+    @sa @ref erase(IteratorType) -- removes the element at a given position
+    @sa @ref erase(const typename object_t::key_type&) -- removes the element
+    from an object at the given key
+    @sa @ref erase(const size_type) -- removes the element from an array at
+    the given index
+
+    @since version 1.0.0
+    */
+    template<class IteratorType, typename std::enable_if<
+                 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
+                 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
+             = 0>
+    IteratorType erase(IteratorType first, IteratorType last)
+    {
+        // make sure iterator fits the current value
+        if (JSON_HEDLEY_UNLIKELY(this != first.m_object or this != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
+        }
+
+        IteratorType result = end();
+
+        switch (m_type)
+        {
+            case value_t::boolean:
+            case value_t::number_float:
+            case value_t::number_integer:
+            case value_t::number_unsigned:
+            case value_t::string:
+            {
+                if (JSON_HEDLEY_LIKELY(not first.m_it.primitive_iterator.is_begin()
+                                       or not last.m_it.primitive_iterator.is_end()))
+                {
+                    JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
+                }
+
+                if (is_string())
+                {
+                    AllocatorType<string_t> alloc;
+                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+                    m_value.string = nullptr;
+                }
+
+                m_type = value_t::null;
+                assert_invariant();
+                break;
+            }
+
+            case value_t::object:
+            {
+                result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
+                                              last.m_it.object_iterator);
+                break;
+            }
+
+            case value_t::array:
+            {
+                result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
+                                             last.m_it.array_iterator);
+                break;
+            }
+
+            default:
+                JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief remove element from a JSON object given a key
+
+    Removes elements from a JSON object with the key value @a key.
+
+    @param[in] key value of the elements to remove
+
+    @return Number of elements removed. If @a ObjectType is the default
+    `std::map` type, the return value will always be `0` (@a key was not
+    found) or `1` (@a key was found).
+
+    @post References and iterators to the erased elements are invalidated.
+    Other references and iterators are not affected.
+
+    @throw type_error.307 when called on a type other than JSON object;
+    example: `"cannot use erase() with null"`
+
+    @complexity `log(size()) + count(key)`
+
+    @liveexample{The example shows the effect of `erase()`.,erase__key_type}
+
+    @sa @ref erase(IteratorType) -- removes the element at a given position
+    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
+    the given range
+    @sa @ref erase(const size_type) -- removes the element from an array at
+    the given index
+
+    @since version 1.0.0
+    */
+    size_type erase(const typename object_t::key_type& key)
+    {
+        // this erase only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            return m_value.object->erase(key);
+        }
+
+        JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief remove element from a JSON array given an index
+
+    Removes element from a JSON array at the index @a idx.
+
+    @param[in] idx index of the element to remove
+
+    @throw type_error.307 when called on a type other than JSON object;
+    example: `"cannot use erase() with null"`
+    @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
+    is out of range"`
+
+    @complexity Linear in distance between @a idx and the end of the container.
+
+    @liveexample{The example shows the effect of `erase()`.,erase__size_type}
+
+    @sa @ref erase(IteratorType) -- removes the element at a given position
+    @sa @ref erase(IteratorType, IteratorType) -- removes the elements in
+    the given range
+    @sa @ref erase(const typename object_t::key_type&) -- removes the element
+    from an object at the given key
+
+    @since version 1.0.0
+    */
+    void erase(const size_type idx)
+    {
+        // this erase only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            if (JSON_HEDLEY_UNLIKELY(idx >= size()))
+            {
+                JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
+            }
+
+            m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
+        }
+        else
+        {
+            JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
+        }
+    }
+
+    /// @}
+
+
+    ////////////
+    // lookup //
+    ////////////
+
+    /// @name lookup
+    /// @{
+
+    /*!
+    @brief find an element in a JSON object
+
+    Finds an element in a JSON object with key equivalent to @a key. If the
+    element is not found or the JSON value is not an object, end() is
+    returned.
+
+    @note This method always returns @ref end() when executed on a JSON type
+          that is not an object.
+
+    @param[in] key key value of the element to search for.
+
+    @return Iterator to an element with key equivalent to @a key. If no such
+    element is found or the JSON value is not an object, past-the-end (see
+    @ref end()) iterator is returned.
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The example shows how `find()` is used.,find__key_type}
+
+    @sa @ref contains(KeyT&&) const -- checks whether a key exists
+
+    @since version 1.0.0
+    */
+    template<typename KeyT>
+    iterator find(KeyT&& key)
+    {
+        auto result = end();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief find an element in a JSON object
+    @copydoc find(KeyT&&)
+    */
+    template<typename KeyT>
+    const_iterator find(KeyT&& key) const
+    {
+        auto result = cend();
+
+        if (is_object())
+        {
+            result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief returns the number of occurrences of a key in a JSON object
+
+    Returns the number of elements with key @a key. If ObjectType is the
+    default `std::map` type, the return value will always be `0` (@a key was
+    not found) or `1` (@a key was found).
+
+    @note This method always returns `0` when executed on a JSON type that is
+          not an object.
+
+    @param[in] key key value of the element to count
+
+    @return Number of elements with key @a key. If the JSON value is not an
+    object, the return value will be `0`.
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The example shows how `count()` is used.,count}
+
+    @since version 1.0.0
+    */
+    template<typename KeyT>
+    size_type count(KeyT&& key) const
+    {
+        // return 0 for all nonobject types
+        return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
+    }
+
+    /*!
+    @brief check the existence of an element in a JSON object
+
+    Check whether an element exists in a JSON object with key equivalent to
+    @a key. If the element is not found or the JSON value is not an object,
+    false is returned.
+
+    @note This method always returns false when executed on a JSON type
+          that is not an object.
+
+    @param[in] key key value to check its existence.
+
+    @return true if an element with specified @a key exists. If no such
+    element with such key is found or the JSON value is not an object,
+    false is returned.
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The following code shows an example for `contains()`.,contains}
+
+    @sa @ref find(KeyT&&) -- returns an iterator to an object element
+    @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
+
+    @since version 3.6.0
+    */
+    template<typename KeyT, typename std::enable_if<
+                 not std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int>::type = 0>
+    bool contains(KeyT && key) const
+    {
+        return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
+    }
+
+    /*!
+    @brief check the existence of an element in a JSON object given a JSON pointer
+
+    Check whether the given JSON pointer @a ptr can be resolved in the current
+    JSON value.
+
+    @note This method can be executed on any JSON value type.
+
+    @param[in] ptr JSON pointer to check its existence.
+
+    @return true if the JSON pointer can be resolved to a stored value, false
+    otherwise.
+
+    @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+
+    @complexity Logarithmic in the size of the JSON object.
+
+    @liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
+
+    @sa @ref contains(KeyT &&) const -- checks the existence of a key
+
+    @since version 3.7.0
+    */
+    bool contains(const json_pointer& ptr) const
+    {
+        return ptr.contains(this);
+    }
+
+    /// @}
+
+
+    ///////////////
+    // iterators //
+    ///////////////
+
+    /// @name iterators
+    /// @{
+
+    /*!
+    @brief returns an iterator to the first element
+
+    Returns an iterator to the first element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return iterator to the first element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+
+    @liveexample{The following code shows an example for `begin()`.,begin}
+
+    @sa @ref cbegin() -- returns a const iterator to the beginning
+    @sa @ref end() -- returns an iterator to the end
+    @sa @ref cend() -- returns a const iterator to the end
+
+    @since version 1.0.0
+    */
+    iterator begin() noexcept
+    {
+        iterator result(this);
+        result.set_begin();
+        return result;
+    }
+
+    /*!
+    @copydoc basic_json::cbegin()
+    */
+    const_iterator begin() const noexcept
+    {
+        return cbegin();
+    }
+
+    /*!
+    @brief returns a const iterator to the first element
+
+    Returns a const iterator to the first element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return const iterator to the first element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
+
+    @liveexample{The following code shows an example for `cbegin()`.,cbegin}
+
+    @sa @ref begin() -- returns an iterator to the beginning
+    @sa @ref end() -- returns an iterator to the end
+    @sa @ref cend() -- returns a const iterator to the end
+
+    @since version 1.0.0
+    */
+    const_iterator cbegin() const noexcept
+    {
+        const_iterator result(this);
+        result.set_begin();
+        return result;
+    }
+
+    /*!
+    @brief returns an iterator to one past the last element
+
+    Returns an iterator to one past the last element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return iterator one past the last element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+
+    @liveexample{The following code shows an example for `end()`.,end}
+
+    @sa @ref cend() -- returns a const iterator to the end
+    @sa @ref begin() -- returns an iterator to the beginning
+    @sa @ref cbegin() -- returns a const iterator to the beginning
+
+    @since version 1.0.0
+    */
+    iterator end() noexcept
+    {
+        iterator result(this);
+        result.set_end();
+        return result;
+    }
+
+    /*!
+    @copydoc basic_json::cend()
+    */
+    const_iterator end() const noexcept
+    {
+        return cend();
+    }
+
+    /*!
+    @brief returns a const iterator to one past the last element
+
+    Returns a const iterator to one past the last element.
+
+    @image html range-begin-end.svg "Illustration from cppreference.com"
+
+    @return const iterator one past the last element
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
+
+    @liveexample{The following code shows an example for `cend()`.,cend}
+
+    @sa @ref end() -- returns an iterator to the end
+    @sa @ref begin() -- returns an iterator to the beginning
+    @sa @ref cbegin() -- returns a const iterator to the beginning
+
+    @since version 1.0.0
+    */
+    const_iterator cend() const noexcept
+    {
+        const_iterator result(this);
+        result.set_end();
+        return result;
+    }
+
+    /*!
+    @brief returns an iterator to the reverse-beginning
+
+    Returns an iterator to the reverse-beginning; that is, the last element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `reverse_iterator(end())`.
+
+    @liveexample{The following code shows an example for `rbegin()`.,rbegin}
+
+    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
+    @sa @ref rend() -- returns a reverse iterator to the end
+    @sa @ref crend() -- returns a const reverse iterator to the end
+
+    @since version 1.0.0
+    */
+    reverse_iterator rbegin() noexcept
+    {
+        return reverse_iterator(end());
+    }
+
+    /*!
+    @copydoc basic_json::crbegin()
+    */
+    const_reverse_iterator rbegin() const noexcept
+    {
+        return crbegin();
+    }
+
+    /*!
+    @brief returns an iterator to the reverse-end
+
+    Returns an iterator to the reverse-end; that is, one before the first
+    element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `reverse_iterator(begin())`.
+
+    @liveexample{The following code shows an example for `rend()`.,rend}
+
+    @sa @ref crend() -- returns a const reverse iterator to the end
+    @sa @ref rbegin() -- returns a reverse iterator to the beginning
+    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
+
+    @since version 1.0.0
+    */
+    reverse_iterator rend() noexcept
+    {
+        return reverse_iterator(begin());
+    }
+
+    /*!
+    @copydoc basic_json::crend()
+    */
+    const_reverse_iterator rend() const noexcept
+    {
+        return crend();
+    }
+
+    /*!
+    @brief returns a const reverse iterator to the last element
+
+    Returns a const iterator to the reverse-beginning; that is, the last
+    element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
+
+    @liveexample{The following code shows an example for `crbegin()`.,crbegin}
+
+    @sa @ref rbegin() -- returns a reverse iterator to the beginning
+    @sa @ref rend() -- returns a reverse iterator to the end
+    @sa @ref crend() -- returns a const reverse iterator to the end
+
+    @since version 1.0.0
+    */
+    const_reverse_iterator crbegin() const noexcept
+    {
+        return const_reverse_iterator(cend());
+    }
+
+    /*!
+    @brief returns a const reverse iterator to one before the first
+
+    Returns a const reverse iterator to the reverse-end; that is, one before
+    the first element.
+
+    @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+    @complexity Constant.
+
+    @requirement This function helps `basic_json` satisfying the
+    [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
+
+    @liveexample{The following code shows an example for `crend()`.,crend}
+
+    @sa @ref rend() -- returns a reverse iterator to the end
+    @sa @ref rbegin() -- returns a reverse iterator to the beginning
+    @sa @ref crbegin() -- returns a const reverse iterator to the beginning
+
+    @since version 1.0.0
+    */
+    const_reverse_iterator crend() const noexcept
+    {
+        return const_reverse_iterator(cbegin());
+    }
+
+  public:
+    /*!
+    @brief wrapper to access iterator member functions in range-based for
+
+    This function allows to access @ref iterator::key() and @ref
+    iterator::value() during range-based for loops. In these loops, a
+    reference to the JSON values is returned, so there is no access to the
+    underlying iterator.
+
+    For loop without iterator_wrapper:
+
+    @code{cpp}
+    for (auto it = j_object.begin(); it != j_object.end(); ++it)
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    Range-based for loop without iterator proxy:
+
+    @code{cpp}
+    for (auto it : j_object)
+    {
+        // "it" is of type json::reference and has no key() member
+        std::cout << "value: " << it << '\n';
+    }
+    @endcode
+
+    Range-based for loop with iterator proxy:
+
+    @code{cpp}
+    for (auto it : json::iterator_wrapper(j_object))
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    @note When iterating over an array, `key()` will return the index of the
+          element as string (see example).
+
+    @param[in] ref  reference to a JSON value
+    @return iteration proxy object wrapping @a ref with an interface to use in
+            range-based for loops
+
+    @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @note The name of this function is not yet final and may change in the
+    future.
+
+    @deprecated This stream operator is deprecated and will be removed in
+                future 4.0.0 of the library. Please use @ref items() instead;
+                that is, replace `json::iterator_wrapper(j)` with `j.items()`.
+    */
+    JSON_HEDLEY_DEPRECATED(3.1.0)
+    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
+    {
+        return ref.items();
+    }
+
+    /*!
+    @copydoc iterator_wrapper(reference)
+    */
+    JSON_HEDLEY_DEPRECATED(3.1.0)
+    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
+    {
+        return ref.items();
+    }
+
+    /*!
+    @brief helper to access iterator member functions in range-based for
+
+    This function allows to access @ref iterator::key() and @ref
+    iterator::value() during range-based for loops. In these loops, a
+    reference to the JSON values is returned, so there is no access to the
+    underlying iterator.
+
+    For loop without `items()` function:
+
+    @code{cpp}
+    for (auto it = j_object.begin(); it != j_object.end(); ++it)
+    {
+        std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+    }
+    @endcode
+
+    Range-based for loop without `items()` function:
+
+    @code{cpp}
+    for (auto it : j_object)
+    {
+        // "it" is of type json::reference and has no key() member
+        std::cout << "value: " << it << '\n';
+    }
+    @endcode
+
+    Range-based for loop with `items()` function:
+
+    @code{cpp}
+    for (auto& el : j_object.items())
+    {
+        std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
+    }
+    @endcode
+
+    The `items()` function also allows to use
+    [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
+    (C++17):
+
+    @code{cpp}
+    for (auto& [key, val] : j_object.items())
+    {
+        std::cout << "key: " << key << ", value:" << val << '\n';
+    }
+    @endcode
+
+    @note When iterating over an array, `key()` will return the index of the
+          element as string (see example). For primitive types (e.g., numbers),
+          `key()` returns an empty string.
+
+    @return iteration proxy object wrapping @a ref with an interface to use in
+            range-based for loops
+
+    @liveexample{The following code shows how the function is used.,items}
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 3.1.0, structured bindings support since 3.5.0.
+    */
+    iteration_proxy<iterator> items() noexcept
+    {
+        return iteration_proxy<iterator>(*this);
+    }
+
+    /*!
+    @copydoc items()
+    */
+    iteration_proxy<const_iterator> items() const noexcept
+    {
+        return iteration_proxy<const_iterator>(*this);
+    }
+
+    /// @}
+
+
+    //////////////
+    // capacity //
+    //////////////
+
+    /// @name capacity
+    /// @{
+
+    /*!
+    @brief checks whether the container is empty.
+
+    Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
+
+    @return The return value depends on the different types and is
+            defined as follows:
+            Value type  | return value
+            ----------- | -------------
+            null        | `true`
+            boolean     | `false`
+            string      | `false`
+            number      | `false`
+            object      | result of function `object_t::empty()`
+            array       | result of function `array_t::empty()`
+
+    @liveexample{The following code uses `empty()` to check if a JSON
+    object contains any elements.,empty}
+
+    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+    the Container concept; that is, their `empty()` functions have constant
+    complexity.
+
+    @iterators No changes.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @note This function does not return whether a string stored as JSON value
+    is empty - it returns whether the JSON container itself is empty which is
+    false in the case of a string.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `begin() == end()`.
+
+    @sa @ref size() -- returns the number of elements
+
+    @since version 1.0.0
+    */
+    bool empty() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+            {
+                // null values are empty
+                return true;
+            }
+
+            case value_t::array:
+            {
+                // delegate call to array_t::empty()
+                return m_value.array->empty();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::empty()
+                return m_value.object->empty();
+            }
+
+            default:
+            {
+                // all other types are nonempty
+                return false;
+            }
+        }
+    }
+
+    /*!
+    @brief returns the number of elements
+
+    Returns the number of elements in a JSON value.
+
+    @return The return value depends on the different types and is
+            defined as follows:
+            Value type  | return value
+            ----------- | -------------
+            null        | `0`
+            boolean     | `1`
+            string      | `1`
+            number      | `1`
+            object      | result of function object_t::size()
+            array       | result of function array_t::size()
+
+    @liveexample{The following code calls `size()` on the different value
+    types.,size}
+
+    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+    the Container concept; that is, their size() functions have constant
+    complexity.
+
+    @iterators No changes.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @note This function does not return the length of a string stored as JSON
+    value - it returns the number of elements in the JSON value which is 1 in
+    the case of a string.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of `std::distance(begin(), end())`.
+
+    @sa @ref empty() -- checks whether the container is empty
+    @sa @ref max_size() -- returns the maximal number of elements
+
+    @since version 1.0.0
+    */
+    size_type size() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::null:
+            {
+                // null values are empty
+                return 0;
+            }
+
+            case value_t::array:
+            {
+                // delegate call to array_t::size()
+                return m_value.array->size();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::size()
+                return m_value.object->size();
+            }
+
+            default:
+            {
+                // all other types have size 1
+                return 1;
+            }
+        }
+    }
+
+    /*!
+    @brief returns the maximum possible number of elements
+
+    Returns the maximum number of elements a JSON value is able to hold due to
+    system or library implementation limitations, i.e. `std::distance(begin(),
+    end())` for the JSON value.
+
+    @return The return value depends on the different types and is
+            defined as follows:
+            Value type  | return value
+            ----------- | -------------
+            null        | `0` (same as `size()`)
+            boolean     | `1` (same as `size()`)
+            string      | `1` (same as `size()`)
+            number      | `1` (same as `size()`)
+            object      | result of function `object_t::max_size()`
+            array       | result of function `array_t::max_size()`
+
+    @liveexample{The following code calls `max_size()` on the different value
+    types. Note the output is implementation specific.,max_size}
+
+    @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+    the Container concept; that is, their `max_size()` functions have constant
+    complexity.
+
+    @iterators No changes.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @requirement This function helps `basic_json` satisfying the
+    [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+    requirements:
+    - The complexity is constant.
+    - Has the semantics of returning `b.size()` where `b` is the largest
+      possible JSON value.
+
+    @sa @ref size() -- returns the number of elements
+
+    @since version 1.0.0
+    */
+    size_type max_size() const noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::array:
+            {
+                // delegate call to array_t::max_size()
+                return m_value.array->max_size();
+            }
+
+            case value_t::object:
+            {
+                // delegate call to object_t::max_size()
+                return m_value.object->max_size();
+            }
+
+            default:
+            {
+                // all other types have max_size() == size()
+                return size();
+            }
+        }
+    }
+
+    /// @}
+
+
+    ///////////////
+    // modifiers //
+    ///////////////
+
+    /// @name modifiers
+    /// @{
+
+    /*!
+    @brief clears the contents
+
+    Clears the content of a JSON value and resets it to the default value as
+    if @ref basic_json(value_t) would have been called with the current value
+    type from @ref type():
+
+    Value type  | initial value
+    ----------- | -------------
+    null        | `null`
+    boolean     | `false`
+    string      | `""`
+    number      | `0`
+    object      | `{}`
+    array       | `[]`
+
+    @post Has the same effect as calling
+    @code {.cpp}
+    *this = basic_json(type());
+    @endcode
+
+    @liveexample{The example below shows the effect of `clear()` to different
+    JSON types.,clear}
+
+    @complexity Linear in the size of the JSON value.
+
+    @iterators All iterators, pointers and references related to this container
+               are invalidated.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @sa @ref basic_json(value_t) -- constructor that creates an object with the
+        same value than calling `clear()`
+
+    @since version 1.0.0
+    */
+    void clear() noexcept
+    {
+        switch (m_type)
+        {
+            case value_t::number_integer:
+            {
+                m_value.number_integer = 0;
+                break;
+            }
+
+            case value_t::number_unsigned:
+            {
+                m_value.number_unsigned = 0;
+                break;
+            }
+
+            case value_t::number_float:
+            {
+                m_value.number_float = 0.0;
+                break;
+            }
+
+            case value_t::boolean:
+            {
+                m_value.boolean = false;
+                break;
+            }
+
+            case value_t::string:
+            {
+                m_value.string->clear();
+                break;
+            }
+
+            case value_t::array:
+            {
+                m_value.array->clear();
+                break;
+            }
+
+            case value_t::object:
+            {
+                m_value.object->clear();
+                break;
+            }
+
+            default:
+                break;
+        }
+    }
+
+    /*!
+    @brief add an object to an array
+
+    Appends the given element @a val to the end of the JSON value. If the
+    function is called on a JSON null value, an empty array is created before
+    appending @a val.
+
+    @param[in] val the value to add to the JSON array
+
+    @throw type_error.308 when called on a type other than JSON array or
+    null; example: `"cannot use push_back() with number"`
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows how `push_back()` and `+=` can be used to
+    add elements to a JSON array. Note how the `null` value was silently
+    converted to a JSON array.,push_back}
+
+    @since version 1.0.0
+    */
+    void push_back(basic_json&& val)
+    {
+        // push_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
+        {
+            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (move semantics)
+        m_value.array->push_back(std::move(val));
+        // invalidate object: mark it null so we do not call the destructor
+        // cppcheck-suppress accessMoved
+        val.m_type = value_t::null;
+    }
+
+    /*!
+    @brief add an object to an array
+    @copydoc push_back(basic_json&&)
+    */
+    reference operator+=(basic_json&& val)
+    {
+        push_back(std::move(val));
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an array
+    @copydoc push_back(basic_json&&)
+    */
+    void push_back(const basic_json& val)
+    {
+        // push_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
+        {
+            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array
+        m_value.array->push_back(val);
+    }
+
+    /*!
+    @brief add an object to an array
+    @copydoc push_back(basic_json&&)
+    */
+    reference operator+=(const basic_json& val)
+    {
+        push_back(val);
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an object
+
+    Inserts the given element @a val to the JSON object. If the function is
+    called on a JSON null value, an empty object is created before inserting
+    @a val.
+
+    @param[in] val the value to add to the JSON object
+
+    @throw type_error.308 when called on a type other than JSON object or
+    null; example: `"cannot use push_back() with number"`
+
+    @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+    @liveexample{The example shows how `push_back()` and `+=` can be used to
+    add elements to a JSON object. Note how the `null` value was silently
+    converted to a JSON object.,push_back__object_t__value}
+
+    @since version 1.0.0
+    */
+    void push_back(const typename object_t::value_type& val)
+    {
+        // push_back only works for null objects or objects
+        if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object())))
+        {
+            JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to array
+        m_value.object->insert(val);
+    }
+
+    /*!
+    @brief add an object to an object
+    @copydoc push_back(const typename object_t::value_type&)
+    */
+    reference operator+=(const typename object_t::value_type& val)
+    {
+        push_back(val);
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an object
+
+    This function allows to use `push_back` with an initializer list. In case
+
+    1. the current value is an object,
+    2. the initializer list @a init contains only two elements, and
+    3. the first element of @a init is a string,
+
+    @a init is converted into an object element and added using
+    @ref push_back(const typename object_t::value_type&). Otherwise, @a init
+    is converted to a JSON value and added using @ref push_back(basic_json&&).
+
+    @param[in] init  an initializer list
+
+    @complexity Linear in the size of the initializer list @a init.
+
+    @note This function is required to resolve an ambiguous overload error,
+          because pairs like `{"key", "value"}` can be both interpreted as
+          `object_t::value_type` or `std::initializer_list<basic_json>`, see
+          https://github.com/nlohmann/json/issues/235 for more information.
+
+    @liveexample{The example shows how initializer lists are treated as
+    objects when possible.,push_back__initializer_list}
+    */
+    void push_back(initializer_list_t init)
+    {
+        if (is_object() and init.size() == 2 and (*init.begin())->is_string())
+        {
+            basic_json&& key = init.begin()->moved_or_copied();
+            push_back(typename object_t::value_type(
+                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
+        }
+        else
+        {
+            push_back(basic_json(init));
+        }
+    }
+
+    /*!
+    @brief add an object to an object
+    @copydoc push_back(initializer_list_t)
+    */
+    reference operator+=(initializer_list_t init)
+    {
+        push_back(init);
+        return *this;
+    }
+
+    /*!
+    @brief add an object to an array
+
+    Creates a JSON value from the passed parameters @a args to the end of the
+    JSON value. If the function is called on a JSON null value, an empty array
+    is created before appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @return reference to the inserted element
+
+    @throw type_error.311 when called on a type other than JSON array or
+    null; example: `"cannot use emplace_back() with number"`
+
+    @complexity Amortized constant.
+
+    @liveexample{The example shows how `push_back()` can be used to add
+    elements to a JSON array. Note how the `null` value was silently converted
+    to a JSON array.,emplace_back}
+
+    @since version 2.0.8, returns reference since 3.7.0
+    */
+    template<class... Args>
+    reference emplace_back(Args&& ... args)
+    {
+        // emplace_back only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_array())))
+        {
+            JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
+        }
+
+        // transform null object into an array
+        if (is_null())
+        {
+            m_type = value_t::array;
+            m_value = value_t::array;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+#ifdef JSON_HAS_CPP_17
+        return m_value.array->emplace_back(std::forward<Args>(args)...);
+#else
+        m_value.array->emplace_back(std::forward<Args>(args)...);
+        return m_value.array->back();
+#endif
+    }
+
+    /*!
+    @brief add an object to an object if key does not exist
+
+    Inserts a new element into a JSON object constructed in-place with the
+    given @a args if there is no element with the key in the container. If the
+    function is called on a JSON null value, an empty object is created before
+    appending the value created from @a args.
+
+    @param[in] args arguments to forward to a constructor of @ref basic_json
+    @tparam Args compatible types to create a @ref basic_json object
+
+    @return a pair consisting of an iterator to the inserted element, or the
+            already-existing element if no insertion happened, and a bool
+            denoting whether the insertion took place.
+
+    @throw type_error.311 when called on a type other than JSON object or
+    null; example: `"cannot use emplace() with number"`
+
+    @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+    @liveexample{The example shows how `emplace()` can be used to add elements
+    to a JSON object. Note how the `null` value was silently converted to a
+    JSON object. Further note how no value is added if there was already one
+    value stored with the same key.,emplace}
+
+    @since version 2.0.8
+    */
+    template<class... Args>
+    std::pair<iterator, bool> emplace(Args&& ... args)
+    {
+        // emplace only works for null objects or arrays
+        if (JSON_HEDLEY_UNLIKELY(not(is_null() or is_object())))
+        {
+            JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
+        }
+
+        // transform null object into an object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value = value_t::object;
+            assert_invariant();
+        }
+
+        // add element to array (perfect forwarding)
+        auto res = m_value.object->emplace(std::forward<Args>(args)...);
+        // create result iterator and set iterator to the result of emplace
+        auto it = begin();
+        it.m_it.object_iterator = res.first;
+
+        // return pair of iterator and boolean
+        return {it, res.second};
+    }
+
+    /// Helper for insertion of an iterator
+    /// @note: This uses std::distance to support GCC 4.8,
+    ///        see https://github.com/nlohmann/json/pull/1257
+    template<typename... Args>
+    iterator insert_iterator(const_iterator pos, Args&& ... args)
+    {
+        iterator result(this);
+        assert(m_value.array != nullptr);
+
+        auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
+        m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
+        result.m_it.array_iterator = m_value.array->begin() + insert_pos;
+
+        // This could have been written as:
+        // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
+        // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
+
+        return result;
+    }
+
+    /*!
+    @brief inserts element
+
+    Inserts element @a val before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] val element to insert
+    @return iterator pointing to the inserted @a val.
+
+    @throw type_error.309 if called on JSON values other than arrays;
+    example: `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+
+    @complexity Constant plus linear in the distance between @a pos and end of
+    the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, const basic_json& val)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // check if iterator pos fits to this JSON value
+            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+            {
+                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
+            }
+
+            // insert to array and return iterator
+            return insert_iterator(pos, val);
+        }
+
+        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief inserts element
+    @copydoc insert(const_iterator, const basic_json&)
+    */
+    iterator insert(const_iterator pos, basic_json&& val)
+    {
+        return insert(pos, val);
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts @a cnt copies of @a val before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] cnt number of copies of @a val to insert
+    @param[in] val element to insert
+    @return iterator pointing to the first element inserted, or @a pos if
+    `cnt==0`
+
+    @throw type_error.309 if called on JSON values other than arrays; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+
+    @complexity Linear in @a cnt plus linear in the distance between @a pos
+    and end of the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert__count}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            // check if iterator pos fits to this JSON value
+            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+            {
+                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
+            }
+
+            // insert to array and return iterator
+            return insert_iterator(pos, cnt, val);
+        }
+
+        JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts elements from range `[first, last)` before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] first begin of the range of elements to insert
+    @param[in] last end of the range of elements to insert
+
+    @throw type_error.309 if called on JSON values other than arrays; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+    @throw invalid_iterator.210 if @a first and @a last do not belong to the
+    same JSON value; example: `"iterators do not fit"`
+    @throw invalid_iterator.211 if @a first or @a last are iterators into
+    container for which insert is called; example: `"passed iterators may not
+    belong to container"`
+
+    @return iterator pointing to the first element inserted, or @a pos if
+    `first==last`
+
+    @complexity Linear in `std::distance(first, last)` plus linear in the
+    distance between @a pos and end of the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert__range}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_UNLIKELY(not is_array()))
+        {
+            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
+        }
+
+        // check if iterator pos fits to this JSON value
+        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
+        {
+            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
+        }
+
+        // insert to array and return iterator
+        return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts elements from initializer list @a ilist before iterator @a pos.
+
+    @param[in] pos iterator before which the content will be inserted; may be
+    the end() iterator
+    @param[in] ilist initializer list to insert the values from
+
+    @throw type_error.309 if called on JSON values other than arrays; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+    example: `"iterator does not fit current value"`
+
+    @return iterator pointing to the first element inserted, or @a pos if
+    `ilist` is empty
+
+    @complexity Linear in `ilist.size()` plus linear in the distance between
+    @a pos and end of the container.
+
+    @liveexample{The example shows how `insert()` is used.,insert__ilist}
+
+    @since version 1.0.0
+    */
+    iterator insert(const_iterator pos, initializer_list_t ilist)
+    {
+        // insert only works for arrays
+        if (JSON_HEDLEY_UNLIKELY(not is_array()))
+        {
+            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
+        }
+
+        // check if iterator pos fits to this JSON value
+        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
+        }
+
+        // insert to array and return iterator
+        return insert_iterator(pos, ilist.begin(), ilist.end());
+    }
+
+    /*!
+    @brief inserts elements
+
+    Inserts elements from range `[first, last)`.
+
+    @param[in] first begin of the range of elements to insert
+    @param[in] last end of the range of elements to insert
+
+    @throw type_error.309 if called on JSON values other than objects; example:
+    `"cannot use insert() with string"`
+    @throw invalid_iterator.202 if iterator @a first or @a last does does not
+    point to an object; example: `"iterators first and last must point to
+    objects"`
+    @throw invalid_iterator.210 if @a first and @a last do not belong to the
+    same JSON value; example: `"iterators do not fit"`
+
+    @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
+    of elements to insert.
+
+    @liveexample{The example shows how `insert()` is used.,insert__range_object}
+
+    @since version 3.0.0
+    */
+    void insert(const_iterator first, const_iterator last)
+    {
+        // insert only works for objects
+        if (JSON_HEDLEY_UNLIKELY(not is_object()))
+        {
+            JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
+        }
+
+        // passed iterators must belong to objects
+        if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object()))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
+        }
+
+        m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
+    }
+
+    /*!
+    @brief updates a JSON object from another object, overwriting existing keys
+
+    Inserts all values from JSON object @a j and overwrites existing keys.
+
+    @param[in] j  JSON object to read values from
+
+    @throw type_error.312 if called on JSON values other than objects; example:
+    `"cannot use update() with string"`
+
+    @complexity O(N*log(size() + N)), where N is the number of elements to
+                insert.
+
+    @liveexample{The example shows how `update()` is used.,update}
+
+    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+    @since version 3.0.0
+    */
+    void update(const_reference j)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(not is_object()))
+        {
+            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
+        }
+        if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
+        {
+            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
+        }
+
+        for (auto it = j.cbegin(); it != j.cend(); ++it)
+        {
+            m_value.object->operator[](it.key()) = it.value();
+        }
+    }
+
+    /*!
+    @brief updates a JSON object from another object, overwriting existing keys
+
+    Inserts all values from from range `[first, last)` and overwrites existing
+    keys.
+
+    @param[in] first begin of the range of elements to insert
+    @param[in] last end of the range of elements to insert
+
+    @throw type_error.312 if called on JSON values other than objects; example:
+    `"cannot use update() with string"`
+    @throw invalid_iterator.202 if iterator @a first or @a last does does not
+    point to an object; example: `"iterators first and last must point to
+    objects"`
+    @throw invalid_iterator.210 if @a first and @a last do not belong to the
+    same JSON value; example: `"iterators do not fit"`
+
+    @complexity O(N*log(size() + N)), where N is the number of elements to
+                insert.
+
+    @liveexample{The example shows how `update()` is used__range.,update}
+
+    @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+    @since version 3.0.0
+    */
+    void update(const_iterator first, const_iterator last)
+    {
+        // implicitly convert null value to an empty object
+        if (is_null())
+        {
+            m_type = value_t::object;
+            m_value.object = create<object_t>();
+            assert_invariant();
+        }
+
+        if (JSON_HEDLEY_UNLIKELY(not is_object()))
+        {
+            JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
+        }
+
+        // check if range iterators belong to the same JSON object
+        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+        {
+            JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
+        }
+
+        // passed iterators must belong to objects
+        if (JSON_HEDLEY_UNLIKELY(not first.m_object->is_object()
+                                 or not last.m_object->is_object()))
+        {
+            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
+        }
+
+        for (auto it = first; it != last; ++it)
+        {
+            m_value.object->operator[](it.key()) = it.value();
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of the JSON value with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other JSON value to exchange the contents with
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how JSON values can be swapped with
+    `swap()`.,swap__reference}
+
+    @since version 1.0.0
+    */
+    void swap(reference other) noexcept (
+        std::is_nothrow_move_constructible<value_t>::value and
+        std::is_nothrow_move_assignable<value_t>::value and
+        std::is_nothrow_move_constructible<json_value>::value and
+        std::is_nothrow_move_assignable<json_value>::value
+    )
+    {
+        std::swap(m_type, other.m_type);
+        std::swap(m_value, other.m_value);
+        assert_invariant();
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON array with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other array to exchange the contents with
+
+    @throw type_error.310 when JSON value is not an array; example: `"cannot
+    use swap() with string"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how arrays can be swapped with
+    `swap()`.,swap__array_t}
+
+    @since version 1.0.0
+    */
+    void swap(array_t& other)
+    {
+        // swap only works for arrays
+        if (JSON_HEDLEY_LIKELY(is_array()))
+        {
+            std::swap(*(m_value.array), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON object with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other object to exchange the contents with
+
+    @throw type_error.310 when JSON value is not an object; example:
+    `"cannot use swap() with string"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how objects can be swapped with
+    `swap()`.,swap__object_t}
+
+    @since version 1.0.0
+    */
+    void swap(object_t& other)
+    {
+        // swap only works for objects
+        if (JSON_HEDLEY_LIKELY(is_object()))
+        {
+            std::swap(*(m_value.object), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
+        }
+    }
+
+    /*!
+    @brief exchanges the values
+
+    Exchanges the contents of a JSON string with those of @a other. Does not
+    invoke any move, copy, or swap operations on individual elements. All
+    iterators and references remain valid. The past-the-end iterator is
+    invalidated.
+
+    @param[in,out] other string to exchange the contents with
+
+    @throw type_error.310 when JSON value is not a string; example: `"cannot
+    use swap() with boolean"`
+
+    @complexity Constant.
+
+    @liveexample{The example below shows how strings can be swapped with
+    `swap()`.,swap__string_t}
+
+    @since version 1.0.0
+    */
+    void swap(string_t& other)
+    {
+        // swap only works for strings
+        if (JSON_HEDLEY_LIKELY(is_string()))
+        {
+            std::swap(*(m_value.string), other);
+        }
+        else
+        {
+            JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
+        }
+    }
+
+    /// @}
+
+  public:
+    //////////////////////////////////////////
+    // lexicographical comparison operators //
+    //////////////////////////////////////////
+
+    /// @name lexicographical comparison operators
+    /// @{
+
+    /*!
+    @brief comparison: equal
+
+    Compares two JSON values for equality according to the following rules:
+    - Two JSON values are equal if (1) they are from the same type and (2)
+      their stored values are the same according to their respective
+      `operator==`.
+    - Integer and floating-point numbers are automatically converted before
+      comparison. Note than two NaN values are always treated as unequal.
+    - Two JSON null values are equal.
+
+    @note Floating-point inside JSON values numbers are compared with
+    `json::number_float_t::operator==` which is `double::operator==` by
+    default. To compare floating-point while respecting an epsilon, an alternative
+    [comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
+    could be used, for instance
+    @code {.cpp}
+    template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
+    inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
+    {
+        return std::abs(a - b) <= epsilon;
+    }
+    @endcode
+
+    @note NaN values never compare equal to themselves or to other NaN values.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether the values @a lhs and @a rhs are equal
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @complexity Linear.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__equal}
+
+    @since version 1.0.0
+    */
+    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
+    {
+        const auto lhs_type = lhs.type();
+        const auto rhs_type = rhs.type();
+
+        if (lhs_type == rhs_type)
+        {
+            switch (lhs_type)
+            {
+                case value_t::array:
+                    return *lhs.m_value.array == *rhs.m_value.array;
+
+                case value_t::object:
+                    return *lhs.m_value.object == *rhs.m_value.object;
+
+                case value_t::null:
+                    return true;
+
+                case value_t::string:
+                    return *lhs.m_value.string == *rhs.m_value.string;
+
+                case value_t::boolean:
+                    return lhs.m_value.boolean == rhs.m_value.boolean;
+
+                case value_t::number_integer:
+                    return lhs.m_value.number_integer == rhs.m_value.number_integer;
+
+                case value_t::number_unsigned:
+                    return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
+
+                case value_t::number_float:
+                    return lhs.m_value.number_float == rhs.m_value.number_float;
+
+                default:
+                    return false;
+            }
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
+        {
+            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+
+        return false;
+    }
+
+    /*!
+    @brief comparison: equal
+    @copydoc operator==(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
+    {
+        return lhs == basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: equal
+    @copydoc operator==(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) == rhs;
+    }
+
+    /*!
+    @brief comparison: not equal
+
+    Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether the values @a lhs and @a rhs are not equal
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__notequal}
+
+    @since version 1.0.0
+    */
+    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
+    {
+        return not (lhs == rhs);
+    }
+
+    /*!
+    @brief comparison: not equal
+    @copydoc operator!=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
+    {
+        return lhs != basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: not equal
+    @copydoc operator!=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) != rhs;
+    }
+
+    /*!
+    @brief comparison: less than
+
+    Compares whether one JSON value @a lhs is less than another JSON value @a
+    rhs according to the following rules:
+    - If @a lhs and @a rhs have the same type, the values are compared using
+      the default `<` operator.
+    - Integer and floating-point numbers are automatically converted before
+      comparison
+    - In case @a lhs and @a rhs have different types, the values are ignored
+      and the order of the types is considered, see
+      @ref operator<(const value_t, const value_t).
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is less than @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__less}
+
+    @since version 1.0.0
+    */
+    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
+    {
+        const auto lhs_type = lhs.type();
+        const auto rhs_type = rhs.type();
+
+        if (lhs_type == rhs_type)
+        {
+            switch (lhs_type)
+            {
+                case value_t::array:
+                    // note parentheses are necessary, see
+                    // https://github.com/nlohmann/json/issues/1530
+                    return (*lhs.m_value.array) < (*rhs.m_value.array);
+
+                case value_t::object:
+                    return (*lhs.m_value.object) < (*rhs.m_value.object);
+
+                case value_t::null:
+                    return false;
+
+                case value_t::string:
+                    return (*lhs.m_value.string) < (*rhs.m_value.string);
+
+                case value_t::boolean:
+                    return (lhs.m_value.boolean) < (rhs.m_value.boolean);
+
+                case value_t::number_integer:
+                    return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
+
+                case value_t::number_unsigned:
+                    return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
+
+                case value_t::number_float:
+                    return (lhs.m_value.number_float) < (rhs.m_value.number_float);
+
+                default:
+                    return false;
+            }
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
+        {
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
+        {
+            return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
+        }
+        else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
+        {
+            return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+        }
+        else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
+        {
+            return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
+        }
+
+        // We only reach this line if we cannot compare values. In that case,
+        // we compare types. Note we have to call the operator explicitly,
+        // because MSVC has problems otherwise.
+        return operator<(lhs_type, rhs_type);
+    }
+
+    /*!
+    @brief comparison: less than
+    @copydoc operator<(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
+    {
+        return lhs < basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: less than
+    @copydoc operator<(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) < rhs;
+    }
+
+    /*!
+    @brief comparison: less than or equal
+
+    Compares whether one JSON value @a lhs is less than or equal to another
+    JSON value by calculating `not (rhs < lhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is less than or equal to @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__greater}
+
+    @since version 1.0.0
+    */
+    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
+    {
+        return not (rhs < lhs);
+    }
+
+    /*!
+    @brief comparison: less than or equal
+    @copydoc operator<=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
+    {
+        return lhs <= basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: less than or equal
+    @copydoc operator<=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) <= rhs;
+    }
+
+    /*!
+    @brief comparison: greater than
+
+    Compares whether one JSON value @a lhs is greater than another
+    JSON value by calculating `not (lhs <= rhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is greater than to @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__lessequal}
+
+    @since version 1.0.0
+    */
+    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
+    {
+        return not (lhs <= rhs);
+    }
+
+    /*!
+    @brief comparison: greater than
+    @copydoc operator>(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
+    {
+        return lhs > basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: greater than
+    @copydoc operator>(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) > rhs;
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+
+    Compares whether one JSON value @a lhs is greater than or equal to another
+    JSON value by calculating `not (lhs < rhs)`.
+
+    @param[in] lhs  first JSON value to consider
+    @param[in] rhs  second JSON value to consider
+    @return whether @a lhs is greater than or equal to @a rhs
+
+    @complexity Linear.
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @liveexample{The example demonstrates comparing several JSON
+    types.,operator__greaterequal}
+
+    @since version 1.0.0
+    */
+    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
+    {
+        return not (lhs < rhs);
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+    @copydoc operator>=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
+    {
+        return lhs >= basic_json(rhs);
+    }
+
+    /*!
+    @brief comparison: greater than or equal
+    @copydoc operator>=(const_reference, const_reference)
+    */
+    template<typename ScalarType, typename std::enable_if<
+                 std::is_scalar<ScalarType>::value, int>::type = 0>
+    friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
+    {
+        return basic_json(lhs) >= rhs;
+    }
+
+    /// @}
+
+    ///////////////////
+    // serialization //
+    ///////////////////
+
+    /// @name serialization
+    /// @{
+
+    /*!
+    @brief serialize to stream
+
+    Serialize the given JSON value @a j to the output stream @a o. The JSON
+    value will be serialized using the @ref dump member function.
+
+    - The indentation of the output can be controlled with the member variable
+      `width` of the output stream @a o. For instance, using the manipulator
+      `std::setw(4)` on @a o sets the indentation level to `4` and the
+      serialization result is the same as calling `dump(4)`.
+
+    - The indentation character can be controlled with the member variable
+      `fill` of the output stream @a o. For instance, the manipulator
+      `std::setfill('\\t')` sets indentation to use a tab character rather than
+      the default space character.
+
+    @param[in,out] o  stream to serialize to
+    @param[in] j  JSON value to serialize
+
+    @return the stream @a o
+
+    @throw type_error.316 if a string stored inside the JSON value is not
+                          UTF-8 encoded
+
+    @complexity Linear.
+
+    @liveexample{The example below shows the serialization with different
+    parameters to `width` to adjust the indentation level.,operator_serialize}
+
+    @since version 1.0.0; indentation character added in version 3.0.0
+    */
+    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
+    {
+        // read width member and use it as indentation parameter if nonzero
+        const bool pretty_print = o.width() > 0;
+        const auto indentation = pretty_print ? o.width() : 0;
+
+        // reset width to 0 for subsequent calls to this stream
+        o.width(0);
+
+        // do the actual serialization
+        serializer s(detail::output_adapter<char>(o), o.fill());
+        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
+        return o;
+    }
+
+    /*!
+    @brief serialize to stream
+    @deprecated This stream operator is deprecated and will be removed in
+                future 4.0.0 of the library. Please use
+                @ref operator<<(std::ostream&, const basic_json&)
+                instead; that is, replace calls like `j >> o;` with `o << j;`.
+    @since version 1.0.0; deprecated since version 3.0.0
+    */
+    JSON_HEDLEY_DEPRECATED(3.0.0)
+    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
+    {
+        return o << j;
+    }
+
+    /// @}
+
+
+    /////////////////////
+    // deserialization //
+    /////////////////////
+
+    /// @name deserialization
+    /// @{
+
+    /*!
+    @brief deserialize from a compatible input
+
+    This function reads from a compatible input. Examples are:
+    - an array of 1-byte values
+    - strings with character/literal type with size of 1 byte
+    - input streams
+    - container with contiguous storage of 1-byte values. Compatible container
+      types include `std::vector`, `std::string`, `std::array`,
+      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
+      arrays can be used with `std::begin()`/`std::end()`. User-defined
+      containers can be used as long as they implement random-access iterators
+      and a contiguous storage.
+
+    @pre Each element of the container has a size of 1 byte. Violating this
+    precondition yields undefined behavior. **This precondition is enforced
+    with a static assertion.**
+
+    @pre The container storage is contiguous. Violating this precondition
+    yields undefined behavior. **This precondition is enforced with an
+    assertion.**
+
+    @warning There is no way to enforce all preconditions at compile-time. If
+             the function is called with a noncompliant container and with
+             assertions switched off, the behavior is undefined and will most
+             likely yield segmentation violation.
+
+    @param[in] i  input to read from
+    @param[in] cb  a parser callback function of type @ref parser_callback_t
+    which is used to control the deserialization by filtering unwanted values
+    (optional)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+    of input; expected string literal""`
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser. The complexity can be higher if the parser callback function
+    @a cb has a super-linear complexity.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below demonstrates the `parse()` function reading
+    from an array.,parse__array__parser_callback_t}
+
+    @liveexample{The example below demonstrates the `parse()` function with
+    and without callback function.,parse__string__parser_callback_t}
+
+    @liveexample{The example below demonstrates the `parse()` function with
+    and without callback function.,parse__istream__parser_callback_t}
+
+    @liveexample{The example below demonstrates the `parse()` function reading
+    from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
+
+    @since version 2.0.3 (contiguous containers)
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json parse(detail::input_adapter&& i,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true)
+    {
+        basic_json result;
+        parser(i, cb, allow_exceptions).parse(true, result);
+        return result;
+    }
+
+    static bool accept(detail::input_adapter&& i)
+    {
+        return parser(i).accept(true);
+    }
+
+    /*!
+    @brief generate SAX events
+
+    The SAX event lister must follow the interface of @ref json_sax.
+
+    This function reads from a compatible input. Examples are:
+    - an array of 1-byte values
+    - strings with character/literal type with size of 1 byte
+    - input streams
+    - container with contiguous storage of 1-byte values. Compatible container
+      types include `std::vector`, `std::string`, `std::array`,
+      `std::valarray`, and `std::initializer_list`. Furthermore, C-style
+      arrays can be used with `std::begin()`/`std::end()`. User-defined
+      containers can be used as long as they implement random-access iterators
+      and a contiguous storage.
+
+    @pre Each element of the container has a size of 1 byte. Violating this
+    precondition yields undefined behavior. **This precondition is enforced
+    with a static assertion.**
+
+    @pre The container storage is contiguous. Violating this precondition
+    yields undefined behavior. **This precondition is enforced with an
+    assertion.**
+
+    @warning There is no way to enforce all preconditions at compile-time. If
+             the function is called with a noncompliant container and with
+             assertions switched off, the behavior is undefined and will most
+             likely yield segmentation violation.
+
+    @param[in] i  input to read from
+    @param[in,out] sax  SAX event listener
+    @param[in] format  the format to parse (JSON, CBOR, MessagePack, or UBJSON)
+    @param[in] strict  whether the input has to be consumed completely
+
+    @return return value of the last processed SAX event
+
+    @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+    of input; expected string literal""`
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
+    a super-linear complexity.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below demonstrates the `sax_parse()` function
+    reading from string and processing the events with a user-defined SAX
+    event consumer.,sax_parse}
+
+    @since version 3.2.0
+    */
+    template <typename SAX>
+    JSON_HEDLEY_NON_NULL(2)
+    static bool sax_parse(detail::input_adapter&& i, SAX* sax,
+                          input_format_t format = input_format_t::json,
+                          const bool strict = true)
+    {
+        assert(sax);
+        return format == input_format_t::json
+               ? parser(std::move(i)).sax_parse(sax, strict)
+               : detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
+    }
+
+    /*!
+    @brief deserialize from an iterator range with contiguous storage
+
+    This function reads from an iterator range of a container with contiguous
+    storage of 1-byte values. Compatible container types include
+    `std::vector`, `std::string`, `std::array`, `std::valarray`, and
+    `std::initializer_list`. Furthermore, C-style arrays can be used with
+    `std::begin()`/`std::end()`. User-defined containers can be used as long
+    as they implement random-access iterators and a contiguous storage.
+
+    @pre The iterator range is contiguous. Violating this precondition yields
+    undefined behavior. **This precondition is enforced with an assertion.**
+    @pre Each element in the range has a size of 1 byte. Violating this
+    precondition yields undefined behavior. **This precondition is enforced
+    with a static assertion.**
+
+    @warning There is no way to enforce all preconditions at compile-time. If
+             the function is called with noncompliant iterators and with
+             assertions switched off, the behavior is undefined and will most
+             likely yield segmentation violation.
+
+    @tparam IteratorType iterator of container with contiguous storage
+    @param[in] first  begin of the range to parse (included)
+    @param[in] last  end of the range to parse (excluded)
+    @param[in] cb  a parser callback function of type @ref parser_callback_t
+    which is used to control the deserialization by filtering unwanted values
+    (optional)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.101 in case of an unexpected token
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser. The complexity can be higher if the parser callback function
+    @a cb has a super-linear complexity.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below demonstrates the `parse()` function reading
+    from an iterator range.,parse__iteratortype__parser_callback_t}
+
+    @since version 2.0.3
+    */
+    template<class IteratorType, typename std::enable_if<
+                 std::is_base_of<
+                     std::random_access_iterator_tag,
+                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+    static basic_json parse(IteratorType first, IteratorType last,
+                            const parser_callback_t cb = nullptr,
+                            const bool allow_exceptions = true)
+    {
+        basic_json result;
+        parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
+        return result;
+    }
+
+    template<class IteratorType, typename std::enable_if<
+                 std::is_base_of<
+                     std::random_access_iterator_tag,
+                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+    static bool accept(IteratorType first, IteratorType last)
+    {
+        return parser(detail::input_adapter(first, last)).accept(true);
+    }
+
+    template<class IteratorType, class SAX, typename std::enable_if<
+                 std::is_base_of<
+                     std::random_access_iterator_tag,
+                     typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+    JSON_HEDLEY_NON_NULL(3)
+    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
+    {
+        return parser(detail::input_adapter(first, last)).sax_parse(sax);
+    }
+
+    /*!
+    @brief deserialize from stream
+    @deprecated This stream operator is deprecated and will be removed in
+                version 4.0.0 of the library. Please use
+                @ref operator>>(std::istream&, basic_json&)
+                instead; that is, replace calls like `j << i;` with `i >> j;`.
+    @since version 1.0.0; deprecated since version 3.0.0
+    */
+    JSON_HEDLEY_DEPRECATED(3.0.0)
+    friend std::istream& operator<<(basic_json& j, std::istream& i)
+    {
+        return operator>>(i, j);
+    }
+
+    /*!
+    @brief deserialize from stream
+
+    Deserializes an input stream to a JSON value.
+
+    @param[in,out] i  input stream to read a serialized JSON value from
+    @param[in,out] j  JSON value to write the deserialized input to
+
+    @throw parse_error.101 in case of an unexpected token
+    @throw parse_error.102 if to_unicode fails or surrogate error
+    @throw parse_error.103 if to_unicode fails
+
+    @complexity Linear in the length of the input. The parser is a predictive
+    LL(1) parser.
+
+    @note A UTF-8 byte order mark is silently ignored.
+
+    @liveexample{The example below shows how a JSON value is constructed by
+    reading a serialization from a stream.,operator_deserialize}
+
+    @sa parse(std::istream&, const parser_callback_t) for a variant with a
+    parser callback function to filter values while parsing
+
+    @since version 1.0.0
+    */
+    friend std::istream& operator>>(std::istream& i, basic_json& j)
+    {
+        parser(detail::input_adapter(i)).parse(false, j);
+        return i;
+    }
+
+    /// @}
+
+    ///////////////////////////
+    // convenience functions //
+    ///////////////////////////
+
+    /*!
+    @brief return the type as string
+
+    Returns the type name as string to be used in error messages - usually to
+    indicate that a function was called on a wrong JSON type.
+
+    @return a string representation of a the @a m_type member:
+            Value type  | return value
+            ----------- | -------------
+            null        | `"null"`
+            boolean     | `"boolean"`
+            string      | `"string"`
+            number      | `"number"` (for all number types)
+            object      | `"object"`
+            array       | `"array"`
+            discarded   | `"discarded"`
+
+    @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+    @complexity Constant.
+
+    @liveexample{The following code exemplifies `type_name()` for all JSON
+    types.,type_name}
+
+    @sa @ref type() -- return the type of the JSON value
+    @sa @ref operator value_t() -- return the type of the JSON value (implicit)
+
+    @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
+    since 3.0.0
+    */
+    JSON_HEDLEY_RETURNS_NON_NULL
+    const char* type_name() const noexcept
+    {
+        {
+            switch (m_type)
+            {
+                case value_t::null:
+                    return "null";
+                case value_t::object:
+                    return "object";
+                case value_t::array:
+                    return "array";
+                case value_t::string:
+                    return "string";
+                case value_t::boolean:
+                    return "boolean";
+                case value_t::discarded:
+                    return "discarded";
+                default:
+                    return "number";
+            }
+        }
+    }
+
+
+  private:
+    //////////////////////
+    // member variables //
+    //////////////////////
+
+    /// the type of the current element
+    value_t m_type = value_t::null;
+
+    /// the value of the current element
+    json_value m_value = {};
+
+    //////////////////////////////////////////
+    // binary serialization/deserialization //
+    //////////////////////////////////////////
+
+    /// @name binary serialization/deserialization support
+    /// @{
+
+  public:
+    /*!
+    @brief create a CBOR serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+    Binary Object Representation) serialization format. CBOR is a binary
+    serialization format which aims to be more compact than JSON itself, yet
+    more efficient to parse.
+
+    The library uses the following mapping from JSON values types to
+    CBOR types according to the CBOR specification (RFC 7049):
+
+    JSON value type | value/range                                | CBOR type                          | first byte
+    --------------- | ------------------------------------------ | ---------------------------------- | ---------------
+    null            | `null`                                     | Null                               | 0xF6
+    boolean         | `true`                                     | True                               | 0xF5
+    boolean         | `false`                                    | False                              | 0xF4
+    number_integer  | -9223372036854775808..-2147483649          | Negative integer (8 bytes follow)  | 0x3B
+    number_integer  | -2147483648..-32769                        | Negative integer (4 bytes follow)  | 0x3A
+    number_integer  | -32768..-129                               | Negative integer (2 bytes follow)  | 0x39
+    number_integer  | -128..-25                                  | Negative integer (1 byte follow)   | 0x38
+    number_integer  | -24..-1                                    | Negative integer                   | 0x20..0x37
+    number_integer  | 0..23                                      | Integer                            | 0x00..0x17
+    number_integer  | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
+    number_integer  | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
+    number_integer  | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
+    number_integer  | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
+    number_unsigned | 0..23                                      | Integer                            | 0x00..0x17
+    number_unsigned | 24..255                                    | Unsigned integer (1 byte follow)   | 0x18
+    number_unsigned | 256..65535                                 | Unsigned integer (2 bytes follow)  | 0x19
+    number_unsigned | 65536..4294967295                          | Unsigned integer (4 bytes follow)  | 0x1A
+    number_unsigned | 4294967296..18446744073709551615           | Unsigned integer (8 bytes follow)  | 0x1B
+    number_float    | *any value*                                | Double-Precision Float             | 0xFB
+    string          | *length*: 0..23                            | UTF-8 string                       | 0x60..0x77
+    string          | *length*: 23..255                          | UTF-8 string (1 byte follow)       | 0x78
+    string          | *length*: 256..65535                       | UTF-8 string (2 bytes follow)      | 0x79
+    string          | *length*: 65536..4294967295                | UTF-8 string (4 bytes follow)      | 0x7A
+    string          | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow)      | 0x7B
+    array           | *size*: 0..23                              | array                              | 0x80..0x97
+    array           | *size*: 23..255                            | array (1 byte follow)              | 0x98
+    array           | *size*: 256..65535                         | array (2 bytes follow)             | 0x99
+    array           | *size*: 65536..4294967295                  | array (4 bytes follow)             | 0x9A
+    array           | *size*: 4294967296..18446744073709551615   | array (8 bytes follow)             | 0x9B
+    object          | *size*: 0..23                              | map                                | 0xA0..0xB7
+    object          | *size*: 23..255                            | map (1 byte follow)                | 0xB8
+    object          | *size*: 256..65535                         | map (2 bytes follow)               | 0xB9
+    object          | *size*: 65536..4294967295                  | map (4 bytes follow)               | 0xBA
+    object          | *size*: 4294967296..18446744073709551615   | map (8 bytes follow)               | 0xBB
+
+    @note The mapping is **complete** in the sense that any JSON value type
+          can be converted to a CBOR value.
+
+    @note If NaN or Infinity are stored inside a JSON number, they are
+          serialized properly. This behavior differs from the @ref dump()
+          function which serializes NaN or Infinity to `null`.
+
+    @note The following CBOR types are not used in the conversion:
+          - byte strings (0x40..0x5F)
+          - UTF-8 strings terminated by "break" (0x7F)
+          - arrays terminated by "break" (0x9F)
+          - maps terminated by "break" (0xBF)
+          - date/time (0xC0..0xC1)
+          - bignum (0xC2..0xC3)
+          - decimal fraction (0xC4)
+          - bigfloat (0xC5)
+          - tagged items (0xC6..0xD4, 0xD8..0xDB)
+          - expected conversions (0xD5..0xD7)
+          - simple values (0xE0..0xF3, 0xF8)
+          - undefined (0xF7)
+          - half and single-precision floats (0xF9-0xFA)
+          - break (0xFF)
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in CBOR format.,to_cbor}
+
+    @sa http://cbor.io
+    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
+        analogous deserialization
+    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
+    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             related UBJSON format
+
+    @since version 2.0.9
+    */
+    static std::vector<uint8_t> to_cbor(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_cbor(j, result);
+        return result;
+    }
+
+    static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
+    {
+        binary_writer<uint8_t>(o).write_cbor(j);
+    }
+
+    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_cbor(j);
+    }
+
+    /*!
+    @brief create a MessagePack serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the MessagePack
+    serialization format. MessagePack is a binary serialization format which
+    aims to be more compact than JSON itself, yet more efficient to parse.
+
+    The library uses the following mapping from JSON values types to
+    MessagePack types according to the MessagePack specification:
+
+    JSON value type | value/range                       | MessagePack type | first byte
+    --------------- | --------------------------------- | ---------------- | ----------
+    null            | `null`                            | nil              | 0xC0
+    boolean         | `true`                            | true             | 0xC3
+    boolean         | `false`                           | false            | 0xC2
+    number_integer  | -9223372036854775808..-2147483649 | int64            | 0xD3
+    number_integer  | -2147483648..-32769               | int32            | 0xD2
+    number_integer  | -32768..-129                      | int16            | 0xD1
+    number_integer  | -128..-33                         | int8             | 0xD0
+    number_integer  | -32..-1                           | negative fixint  | 0xE0..0xFF
+    number_integer  | 0..127                            | positive fixint  | 0x00..0x7F
+    number_integer  | 128..255                          | uint 8           | 0xCC
+    number_integer  | 256..65535                        | uint 16          | 0xCD
+    number_integer  | 65536..4294967295                 | uint 32          | 0xCE
+    number_integer  | 4294967296..18446744073709551615  | uint 64          | 0xCF
+    number_unsigned | 0..127                            | positive fixint  | 0x00..0x7F
+    number_unsigned | 128..255                          | uint 8           | 0xCC
+    number_unsigned | 256..65535                        | uint 16          | 0xCD
+    number_unsigned | 65536..4294967295                 | uint 32          | 0xCE
+    number_unsigned | 4294967296..18446744073709551615  | uint 64          | 0xCF
+    number_float    | *any value*                       | float 64         | 0xCB
+    string          | *length*: 0..31                   | fixstr           | 0xA0..0xBF
+    string          | *length*: 32..255                 | str 8            | 0xD9
+    string          | *length*: 256..65535              | str 16           | 0xDA
+    string          | *length*: 65536..4294967295       | str 32           | 0xDB
+    array           | *size*: 0..15                     | fixarray         | 0x90..0x9F
+    array           | *size*: 16..65535                 | array 16         | 0xDC
+    array           | *size*: 65536..4294967295         | array 32         | 0xDD
+    object          | *size*: 0..15                     | fix map          | 0x80..0x8F
+    object          | *size*: 16..65535                 | map 16           | 0xDE
+    object          | *size*: 65536..4294967295         | map 32           | 0xDF
+
+    @note The mapping is **complete** in the sense that any JSON value type
+          can be converted to a MessagePack value.
+
+    @note The following values can **not** be converted to a MessagePack value:
+          - strings with more than 4294967295 bytes
+          - arrays with more than 4294967295 elements
+          - objects with more than 4294967295 elements
+
+    @note The following MessagePack types are not used in the conversion:
+          - bin 8 - bin 32 (0xC4..0xC6)
+          - ext 8 - ext 32 (0xC7..0xC9)
+          - float 32 (0xCA)
+          - fixext 1 - fixext 16 (0xD4..0xD8)
+
+    @note Any MessagePack output created @ref to_msgpack can be successfully
+          parsed by @ref from_msgpack.
+
+    @note If NaN or Infinity are stored inside a JSON number, they are
+          serialized properly. This behavior differs from the @ref dump()
+          function which serializes NaN or Infinity to `null`.
+
+    @param[in] j  JSON value to serialize
+    @return MessagePack serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in MessagePack format.,to_msgpack}
+
+    @sa http://msgpack.org
+    @sa @ref from_msgpack for the analogous deserialization
+    @sa @ref to_cbor(const basic_json& for the related CBOR format
+    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             related UBJSON format
+
+    @since version 2.0.9
+    */
+    static std::vector<uint8_t> to_msgpack(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_msgpack(j, result);
+        return result;
+    }
+
+    static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
+    {
+        binary_writer<uint8_t>(o).write_msgpack(j);
+    }
+
+    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_msgpack(j);
+    }
+
+    /*!
+    @brief create a UBJSON serialization of a given JSON value
+
+    Serializes a given JSON value @a j to a byte vector using the UBJSON
+    (Universal Binary JSON) serialization format. UBJSON aims to be more compact
+    than JSON itself, yet more efficient to parse.
+
+    The library uses the following mapping from JSON values types to
+    UBJSON types according to the UBJSON specification:
+
+    JSON value type | value/range                       | UBJSON type | marker
+    --------------- | --------------------------------- | ----------- | ------
+    null            | `null`                            | null        | `Z`
+    boolean         | `true`                            | true        | `T`
+    boolean         | `false`                           | false       | `F`
+    number_integer  | -9223372036854775808..-2147483649 | int64       | `L`
+    number_integer  | -2147483648..-32769               | int32       | `l`
+    number_integer  | -32768..-129                      | int16       | `I`
+    number_integer  | -128..127                         | int8        | `i`
+    number_integer  | 128..255                          | uint8       | `U`
+    number_integer  | 256..32767                        | int16       | `I`
+    number_integer  | 32768..2147483647                 | int32       | `l`
+    number_integer  | 2147483648..9223372036854775807   | int64       | `L`
+    number_unsigned | 0..127                            | int8        | `i`
+    number_unsigned | 128..255                          | uint8       | `U`
+    number_unsigned | 256..32767                        | int16       | `I`
+    number_unsigned | 32768..2147483647                 | int32       | `l`
+    number_unsigned | 2147483648..9223372036854775807   | int64       | `L`
+    number_float    | *any value*                       | float64     | `D`
+    string          | *with shortest length indicator*  | string      | `S`
+    array           | *see notes on optimized format*   | array       | `[`
+    object          | *see notes on optimized format*   | map         | `{`
+
+    @note The mapping is **complete** in the sense that any JSON value type
+          can be converted to a UBJSON value.
+
+    @note The following values can **not** be converted to a UBJSON value:
+          - strings with more than 9223372036854775807 bytes (theoretical)
+          - unsigned integer numbers above 9223372036854775807
+
+    @note The following markers are not used in the conversion:
+          - `Z`: no-op values are not created.
+          - `C`: single-byte strings are serialized with `S` markers.
+
+    @note Any UBJSON output created @ref to_ubjson can be successfully parsed
+          by @ref from_ubjson.
+
+    @note If NaN or Infinity are stored inside a JSON number, they are
+          serialized properly. This behavior differs from the @ref dump()
+          function which serializes NaN or Infinity to `null`.
+
+    @note The optimized formats for containers are supported: Parameter
+          @a use_size adds size information to the beginning of a container and
+          removes the closing marker. Parameter @a use_type further checks
+          whether all elements of a container have the same type and adds the
+          type marker to the beginning of the container. The @a use_type
+          parameter must only be used together with @a use_size = true. Note
+          that @a use_size = true alone may result in larger representations -
+          the benefit of this parameter is that the receiving side is
+          immediately informed on the number of elements of the container.
+
+    @param[in] j  JSON value to serialize
+    @param[in] use_size  whether to add size annotations to container types
+    @param[in] use_type  whether to add type annotations to container types
+                         (must be combined with @a use_size = true)
+    @return UBJSON serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in UBJSON format.,to_ubjson}
+
+    @sa http://ubjson.org
+    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
+        analogous deserialization
+    @sa @ref to_cbor(const basic_json& for the related CBOR format
+    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
+
+    @since version 3.1.0
+    */
+    static std::vector<uint8_t> to_ubjson(const basic_json& j,
+                                          const bool use_size = false,
+                                          const bool use_type = false)
+    {
+        std::vector<uint8_t> result;
+        to_ubjson(j, result, use_size, use_type);
+        return result;
+    }
+
+    static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
+    }
+
+    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
+                          const bool use_size = false, const bool use_type = false)
+    {
+        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
+    }
+
+
+    /*!
+    @brief Serializes the given JSON object `j` to BSON and returns a vector
+           containing the corresponding BSON-representation.
+
+    BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
+    stored as a single entity (a so-called document).
+
+    The library uses the following mapping from JSON values types to BSON types:
+
+    JSON value type | value/range                       | BSON type   | marker
+    --------------- | --------------------------------- | ----------- | ------
+    null            | `null`                            | null        | 0x0A
+    boolean         | `true`, `false`                   | boolean     | 0x08
+    number_integer  | -9223372036854775808..-2147483649 | int64       | 0x12
+    number_integer  | -2147483648..2147483647           | int32       | 0x10
+    number_integer  | 2147483648..9223372036854775807   | int64       | 0x12
+    number_unsigned | 0..2147483647                     | int32       | 0x10
+    number_unsigned | 2147483648..9223372036854775807   | int64       | 0x12
+    number_unsigned | 9223372036854775808..18446744073709551615| --   | --
+    number_float    | *any value*                       | double      | 0x01
+    string          | *any value*                       | string      | 0x02
+    array           | *any value*                       | document    | 0x04
+    object          | *any value*                       | document    | 0x03
+
+    @warning The mapping is **incomplete**, since only JSON-objects (and things
+    contained therein) can be serialized to BSON.
+    Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
+    and the keys may not contain U+0000, since they are serialized a
+    zero-terminated c-strings.
+
+    @throw out_of_range.407  if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
+    @throw out_of_range.409  if a key in `j` contains a NULL (U+0000)
+    @throw type_error.317    if `!j.is_object()`
+
+    @pre The input `j` is required to be an object: `j.is_object() == true`.
+
+    @note Any BSON output created via @ref to_bson can be successfully parsed
+          by @ref from_bson.
+
+    @param[in] j  JSON value to serialize
+    @return BSON serialization as byte vector
+
+    @complexity Linear in the size of the JSON value @a j.
+
+    @liveexample{The example shows the serialization of a JSON value to a byte
+    vector in BSON format.,to_bson}
+
+    @sa http://bsonspec.org/spec.html
+    @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the
+        analogous deserialization
+    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             related UBJSON format
+    @sa @ref to_cbor(const basic_json&) for the related CBOR format
+    @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
+    */
+    static std::vector<uint8_t> to_bson(const basic_json& j)
+    {
+        std::vector<uint8_t> result;
+        to_bson(j, result);
+        return result;
+    }
+
+    /*!
+    @brief Serializes the given JSON object `j` to BSON and forwards the
+           corresponding BSON-representation to the given output_adapter `o`.
+    @param j The JSON object to convert to BSON.
+    @param o The output adapter that receives the binary BSON representation.
+    @pre The input `j` shall be an object: `j.is_object() == true`
+    @sa @ref to_bson(const basic_json&)
+    */
+    static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
+    {
+        binary_writer<uint8_t>(o).write_bson(j);
+    }
+
+    /*!
+    @copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
+    */
+    static void to_bson(const basic_json& j, detail::output_adapter<char> o)
+    {
+        binary_writer<char>(o).write_bson(j);
+    }
+
+
+    /*!
+    @brief create a JSON value from an input in CBOR format
+
+    Deserializes a given input @a i to a JSON value using the CBOR (Concise
+    Binary Object Representation) serialization format.
+
+    The library maps CBOR types to JSON value types as follows:
+
+    CBOR type              | JSON value type | first byte
+    ---------------------- | --------------- | ----------
+    Integer                | number_unsigned | 0x00..0x17
+    Unsigned integer       | number_unsigned | 0x18
+    Unsigned integer       | number_unsigned | 0x19
+    Unsigned integer       | number_unsigned | 0x1A
+    Unsigned integer       | number_unsigned | 0x1B
+    Negative integer       | number_integer  | 0x20..0x37
+    Negative integer       | number_integer  | 0x38
+    Negative integer       | number_integer  | 0x39
+    Negative integer       | number_integer  | 0x3A
+    Negative integer       | number_integer  | 0x3B
+    Negative integer       | number_integer  | 0x40..0x57
+    UTF-8 string           | string          | 0x60..0x77
+    UTF-8 string           | string          | 0x78
+    UTF-8 string           | string          | 0x79
+    UTF-8 string           | string          | 0x7A
+    UTF-8 string           | string          | 0x7B
+    UTF-8 string           | string          | 0x7F
+    array                  | array           | 0x80..0x97
+    array                  | array           | 0x98
+    array                  | array           | 0x99
+    array                  | array           | 0x9A
+    array                  | array           | 0x9B
+    array                  | array           | 0x9F
+    map                    | object          | 0xA0..0xB7
+    map                    | object          | 0xB8
+    map                    | object          | 0xB9
+    map                    | object          | 0xBA
+    map                    | object          | 0xBB
+    map                    | object          | 0xBF
+    False                  | `false`         | 0xF4
+    True                   | `true`          | 0xF5
+    Null                   | `null`          | 0xF6
+    Half-Precision Float   | number_float    | 0xF9
+    Single-Precision Float | number_float    | 0xFA
+    Double-Precision Float | number_float    | 0xFB
+
+    @warning The mapping is **incomplete** in the sense that not all CBOR
+             types can be converted to a JSON value. The following CBOR types
+             are not supported and will yield parse errors (parse_error.112):
+             - byte strings (0x40..0x5F)
+             - date/time (0xC0..0xC1)
+             - bignum (0xC2..0xC3)
+             - decimal fraction (0xC4)
+             - bigfloat (0xC5)
+             - tagged items (0xC6..0xD4, 0xD8..0xDB)
+             - expected conversions (0xD5..0xD7)
+             - simple values (0xE0..0xF3, 0xF8)
+             - undefined (0xF7)
+
+    @warning CBOR allows map keys of any type, whereas JSON only allows
+             strings as keys in object values. Therefore, CBOR maps with keys
+             other than UTF-8 strings are rejected (parse_error.113).
+
+    @note Any CBOR output created @ref to_cbor can be successfully parsed by
+          @ref from_cbor.
+
+    @param[in] i  an input in CBOR format convertible to an input adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.110 if the given input ends prematurely or the end of
+    file was not reached when @a strict was set to true
+    @throw parse_error.112 if unsupported features from CBOR were
+    used in the given input @a v or if the input is not valid CBOR
+    @throw parse_error.113 if a string was expected as map key, but not found
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in CBOR
+    format to a JSON value.,from_cbor}
+
+    @sa http://cbor.io
+    @sa @ref to_cbor(const basic_json&) for the analogous serialization
+    @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the
+        related MessagePack format
+    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
+        related UBJSON format
+
+    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+           consume input adapters, removed start_index parameter, and added
+           @a strict parameter since 3.0.0; added @a allow_exceptions parameter
+           since 3.2.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_cbor(detail::input_adapter&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_cbor(detail::input_adapter&&, const bool, const bool)
+    */
+    template<typename A1, typename A2,
+             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_cbor(A1 && a1, A2 && a2,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @brief create a JSON value from an input in MessagePack format
+
+    Deserializes a given input @a i to a JSON value using the MessagePack
+    serialization format.
+
+    The library maps MessagePack types to JSON value types as follows:
+
+    MessagePack type | JSON value type | first byte
+    ---------------- | --------------- | ----------
+    positive fixint  | number_unsigned | 0x00..0x7F
+    fixmap           | object          | 0x80..0x8F
+    fixarray         | array           | 0x90..0x9F
+    fixstr           | string          | 0xA0..0xBF
+    nil              | `null`          | 0xC0
+    false            | `false`         | 0xC2
+    true             | `true`          | 0xC3
+    float 32         | number_float    | 0xCA
+    float 64         | number_float    | 0xCB
+    uint 8           | number_unsigned | 0xCC
+    uint 16          | number_unsigned | 0xCD
+    uint 32          | number_unsigned | 0xCE
+    uint 64          | number_unsigned | 0xCF
+    int 8            | number_integer  | 0xD0
+    int 16           | number_integer  | 0xD1
+    int 32           | number_integer  | 0xD2
+    int 64           | number_integer  | 0xD3
+    str 8            | string          | 0xD9
+    str 16           | string          | 0xDA
+    str 32           | string          | 0xDB
+    array 16         | array           | 0xDC
+    array 32         | array           | 0xDD
+    map 16           | object          | 0xDE
+    map 32           | object          | 0xDF
+    negative fixint  | number_integer  | 0xE0-0xFF
+
+    @warning The mapping is **incomplete** in the sense that not all
+             MessagePack types can be converted to a JSON value. The following
+             MessagePack types are not supported and will yield parse errors:
+              - bin 8 - bin 32 (0xC4..0xC6)
+              - ext 8 - ext 32 (0xC7..0xC9)
+              - fixext 1 - fixext 16 (0xD4..0xD8)
+
+    @note Any MessagePack output created @ref to_msgpack can be successfully
+          parsed by @ref from_msgpack.
+
+    @param[in] i  an input in MessagePack format convertible to an input
+                  adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.110 if the given input ends prematurely or the end of
+    file was not reached when @a strict was set to true
+    @throw parse_error.112 if unsupported features from MessagePack were
+    used in the given input @a i or if the input is not valid MessagePack
+    @throw parse_error.113 if a string was expected as map key, but not found
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    MessagePack format to a JSON value.,from_msgpack}
+
+    @sa http://msgpack.org
+    @sa @ref to_msgpack(const basic_json&) for the analogous serialization
+    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
+        related CBOR format
+    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
+        the related UBJSON format
+    @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
+        the related BSON format
+
+    @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+           consume input adapters, removed start_index parameter, and added
+           @a strict parameter since 3.0.0; added @a allow_exceptions parameter
+           since 3.2.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_msgpack(detail::input_adapter&& i,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool)
+    */
+    template<typename A1, typename A2,
+             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_msgpack(A1 && a1, A2 && a2,
+                                   const bool strict = true,
+                                   const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @brief create a JSON value from an input in UBJSON format
+
+    Deserializes a given input @a i to a JSON value using the UBJSON (Universal
+    Binary JSON) serialization format.
+
+    The library maps UBJSON types to JSON value types as follows:
+
+    UBJSON type | JSON value type                         | marker
+    ----------- | --------------------------------------- | ------
+    no-op       | *no value, next value is read*          | `N`
+    null        | `null`                                  | `Z`
+    false       | `false`                                 | `F`
+    true        | `true`                                  | `T`
+    float32     | number_float                            | `d`
+    float64     | number_float                            | `D`
+    uint8       | number_unsigned                         | `U`
+    int8        | number_integer                          | `i`
+    int16       | number_integer                          | `I`
+    int32       | number_integer                          | `l`
+    int64       | number_integer                          | `L`
+    string      | string                                  | `S`
+    char        | string                                  | `C`
+    array       | array (optimized values are supported)  | `[`
+    object      | object (optimized values are supported) | `{`
+
+    @note The mapping is **complete** in the sense that any UBJSON value can
+          be converted to a JSON value.
+
+    @param[in] i  an input in UBJSON format convertible to an input adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.110 if the given input ends prematurely or the end of
+    file was not reached when @a strict was set to true
+    @throw parse_error.112 if a parse error occurs
+    @throw parse_error.113 if a string could not be parsed successfully
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    UBJSON format to a JSON value.,from_ubjson}
+
+    @sa http://ubjson.org
+    @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
+             analogous serialization
+    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
+        related CBOR format
+    @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
+        the related MessagePack format
+    @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for
+        the related BSON format
+
+    @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_ubjson(detail::input_adapter&& i,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool)
+    */
+    template<typename A1, typename A2,
+             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_ubjson(A1 && a1, A2 && a2,
+                                  const bool strict = true,
+                                  const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @brief Create a JSON value from an input in BSON format
+
+    Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
+    serialization format.
+
+    The library maps BSON record types to JSON value types as follows:
+
+    BSON type       | BSON marker byte | JSON value type
+    --------------- | ---------------- | ---------------------------
+    double          | 0x01             | number_float
+    string          | 0x02             | string
+    document        | 0x03             | object
+    array           | 0x04             | array
+    binary          | 0x05             | still unsupported
+    undefined       | 0x06             | still unsupported
+    ObjectId        | 0x07             | still unsupported
+    boolean         | 0x08             | boolean
+    UTC Date-Time   | 0x09             | still unsupported
+    null            | 0x0A             | null
+    Regular Expr.   | 0x0B             | still unsupported
+    DB Pointer      | 0x0C             | still unsupported
+    JavaScript Code | 0x0D             | still unsupported
+    Symbol          | 0x0E             | still unsupported
+    JavaScript Code | 0x0F             | still unsupported
+    int32           | 0x10             | number_integer
+    Timestamp       | 0x11             | still unsupported
+    128-bit decimal float | 0x13       | still unsupported
+    Max Key         | 0x7F             | still unsupported
+    Min Key         | 0xFF             | still unsupported
+
+    @warning The mapping is **incomplete**. The unsupported mappings
+             are indicated in the table above.
+
+    @param[in] i  an input in BSON format convertible to an input adapter
+    @param[in] strict  whether to expect the input to be consumed until EOF
+                       (true by default)
+    @param[in] allow_exceptions  whether to throw exceptions in case of a
+    parse error (optional, true by default)
+
+    @return deserialized JSON value; in case of a parse error and
+            @a allow_exceptions set to `false`, the return value will be
+            value_t::discarded.
+
+    @throw parse_error.114 if an unsupported BSON record type is encountered
+
+    @complexity Linear in the size of the input @a i.
+
+    @liveexample{The example shows the deserialization of a byte vector in
+    BSON format to a JSON value.,from_bson}
+
+    @sa http://bsonspec.org/spec.html
+    @sa @ref to_bson(const basic_json&) for the analogous serialization
+    @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the
+        related CBOR format
+    @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
+        the related MessagePack format
+    @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
+        related UBJSON format
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bson(detail::input_adapter&& i,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+    /*!
+    @copydoc from_bson(detail::input_adapter&&, const bool, const bool)
+    */
+    template<typename A1, typename A2,
+             detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json from_bson(A1 && a1, A2 && a2,
+                                const bool strict = true,
+                                const bool allow_exceptions = true)
+    {
+        basic_json result;
+        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+        const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
+        return res ? result : basic_json(value_t::discarded);
+    }
+
+
+
+    /// @}
+
+    //////////////////////////
+    // JSON Pointer support //
+    //////////////////////////
+
+    /// @name JSON Pointer functions
+    /// @{
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Uses a JSON pointer to retrieve a reference to the respective JSON value.
+    No bound checking is performed. Similar to @ref operator[](const typename
+    object_t::key_type&), `null` values are created in arrays and objects if
+    necessary.
+
+    In particular:
+    - If the JSON pointer points to an object key that does not exist, it
+      is created an filled with a `null` value before a reference to it
+      is returned.
+    - If the JSON pointer points to an array index that does not exist, it
+      is created an filled with a `null` value before a reference to it
+      is returned. All indices between the current maximum and the given
+      index are also filled with `null`.
+    - The special value `-` is treated as a synonym for the index past the
+      end.
+
+    @param[in] ptr  a JSON pointer
+
+    @return reference to the element pointed to by @a ptr
+
+    @complexity Constant.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+
+    @liveexample{The behavior is shown in the example.,operatorjson_pointer}
+
+    @since version 2.0.0
+    */
+    reference operator[](const json_pointer& ptr)
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Uses a JSON pointer to retrieve a reference to the respective JSON value.
+    No bound checking is performed. The function does not change the JSON
+    value; no `null` values are created. In particular, the the special value
+    `-` yields an exception.
+
+    @param[in] ptr  JSON pointer to the desired element
+
+    @return const reference to the element pointed to by @a ptr
+
+    @complexity Constant.
+
+    @throw parse_error.106   if an array index begins with '0'
+    @throw parse_error.109   if an array index was not a number
+    @throw out_of_range.402  if the array index '-' is used
+    @throw out_of_range.404  if the JSON pointer can not be resolved
+
+    @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
+
+    @since version 2.0.0
+    */
+    const_reference operator[](const json_pointer& ptr) const
+    {
+        return ptr.get_unchecked(this);
+    }
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Returns a reference to the element at with specified JSON pointer @a ptr,
+    with bounds checking.
+
+    @param[in] ptr  JSON pointer to the desired element
+
+    @return reference to the element pointed to by @a ptr
+
+    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+    begins with '0'. See example below.
+
+    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+    is not a number. See example below.
+
+    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+    is out of range. See example below.
+
+    @throw out_of_range.402 if the array index '-' is used in the passed JSON
+    pointer @a ptr. As `at` provides checked access (and no elements are
+    implicitly inserted), the index '-' is always invalid. See example below.
+
+    @throw out_of_range.403 if the JSON pointer describes a key of an object
+    which cannot be found. See example below.
+
+    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+    See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 2.0.0
+
+    @liveexample{The behavior is shown in the example.,at_json_pointer}
+    */
+    reference at(const json_pointer& ptr)
+    {
+        return ptr.get_checked(this);
+    }
+
+    /*!
+    @brief access specified element via JSON Pointer
+
+    Returns a const reference to the element at with specified JSON pointer @a
+    ptr, with bounds checking.
+
+    @param[in] ptr  JSON pointer to the desired element
+
+    @return reference to the element pointed to by @a ptr
+
+    @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+    begins with '0'. See example below.
+
+    @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+    is not a number. See example below.
+
+    @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+    is out of range. See example below.
+
+    @throw out_of_range.402 if the array index '-' is used in the passed JSON
+    pointer @a ptr. As `at` provides checked access (and no elements are
+    implicitly inserted), the index '-' is always invalid. See example below.
+
+    @throw out_of_range.403 if the JSON pointer describes a key of an object
+    which cannot be found. See example below.
+
+    @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+    See example below.
+
+    @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+    changes in the JSON value.
+
+    @complexity Constant.
+
+    @since version 2.0.0
+
+    @liveexample{The behavior is shown in the example.,at_json_pointer_const}
+    */
+    const_reference at(const json_pointer& ptr) const
+    {
+        return ptr.get_checked(this);
+    }
+
+    /*!
+    @brief return flattened JSON value
+
+    The function creates a JSON object whose keys are JSON pointers (see [RFC
+    6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
+    primitive. The original JSON value can be restored using the @ref
+    unflatten() function.
+
+    @return an object that maps JSON pointers to primitive values
+
+    @note Empty objects and arrays are flattened to `null` and will not be
+          reconstructed correctly by the @ref unflatten() function.
+
+    @complexity Linear in the size the JSON value.
+
+    @liveexample{The following code shows how a JSON object is flattened to an
+    object whose keys consist of JSON pointers.,flatten}
+
+    @sa @ref unflatten() for the reverse function
+
+    @since version 2.0.0
+    */
+    basic_json flatten() const
+    {
+        basic_json result(value_t::object);
+        json_pointer::flatten("", *this, result);
+        return result;
+    }
+
+    /*!
+    @brief unflatten a previously flattened JSON value
+
+    The function restores the arbitrary nesting of a JSON value that has been
+    flattened before using the @ref flatten() function. The JSON value must
+    meet certain constraints:
+    1. The value must be an object.
+    2. The keys must be JSON pointers (see
+       [RFC 6901](https://tools.ietf.org/html/rfc6901))
+    3. The mapped values must be primitive JSON types.
+
+    @return the original JSON from a flattened version
+
+    @note Empty objects and arrays are flattened by @ref flatten() to `null`
+          values and can not unflattened to their original type. Apart from
+          this example, for a JSON value `j`, the following is always true:
+          `j == j.flatten().unflatten()`.
+
+    @complexity Linear in the size the JSON value.
+
+    @throw type_error.314  if value is not an object
+    @throw type_error.315  if object values are not primitive
+
+    @liveexample{The following code shows how a flattened JSON object is
+    unflattened into the original nested JSON object.,unflatten}
+
+    @sa @ref flatten() for the reverse function
+
+    @since version 2.0.0
+    */
+    basic_json unflatten() const
+    {
+        return json_pointer::unflatten(*this);
+    }
+
+    /// @}
+
+    //////////////////////////
+    // JSON Patch functions //
+    //////////////////////////
+
+    /// @name JSON Patch functions
+    /// @{
+
+    /*!
+    @brief applies a JSON patch
+
+    [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
+    expressing a sequence of operations to apply to a JSON) document. With
+    this function, a JSON Patch is applied to the current JSON value by
+    executing all operations from the patch.
+
+    @param[in] json_patch  JSON patch document
+    @return patched document
+
+    @note The application of a patch is atomic: Either all operations succeed
+          and the patched document is returned or an exception is thrown. In
+          any case, the original value is not changed: the patch is applied
+          to a copy of the value.
+
+    @throw parse_error.104 if the JSON patch does not consist of an array of
+    objects
+
+    @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
+    attributes are missing); example: `"operation add must have member path"`
+
+    @throw out_of_range.401 if an array index is out of range.
+
+    @throw out_of_range.403 if a JSON pointer inside the patch could not be
+    resolved successfully in the current JSON value; example: `"key baz not
+    found"`
+
+    @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
+    "move")
+
+    @throw other_error.501 if "test" operation was unsuccessful
+
+    @complexity Linear in the size of the JSON value and the length of the
+    JSON patch. As usually only a fraction of the JSON value is affected by
+    the patch, the complexity can usually be neglected.
+
+    @liveexample{The following code shows how a JSON patch is applied to a
+    value.,patch}
+
+    @sa @ref diff -- create a JSON patch by comparing two JSON values
+
+    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
+    @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
+
+    @since version 2.0.0
+    */
+    basic_json patch(const basic_json& json_patch) const
+    {
+        // make a working copy to apply the patch to
+        basic_json result = *this;
+
+        // the valid JSON Patch operations
+        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
+
+        const auto get_op = [](const std::string & op)
+        {
+            if (op == "add")
+            {
+                return patch_operations::add;
+            }
+            if (op == "remove")
+            {
+                return patch_operations::remove;
+            }
+            if (op == "replace")
+            {
+                return patch_operations::replace;
+            }
+            if (op == "move")
+            {
+                return patch_operations::move;
+            }
+            if (op == "copy")
+            {
+                return patch_operations::copy;
+            }
+            if (op == "test")
+            {
+                return patch_operations::test;
+            }
+
+            return patch_operations::invalid;
+        };
+
+        // wrapper for "add" operation; add value at ptr
+        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
+        {
+            // adding to the root of the target document means replacing it
+            if (ptr.empty())
+            {
+                result = val;
+                return;
+            }
+
+            // make sure the top element of the pointer exists
+            json_pointer top_pointer = ptr.top();
+            if (top_pointer != ptr)
+            {
+                result.at(top_pointer);
+            }
+
+            // get reference to parent of JSON pointer ptr
+            const auto last_path = ptr.back();
+            ptr.pop_back();
+            basic_json& parent = result[ptr];
+
+            switch (parent.m_type)
+            {
+                case value_t::null:
+                case value_t::object:
+                {
+                    // use operator[] to add value
+                    parent[last_path] = val;
+                    break;
+                }
+
+                case value_t::array:
+                {
+                    if (last_path == "-")
+                    {
+                        // special case: append to back
+                        parent.push_back(val);
+                    }
+                    else
+                    {
+                        const auto idx = json_pointer::array_index(last_path);
+                        if (JSON_HEDLEY_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
+                        {
+                            // avoid undefined behavior
+                            JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
+                        }
+
+                        // default case: insert add offset
+                        parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
+                    }
+                    break;
+                }
+
+                // if there exists a parent it cannot be primitive
+                default:            // LCOV_EXCL_LINE
+                    assert(false);  // LCOV_EXCL_LINE
+            }
+        };
+
+        // wrapper for "remove" operation; remove value at ptr
+        const auto operation_remove = [&result](json_pointer & ptr)
+        {
+            // get reference to parent of JSON pointer ptr
+            const auto last_path = ptr.back();
+            ptr.pop_back();
+            basic_json& parent = result.at(ptr);
+
+            // remove child
+            if (parent.is_object())
+            {
+                // perform range check
+                auto it = parent.find(last_path);
+                if (JSON_HEDLEY_LIKELY(it != parent.end()))
+                {
+                    parent.erase(it);
+                }
+                else
+                {
+                    JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
+                }
+            }
+            else if (parent.is_array())
+            {
+                // note erase performs range check
+                parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
+            }
+        };
+
+        // type check: top level value must be an array
+        if (JSON_HEDLEY_UNLIKELY(not json_patch.is_array()))
+        {
+            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
+        }
+
+        // iterate and apply the operations
+        for (const auto& val : json_patch)
+        {
+            // wrapper to get a value for an operation
+            const auto get_value = [&val](const std::string & op,
+                                          const std::string & member,
+                                          bool string_type) -> basic_json &
+            {
+                // find value
+                auto it = val.m_value.object->find(member);
+
+                // context-sensitive error message
+                const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
+
+                // check if desired value is present
+                if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
+                {
+                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
+                }
+
+                // check if result is of type string
+                if (JSON_HEDLEY_UNLIKELY(string_type and not it->second.is_string()))
+                {
+                    JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
+                }
+
+                // no error: return value
+                return it->second;
+            };
+
+            // type check: every element of the array must be an object
+            if (JSON_HEDLEY_UNLIKELY(not val.is_object()))
+            {
+                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
+            }
+
+            // collect mandatory members
+            const std::string op = get_value("op", "op", true);
+            const std::string path = get_value(op, "path", true);
+            json_pointer ptr(path);
+
+            switch (get_op(op))
+            {
+                case patch_operations::add:
+                {
+                    operation_add(ptr, get_value("add", "value", false));
+                    break;
+                }
+
+                case patch_operations::remove:
+                {
+                    operation_remove(ptr);
+                    break;
+                }
+
+                case patch_operations::replace:
+                {
+                    // the "path" location must exist - use at()
+                    result.at(ptr) = get_value("replace", "value", false);
+                    break;
+                }
+
+                case patch_operations::move:
+                {
+                    const std::string from_path = get_value("move", "from", true);
+                    json_pointer from_ptr(from_path);
+
+                    // the "from" location must exist - use at()
+                    basic_json v = result.at(from_ptr);
+
+                    // The move operation is functionally identical to a
+                    // "remove" operation on the "from" location, followed
+                    // immediately by an "add" operation at the target
+                    // location with the value that was just removed.
+                    operation_remove(from_ptr);
+                    operation_add(ptr, v);
+                    break;
+                }
+
+                case patch_operations::copy:
+                {
+                    const std::string from_path = get_value("copy", "from", true);
+                    const json_pointer from_ptr(from_path);
+
+                    // the "from" location must exist - use at()
+                    basic_json v = result.at(from_ptr);
+
+                    // The copy is functionally identical to an "add"
+                    // operation at the target location using the value
+                    // specified in the "from" member.
+                    operation_add(ptr, v);
+                    break;
+                }
+
+                case patch_operations::test:
+                {
+                    bool success = false;
+                    JSON_TRY
+                    {
+                        // check if "value" matches the one at "path"
+                        // the "path" location must exist - use at()
+                        success = (result.at(ptr) == get_value("test", "value", false));
+                    }
+                    JSON_INTERNAL_CATCH (out_of_range&)
+                    {
+                        // ignore out of range errors: success remains false
+                    }
+
+                    // throw an exception if test fails
+                    if (JSON_HEDLEY_UNLIKELY(not success))
+                    {
+                        JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
+                    }
+
+                    break;
+                }
+
+                default:
+                {
+                    // op must be "add", "remove", "replace", "move", "copy", or
+                    // "test"
+                    JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /*!
+    @brief creates a diff as a JSON patch
+
+    Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
+    be changed into the value @a target by calling @ref patch function.
+
+    @invariant For two JSON values @a source and @a target, the following code
+    yields always `true`:
+    @code {.cpp}
+    source.patch(diff(source, target)) == target;
+    @endcode
+
+    @note Currently, only `remove`, `add`, and `replace` operations are
+          generated.
+
+    @param[in] source  JSON value to compare from
+    @param[in] target  JSON value to compare against
+    @param[in] path    helper value to create JSON pointers
+
+    @return a JSON patch to convert the @a source to @a target
+
+    @complexity Linear in the lengths of @a source and @a target.
+
+    @liveexample{The following code shows how a JSON patch is created as a
+    diff for two JSON values.,diff}
+
+    @sa @ref patch -- apply a JSON patch
+    @sa @ref merge_patch -- apply a JSON Merge Patch
+
+    @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
+
+    @since version 2.0.0
+    */
+    JSON_HEDLEY_WARN_UNUSED_RESULT
+    static basic_json diff(const basic_json& source, const basic_json& target,
+                           const std::string& path = "")
+    {
+        // the patch
+        basic_json result(value_t::array);
+
+        // if the values are the same, return empty patch
+        if (source == target)
+        {
+            return result;
+        }
+
+        if (source.type() != target.type())
+        {
+            // different types: replace value
+            result.push_back(
+            {
+                {"op", "replace"}, {"path", path}, {"value", target}
+            });
+            return result;
+        }
+
+        switch (source.type())
+        {
+            case value_t::array:
+            {
+                // first pass: traverse common elements
+                std::size_t i = 0;
+                while (i < source.size() and i < target.size())
+                {
+                    // recursive call to compare array values at index i
+                    auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
+                    result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+                    ++i;
+                }
+
+                // i now reached the end of at least one array
+                // in a second pass, traverse the remaining elements
+
+                // remove my remaining elements
+                const auto end_index = static_cast<difference_type>(result.size());
+                while (i < source.size())
+                {
+                    // add operations in reverse order to avoid invalid
+                    // indices
+                    result.insert(result.begin() + end_index, object(
+                    {
+                        {"op", "remove"},
+                        {"path", path + "/" + std::to_string(i)}
+                    }));
+                    ++i;
+                }
+
+                // add other remaining elements
+                while (i < target.size())
+                {
+                    result.push_back(
+                    {
+                        {"op", "add"},
+                        {"path", path + "/" + std::to_string(i)},
+                        {"value", target[i]}
+                    });
+                    ++i;
+                }
+
+                break;
+            }
+
+            case value_t::object:
+            {
+                // first pass: traverse this object's elements
+                for (auto it = source.cbegin(); it != source.cend(); ++it)
+                {
+                    // escape the key name to be used in a JSON patch
+                    const auto key = json_pointer::escape(it.key());
+
+                    if (target.find(it.key()) != target.end())
+                    {
+                        // recursive call to compare object values at key it
+                        auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
+                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+                    }
+                    else
+                    {
+                        // found a key that is not in o -> remove it
+                        result.push_back(object(
+                        {
+                            {"op", "remove"}, {"path", path + "/" + key}
+                        }));
+                    }
+                }
+
+                // second pass: traverse other object's elements
+                for (auto it = target.cbegin(); it != target.cend(); ++it)
+                {
+                    if (source.find(it.key()) == source.end())
+                    {
+                        // found a key that is not in this -> add it
+                        const auto key = json_pointer::escape(it.key());
+                        result.push_back(
+                        {
+                            {"op", "add"}, {"path", path + "/" + key},
+                            {"value", it.value()}
+                        });
+                    }
+                }
+
+                break;
+            }
+
+            default:
+            {
+                // both primitive type: replace value
+                result.push_back(
+                {
+                    {"op", "replace"}, {"path", path}, {"value", target}
+                });
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    /// @}
+
+    ////////////////////////////////
+    // JSON Merge Patch functions //
+    ////////////////////////////////
+
+    /// @name JSON Merge Patch functions
+    /// @{
+
+    /*!
+    @brief applies a JSON Merge Patch
+
+    The merge patch format is primarily intended for use with the HTTP PATCH
+    method as a means of describing a set of modifications to a target
+    resource's content. This function applies a merge patch to the current
+    JSON value.
+
+    The function implements the following algorithm from Section 2 of
+    [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
+
+    ```
+    define MergePatch(Target, Patch):
+      if Patch is an Object:
+        if Target is not an Object:
+          Target = {} // Ignore the contents and set it to an empty Object
+        for each Name/Value pair in Patch:
+          if Value is null:
+            if Name exists in Target:
+              remove the Name/Value pair from Target
+          else:
+            Target[Name] = MergePatch(Target[Name], Value)
+        return Target
+      else:
+        return Patch
+    ```
+
+    Thereby, `Target` is the current object; that is, the patch is applied to
+    the current value.
+
+    @param[in] apply_patch  the patch to apply
+
+    @complexity Linear in the lengths of @a patch.
+
+    @liveexample{The following code shows how a JSON Merge Patch is applied to
+    a JSON document.,merge_patch}
+
+    @sa @ref patch -- apply a JSON patch
+    @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
+
+    @since version 3.0.0
+    */
+    void merge_patch(const basic_json& apply_patch)
+    {
+        if (apply_patch.is_object())
+        {
+            if (not is_object())
+            {
+                *this = object();
+            }
+            for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
+            {
+                if (it.value().is_null())
+                {
+                    erase(it.key());
+                }
+                else
+                {
+                    operator[](it.key()).merge_patch(it.value());
+                }
+            }
+        }
+        else
+        {
+            *this = apply_patch;
+        }
+    }
+
+    /// @}
+};
+
+/*!
+@brief user-defined to_string function for JSON values
+
+This function implements a user-defined to_string  for JSON objects.
+
+@param[in] j  a JSON object
+@return a std::string object
+*/
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
+{
+    return j.dump();
+}
+} // namespace nlohmann
+
+///////////////////////
+// nonmember support //
+///////////////////////
+
+// specialization of std::swap, and std::hash
+namespace std
+{
+
+/// hash value for JSON objects
+template<>
+struct hash<nlohmann::json>
+{
+    /*!
+    @brief return a hash value for a JSON object
+
+    @since version 1.0.0
+    */
+    std::size_t operator()(const nlohmann::json& j) const
+    {
+        // a naive hashing via the string representation
+        const auto& h = hash<nlohmann::json::string_t>();
+        return h(j.dump());
+    }
+};
+
+/// specialization for std::less<value_t>
+/// @note: do not remove the space after '<',
+///        see https://github.com/nlohmann/json/pull/679
+template<>
+struct less<::nlohmann::detail::value_t>
+{
+    /*!
+    @brief compare two value_t enum values
+    @since version 3.0.0
+    */
+    bool operator()(nlohmann::detail::value_t lhs,
+                    nlohmann::detail::value_t rhs) const noexcept
+    {
+        return nlohmann::detail::operator<(lhs, rhs);
+    }
+};
+
+/*!
+@brief exchanges the values of two JSON objects
+
+@since version 1.0.0
+*/
+template<>
+inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
+    is_nothrow_move_constructible<nlohmann::json>::value and
+    is_nothrow_move_assignable<nlohmann::json>::value
+)
+{
+    j1.swap(j2);
+}
+
+} // namespace std
+
+/*!
+@brief user-defined string literal for JSON values
+
+This operator implements a user-defined string literal for JSON objects. It
+can be used by adding `"_json"` to a string literal and returns a JSON object
+if no parse error occurred.
+
+@param[in] s  a string representation of a JSON object
+@param[in] n  the length of string @a s
+@return a JSON object
+
+@since version 1.0.0
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json operator "" _json(const char* s, std::size_t n)
+{
+    return nlohmann::json::parse(s, s + n);
+}
+
+/*!
+@brief user-defined string literal for JSON pointer
+
+This operator implements a user-defined string literal for JSON Pointers. It
+can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
+object if no parse error occurred.
+
+@param[in] s  a string representation of a JSON Pointer
+@param[in] n  the length of string @a s
+@return a JSON pointer object
+
+@since version 2.0.0
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
+{
+    return nlohmann::json::json_pointer(std::string(s, n));
+}
+
+// #include <nlohmann/detail/macro_unscope.hpp>
+
+
+// restore GCC/clang diagnostic settings
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+    #pragma GCC diagnostic pop
+#endif
+#if defined(__clang__)
+    #pragma GCC diagnostic pop
+#endif
+
+// clean up
+#undef JSON_INTERNAL_CATCH
+#undef JSON_CATCH
+#undef JSON_THROW
+#undef JSON_TRY
+#undef JSON_HAS_CPP_14
+#undef JSON_HAS_CPP_17
+#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
+#undef NLOHMANN_BASIC_JSON_TPL
+
+// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
+#undef JSON_HEDLEY_ALWAYS_INLINE
+#undef JSON_HEDLEY_ARM_VERSION
+#undef JSON_HEDLEY_ARM_VERSION_CHECK
+#undef JSON_HEDLEY_ARRAY_PARAM
+#undef JSON_HEDLEY_ASSUME
+#undef JSON_HEDLEY_BEGIN_C_DECLS
+#undef JSON_HEDLEY_C_DECL
+#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#undef JSON_HEDLEY_CLANG_HAS_WARNING
+#undef JSON_HEDLEY_COMPCERT_VERSION
+#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#undef JSON_HEDLEY_CONCAT
+#undef JSON_HEDLEY_CONCAT_EX
+#undef JSON_HEDLEY_CONST
+#undef JSON_HEDLEY_CONST_CAST
+#undef JSON_HEDLEY_CONSTEXPR
+#undef JSON_HEDLEY_CPP_CAST
+#undef JSON_HEDLEY_CRAY_VERSION
+#undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#undef JSON_HEDLEY_DEPRECATED
+#undef JSON_HEDLEY_DEPRECATED_FOR
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#undef JSON_HEDLEY_DIAGNOSTIC_POP
+#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#undef JSON_HEDLEY_DMC_VERSION
+#undef JSON_HEDLEY_DMC_VERSION_CHECK
+#undef JSON_HEDLEY_EMPTY_BASES
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#undef JSON_HEDLEY_END_C_DECLS
+#undef JSON_HEDLEY_FALL_THROUGH
+#undef JSON_HEDLEY_FLAGS
+#undef JSON_HEDLEY_FLAGS_CAST
+#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#undef JSON_HEDLEY_GCC_HAS_FEATURE
+#undef JSON_HEDLEY_GCC_HAS_WARNING
+#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#undef JSON_HEDLEY_GCC_VERSION
+#undef JSON_HEDLEY_GCC_VERSION_CHECK
+#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#undef JSON_HEDLEY_GNUC_HAS_WARNING
+#undef JSON_HEDLEY_GNUC_VERSION
+#undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#undef JSON_HEDLEY_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_BUILTIN
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_EXTENSION
+#undef JSON_HEDLEY_HAS_FEATURE
+#undef JSON_HEDLEY_HAS_WARNING
+#undef JSON_HEDLEY_IAR_VERSION
+#undef JSON_HEDLEY_IAR_VERSION_CHECK
+#undef JSON_HEDLEY_IBM_VERSION
+#undef JSON_HEDLEY_IBM_VERSION_CHECK
+#undef JSON_HEDLEY_IMPORT
+#undef JSON_HEDLEY_INLINE
+#undef JSON_HEDLEY_INTEL_VERSION
+#undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#undef JSON_HEDLEY_IS_CONSTANT
+#undef JSON_HEDLEY_IS_CONSTEXPR_
+#undef JSON_HEDLEY_LIKELY
+#undef JSON_HEDLEY_MALLOC
+#undef JSON_HEDLEY_MESSAGE
+#undef JSON_HEDLEY_MSVC_VERSION
+#undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#undef JSON_HEDLEY_NEVER_INLINE
+#undef JSON_HEDLEY_NO_ESCAPE
+#undef JSON_HEDLEY_NON_NULL
+#undef JSON_HEDLEY_NO_RETURN
+#undef JSON_HEDLEY_NO_THROW
+#undef JSON_HEDLEY_NULL
+#undef JSON_HEDLEY_PELLES_VERSION
+#undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#undef JSON_HEDLEY_PGI_VERSION
+#undef JSON_HEDLEY_PGI_VERSION_CHECK
+#undef JSON_HEDLEY_PREDICT
+#undef JSON_HEDLEY_PRINTF_FORMAT
+#undef JSON_HEDLEY_PRIVATE
+#undef JSON_HEDLEY_PUBLIC
+#undef JSON_HEDLEY_PURE
+#undef JSON_HEDLEY_REINTERPRET_CAST
+#undef JSON_HEDLEY_REQUIRE
+#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#undef JSON_HEDLEY_REQUIRE_MSG
+#undef JSON_HEDLEY_RESTRICT
+#undef JSON_HEDLEY_RETURNS_NON_NULL
+#undef JSON_HEDLEY_SENTINEL
+#undef JSON_HEDLEY_STATIC_ASSERT
+#undef JSON_HEDLEY_STATIC_CAST
+#undef JSON_HEDLEY_STRINGIFY
+#undef JSON_HEDLEY_STRINGIFY_EX
+#undef JSON_HEDLEY_SUNPRO_VERSION
+#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#undef JSON_HEDLEY_TINYC_VERSION
+#undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#undef JSON_HEDLEY_TI_VERSION
+#undef JSON_HEDLEY_TI_VERSION_CHECK
+#undef JSON_HEDLEY_UNAVAILABLE
+#undef JSON_HEDLEY_UNLIKELY
+#undef JSON_HEDLEY_UNPREDICTABLE
+#undef JSON_HEDLEY_UNREACHABLE
+#undef JSON_HEDLEY_UNREACHABLE_RETURN
+#undef JSON_HEDLEY_VERSION
+#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#undef JSON_HEDLEY_VERSION_ENCODE
+#undef JSON_HEDLEY_WARNING
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT
+
+
+
+#endif  // INCLUDE_NLOHMANN_JSON_HPP_
diff --git a/openweathermap.h b/openweathermap.h
index b38da64..9bf6d17 100644
--- a/openweathermap.h
+++ b/openweathermap.h
@@ -5,16 +5,16 @@
 
 #include "Poco/Data/Session.h"
 #include "Poco/Data/SQLite/Connector.h"
-#include <Poco/JSON/JSON.h>
-#include <Poco/JSON/Parser.h>
-#include <Poco/Dynamic/Var.h>
-#include <Poco/URI.h>
-#include <Poco/Net/HTTPClientSession.h>
-#include <Poco/Net/HTTPRequest.h>
-#include <Poco/Net/HTTPResponse.h>
-#include <Poco/StreamCopier.h>
-#include <Poco/Path.h>
-#include <Poco/Exception.h>
+#include "Poco/JSON/JSON.h"
+#include "Poco/JSON/Parser.h"
+#include "Poco/Dynamic/Var.h"
+#include "Poco/URI.h"
+#include "Poco/Net/HTTPClientSession.h"
+#include "Poco/Net/HTTPRequest.h"
+#include "Poco/Net/HTTPResponse.h"
+#include "Poco/StreamCopier.h"
+#include "Poco/Path.h"
+#include "Poco/Exception.h"
 #include "influxdb.h"
 #include "dbSqlite.h"
 #include "json.h"
-- 
GitLab